You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2020/02/18 16:36:31 UTC

[commons-collections] 01/06: Update DynamicHasher to have a specialised iterator when empty.

This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git

commit 66b418f3e9df348d784398d33d406ccedc08cd83
Author: aherbert <a....@sussex.ac.uk>
AuthorDate: Tue Feb 18 12:39:11 2020 +0000

    Update DynamicHasher to have a specialised iterator when empty.
    
    Add tests to exercise the empty and non-empty iterators and their
    expected exceptions when no more elements.
---
 .../bloomfilter/hasher/DynamicHasher.java          | 30 +++++++++++++++++++---
 .../bloomfilter/hasher/DynamicHasherTest.java      | 21 +++++++++++++--
 2 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/hasher/DynamicHasher.java b/src/main/java/org/apache/commons/collections4/bloomfilter/hasher/DynamicHasher.java
index 56be62b..f3d10a4 100644
--- a/src/main/java/org/apache/commons/collections4/bloomfilter/hasher/DynamicHasher.java
+++ b/src/main/java/org/apache/commons/collections4/bloomfilter/hasher/DynamicHasher.java
@@ -102,9 +102,7 @@ public class DynamicHasher implements Hasher {
 
         @Override
         public boolean hasNext() {
-            if (buffers.isEmpty()) {
-                return false;
-            }
+            // Note: This iterator is only used when buffers.size() is not zero
             return buffer < buffers.size() - 1 || funcCount < shape.getNumberOfHashFunctions();
         }
 
@@ -124,6 +122,29 @@ public class DynamicHasher implements Hasher {
     }
 
     /**
+     * An iterator of integers to use then there are no values.
+     */
+    private static class NoValuesIterator implements PrimitiveIterator.OfInt {
+        /** The singleton instance. */
+        private static final NoValuesIterator INSTANCE = new NoValuesIterator();
+
+        /**
+         * Empty constructor.
+         */
+        private NoValuesIterator() {}
+
+        @Override
+        public boolean hasNext() {
+            return false;
+        }
+
+        @Override
+        public int nextInt() {
+            throw new NoSuchElementException();
+        }
+    }
+
+    /**
      * The list of byte arrays that are to be hashed.
      */
     private final List<byte[]> buffers;
@@ -163,7 +184,8 @@ public class DynamicHasher implements Hasher {
                     HashFunctionIdentity.asCommonString(shape.getHashFunctionIdentity()),
                     HashFunctionIdentity.asCommonString(getHashFunctionIdentity())));
         }
-        return new Iterator(shape);
+        // Use optimised iterator for no values
+        return buffers.isEmpty() ? NoValuesIterator.INSTANCE : new Iterator(shape);
     }
 
     @Override
diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/hasher/DynamicHasherTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/hasher/DynamicHasherTest.java
index 3babbb7..862136a 100644
--- a/src/test/java/org/apache/commons/collections4/bloomfilter/hasher/DynamicHasherTest.java
+++ b/src/test/java/org/apache/commons/collections4/bloomfilter/hasher/DynamicHasherTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.util.NoSuchElementException;
 import java.util.PrimitiveIterator.OfInt;
 
 import org.apache.commons.collections4.bloomfilter.hasher.function.MD5Cyclic;
@@ -108,6 +109,12 @@ public class DynamicHasherTest {
             assertEquals(element, iter.nextInt());
         }
         assertFalse(iter.hasNext());
+        try {
+            iter.next();
+            fail("Should have thown NoSuchElementException");
+        } catch (final NoSuchElementException ignore) {
+            // do nothing
+        }
     }
 
     /**
@@ -127,11 +134,21 @@ public class DynamicHasherTest {
     }
 
     /**
-     * Tests if isEmpty() reports correctly.
+     * Tests if isEmpty() reports correctly and the iterator returns no values.
      */
     @Test
     public void testIsEmpty() {
-        assertTrue(builder.build().isEmpty());
+        DynamicHasher hasher = builder.build();
+        assertTrue(hasher.isEmpty());
+        final OfInt iter = hasher.getBits(shape);
+        assertFalse(iter.hasNext());
+        try {
+            iter.next();
+            fail("Should have thown NoSuchElementException");
+        } catch (final NoSuchElementException expected) {
+            // do nothing
+        }
+
         assertFalse(builder.with("Hello").build().isEmpty());
     }
 }