Added utility classes and methods
Project: http://git-wip-us.apache.org/repos/asf/incubator-hivemall/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hivemall/commit/21a87814 Tree: http://git-wip-us.apache.org/repos/asf/incubator-hivemall/tree/21a87814 Diff: http://git-wip-us.apache.org/repos/asf/incubator-hivemall/diff/21a87814 Branch: refs/heads/master Commit: 21a87814895c9c63479a049387dd53b34cc5c56e Parents: 44528a8 Author: Makoto Yui <m...@apache.org> Authored: Tue Sep 12 19:24:25 2017 +0900 Committer: Makoto Yui <m...@apache.org> Committed: Tue Sep 12 19:24:25 2017 +0900 ---------------------------------------------------------------------- .../collections/maps/BoundedSortedMap.java | 59 ++++++++++ .../hivemall/utils/lang/NaturalComparator.java | 48 ++++++++ .../java/hivemall/utils/lang/StringUtils.java | 17 +++ .../main/java/hivemall/utils/struct/Pair.java | 38 +++++++ .../collections/BoundedPriorityQueueTest.java | 114 +++++++++++++++++++ .../collections/maps/BoundedSortedMapTest.java | 84 ++++++++++++++ 6 files changed, 360 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/21a87814/core/src/main/java/hivemall/utils/collections/maps/BoundedSortedMap.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/hivemall/utils/collections/maps/BoundedSortedMap.java b/core/src/main/java/hivemall/utils/collections/maps/BoundedSortedMap.java new file mode 100644 index 0000000..b1bf806 --- /dev/null +++ b/core/src/main/java/hivemall/utils/collections/maps/BoundedSortedMap.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package hivemall.utils.collections.maps; + +import hivemall.utils.lang.Preconditions; + +import java.util.Collections; +import java.util.Map.Entry; +import java.util.TreeMap; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnegative; +import javax.annotation.Nullable; + +public final class BoundedSortedMap<K, V> extends TreeMap<K, V> { + private static final long serialVersionUID = 4580890152997313541L; + + private final int bound; + + public BoundedSortedMap(@Nonnegative int size) { + this(size, false); + } + + public BoundedSortedMap(@Nonnegative int size, boolean reverseOrder) { + super(reverseOrder ? Collections.reverseOrder() : null); + Preconditions.checkArgument(size > 0, "size must be greater than zero: " + size); + this.bound = size; + } + + @Nullable + public V put(@CheckForNull final K key, @Nullable final V value) { + final V old = super.put(key, value); + if (size() > bound) { + Entry<K, V> e = pollLastEntry(); + if (e == null) { + return null; + } + return e.getValue(); + } + return old; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/21a87814/core/src/main/java/hivemall/utils/lang/NaturalComparator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/hivemall/utils/lang/NaturalComparator.java b/core/src/main/java/hivemall/utils/lang/NaturalComparator.java new file mode 100644 index 0000000..d451f1b --- /dev/null +++ b/core/src/main/java/hivemall/utils/lang/NaturalComparator.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package hivemall.utils.lang; + +import java.util.Comparator; + +import javax.annotation.Nonnull; + +public final class NaturalComparator<T extends Comparable<? super T>> implements Comparator<T> { + + @SuppressWarnings("rawtypes") + private final static NaturalComparator INSTANCE = new NaturalComparator(); + + private NaturalComparator() {}// avoid instantiation + + @Override + public int compare(T o1, T o2) { + return o1.compareTo(o2); + } + + @SuppressWarnings("unchecked") + @Nonnull + public final static <T extends Comparable<? super T>> Comparator<T> getInstance() { + return (Comparator<T>) INSTANCE; + } + + @Nonnull + public final static <T extends Comparable<? super T>> Comparator<T> newInstance() { + return new NaturalComparator<T>(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/21a87814/core/src/main/java/hivemall/utils/lang/StringUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/hivemall/utils/lang/StringUtils.java b/core/src/main/java/hivemall/utils/lang/StringUtils.java index 48e137f..5b66dd1 100644 --- a/core/src/main/java/hivemall/utils/lang/StringUtils.java +++ b/core/src/main/java/hivemall/utils/lang/StringUtils.java @@ -250,5 +250,22 @@ public final class StringUtils { return builder.toString(); } + public static int compare(@Nullable final String o1, @Nullable final String o2) { + return compare(o1, o2, true); + } + + public static int compare(@Nullable final String o1, @Nullable final String o2, + final boolean nullIsLess) { + if (o1 == o2) { + return 0; + } + if (o1 == null) { + return nullIsLess ? -1 : 1; + } + if (o2 == null) { + return nullIsLess ? 1 : -1; + } + return o1.compareTo(o2); + } } http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/21a87814/core/src/main/java/hivemall/utils/struct/Pair.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/hivemall/utils/struct/Pair.java b/core/src/main/java/hivemall/utils/struct/Pair.java new file mode 100644 index 0000000..17737ed --- /dev/null +++ b/core/src/main/java/hivemall/utils/struct/Pair.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package hivemall.utils.struct; + +import java.util.AbstractMap; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class Pair<K, V> extends AbstractMap.SimpleEntry<K, V> { + private static final long serialVersionUID = 6411527075103472113L; + + public Pair(@Nullable K key, @Nullable V value) { + super(key, value); + } + + @Nonnull + public static <K, V> Pair<K, V> of(@Nullable K key, @Nullable V value) { + return new Pair<>(key, value); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/21a87814/core/src/test/java/hivemall/utils/collections/BoundedPriorityQueueTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/hivemall/utils/collections/BoundedPriorityQueueTest.java b/core/src/test/java/hivemall/utils/collections/BoundedPriorityQueueTest.java new file mode 100644 index 0000000..1220d76 --- /dev/null +++ b/core/src/test/java/hivemall/utils/collections/BoundedPriorityQueueTest.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package hivemall.utils.collections; + +import hivemall.utils.lang.NaturalComparator; +import hivemall.utils.lang.StringUtils; + +import java.util.Collections; +import java.util.Comparator; + +import org.junit.Assert; +import org.junit.Test; + +public class BoundedPriorityQueueTest { + + @Test + public void testTop3() { + BoundedPriorityQueue<Integer> queue = new BoundedPriorityQueue<Integer>(3, + new Comparator<Integer>() { + @Override + public int compare(Integer o1, Integer o2) { + return Integer.compare(o1, o2); + } + }); + Assert.assertTrue(queue.offer(1)); + Assert.assertTrue(queue.offer(4)); + Assert.assertTrue(queue.offer(3)); + Assert.assertTrue(queue.offer(2)); + Assert.assertFalse(queue.offer(1)); + Assert.assertTrue(queue.offer(2)); + Assert.assertTrue(queue.offer(3)); + + Assert.assertEquals(3, queue.size()); + + Assert.assertEquals(Integer.valueOf(3), queue.peek()); + Assert.assertEquals(Integer.valueOf(3), queue.poll()); + Assert.assertEquals(Integer.valueOf(3), queue.poll()); + Assert.assertEquals(Integer.valueOf(4), queue.poll()); + Assert.assertNull(queue.poll()); + Assert.assertEquals(0, queue.size()); + } + + @Test + public void testTail3() { + BoundedPriorityQueue<Integer> queue = new BoundedPriorityQueue<Integer>(3, + Collections.<Integer>reverseOrder()); + Assert.assertTrue(queue.offer(1)); + Assert.assertTrue(queue.offer(4)); + Assert.assertTrue(queue.offer(3)); + Assert.assertTrue(queue.offer(2)); + Assert.assertTrue(queue.offer(1)); + Assert.assertTrue(queue.offer(2)); + Assert.assertFalse(queue.offer(3)); + + Assert.assertEquals(3, queue.size()); + + Assert.assertEquals(Integer.valueOf(2), queue.peek()); + Assert.assertEquals(Integer.valueOf(2), queue.poll()); + Assert.assertEquals(Integer.valueOf(1), queue.poll()); + Assert.assertEquals(Integer.valueOf(1), queue.poll()); + Assert.assertNull(queue.poll()); + Assert.assertEquals(0, queue.size()); + } + + @Test + public void testString1() { + BoundedPriorityQueue<String> queue = new BoundedPriorityQueue<>(3, + new Comparator<String>() { + @Override + public int compare(String o1, String o2) { + return StringUtils.compare(o1, o2); + } + }); + queue.offer("B"); + queue.offer("A"); + queue.offer("C"); + queue.offer("D"); + Assert.assertEquals("B", queue.poll()); + Assert.assertEquals("C", queue.poll()); + Assert.assertEquals("D", queue.poll()); + Assert.assertNull(queue.poll()); + } + + @Test + public void testString2() { + BoundedPriorityQueue<String> queue = new BoundedPriorityQueue<>(3, + NaturalComparator.<String>getInstance()); + queue.offer("B"); + queue.offer("A"); + queue.offer("C"); + queue.offer("D"); + Assert.assertEquals("B", queue.poll()); + Assert.assertEquals("C", queue.poll()); + Assert.assertEquals("D", queue.poll()); + Assert.assertNull(queue.poll()); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/21a87814/core/src/test/java/hivemall/utils/collections/maps/BoundedSortedMapTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/hivemall/utils/collections/maps/BoundedSortedMapTest.java b/core/src/test/java/hivemall/utils/collections/maps/BoundedSortedMapTest.java new file mode 100644 index 0000000..ce376cf --- /dev/null +++ b/core/src/test/java/hivemall/utils/collections/maps/BoundedSortedMapTest.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package hivemall.utils.collections.maps; + +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.SortedMap; + +import org.junit.Assert; +import org.junit.Test; + +public class BoundedSortedMapTest { + + @Test + public void testNaturalOrderTop3() { + // natural order = ascending + SortedMap<Integer, Double> map = new BoundedSortedMap<Integer, Double>(3); + Assert.assertNull(map.put(1, 1.d)); + Assert.assertEquals(Double.valueOf(1.d), map.put(1, 1.1d)); + Assert.assertNull(map.put(4, 4.d)); + Assert.assertNull(map.put(2, 2.d)); + Assert.assertEquals(Double.valueOf(2.d), map.put(2, 2.2d)); + Assert.assertEquals(Double.valueOf(4.d), map.put(3, 3.d)); + Assert.assertEquals(Double.valueOf(3.d), map.put(3, 3.3d)); + + Assert.assertEquals(3, map.size()); + + Iterator<Entry<Integer, Double>> itor = map.entrySet().iterator(); + Entry<Integer, Double> e = itor.next(); + Assert.assertEquals(Integer.valueOf(1), e.getKey()); + Assert.assertEquals(Double.valueOf(1.1d), e.getValue()); + e = itor.next(); + Assert.assertEquals(Integer.valueOf(2), e.getKey()); + Assert.assertEquals(Double.valueOf(2.2d), e.getValue()); + e = itor.next(); + Assert.assertEquals(Integer.valueOf(3), e.getKey()); + Assert.assertEquals(Double.valueOf(3.3d), e.getValue()); + Assert.assertFalse(itor.hasNext()); + } + + @Test + public void testReverseOrderTop3() { + // reverse order = descending + SortedMap<Integer, Double> map = new BoundedSortedMap<Integer, Double>(3, true); + Assert.assertNull(map.put(1, 1.d)); + Assert.assertEquals(Double.valueOf(1.d), map.put(1, 1.1d)); + Assert.assertNull(map.put(4, 4.d)); + Assert.assertNull(map.put(2, 2.d)); + Assert.assertEquals(Double.valueOf(2.d), map.put(2, 2.2d)); + Assert.assertEquals(Double.valueOf(1.1d), map.put(3, 3.d)); + Assert.assertEquals(Double.valueOf(3.d), map.put(3, 3.3d)); + + Assert.assertEquals(3, map.size()); + + Iterator<Entry<Integer, Double>> itor = map.entrySet().iterator(); + Entry<Integer, Double> e = itor.next(); + Assert.assertEquals(Integer.valueOf(4), e.getKey()); + Assert.assertEquals(Double.valueOf(4.d), e.getValue()); + e = itor.next(); + Assert.assertEquals(Integer.valueOf(3), e.getKey()); + Assert.assertEquals(Double.valueOf(3.3d), e.getValue()); + e = itor.next(); + Assert.assertEquals(Integer.valueOf(2), e.getKey()); + Assert.assertEquals(Double.valueOf(2.2d), e.getValue()); + Assert.assertFalse(itor.hasNext()); + } + +}