This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-collections.git
The following commit(s) were added to refs/heads/master by this push: new 5479a7d76 Fix generic typing for BloomFilter.copy() 5479a7d76 is described below commit 5479a7d765a3c5431eef56d90d9767666f39e89c Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Fri Oct 18 18:04:05 2024 -0400 Fix generic typing for BloomFilter.copy() Avoids guaranteed exceptions. For example: SparseBloomFilter filter = new SimpleBloomFilter(Shape.fromNP(10000, 0.01)).copy(); After this commit, this type of broken code won't even compile. --- .../bloomfilter/ArrayCountingBloomFilter.java | 5 ++ .../collections4/bloomfilter/BloomFilter.java | 27 ++++---- .../bloomfilter/BloomFilterExtractor.java | 4 +- .../bloomfilter/CountingBloomFilter.java | 15 ++--- .../collections4/bloomfilter/LayerManager.java | 41 ++++++------ .../bloomfilter/LayeredBloomFilter.java | 22 ++++--- .../collections4/bloomfilter/SetOperations.java | 2 +- .../bloomfilter/SimpleBloomFilter.java | 10 ++- .../bloomfilter/SparseBloomFilter.java | 9 ++- .../bloomfilter/WrappedBloomFilter.java | 19 +++--- .../AbstractBloomFilterExtractorTest.java | 4 +- .../BitMapExtractorFromWrappedBloomFilterTest.java | 10 +-- ...mFilterExtractorFromLayeredBloomFilterTest.java | 8 ++- .../bloomfilter/DefaultBloomFilterTest.java | 10 +-- .../collections4/bloomfilter/LayerManagerTest.java | 54 ++++++++-------- .../bloomfilter/LayeredBloomFilterTest.java | 73 +++++++++++----------- 16 files changed, 171 insertions(+), 142 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/ArrayCountingBloomFilter.java b/src/main/java/org/apache/commons/collections4/bloomfilter/ArrayCountingBloomFilter.java index 0baa3d247..5e308404e 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/ArrayCountingBloomFilter.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/ArrayCountingBloomFilter.java @@ -160,6 +160,11 @@ public final class ArrayCountingBloomFilter implements CountingBloomFilter { return indexExtractor.processIndices(idx -> cells[idx] != 0); } + /** + * Creates a new instance of this {@link ArrayCountingBloomFilter} with the same properties as the current one. + * + * @return a copy of this BloomFilter. + */ @Override public ArrayCountingBloomFilter copy() { return new ArrayCountingBloomFilter(this); diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/BloomFilter.java b/src/main/java/org/apache/commons/collections4/bloomfilter/BloomFilter.java index 0a6e1b38e..6f850c025 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/BloomFilter.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/BloomFilter.java @@ -23,11 +23,13 @@ import java.util.Objects; * <p> * <em>See implementation notes for {@link BitMapExtractor} and {@link IndexExtractor}.</em> * </p> + * + * @param <T> The BloomFilter type. * @see BitMapExtractor * @see IndexExtractor * @since 4.5.0 */ -public interface BloomFilter extends IndexExtractor, BitMapExtractor { +public interface BloomFilter<T extends BloomFilter<T>> extends IndexExtractor, BitMapExtractor { /** * The sparse characteristic used to determine the best method for matching. @@ -84,7 +86,7 @@ public interface BloomFilter extends IndexExtractor, BitMapExtractor { * @param other the other Bloom filter * @return true if all enabled bits in the other filter are enabled in this filter. */ - default boolean contains(final BloomFilter other) { + default boolean contains(final BloomFilter<?> other) { Objects.requireNonNull(other, "other"); return (characteristics() & SPARSE) != 0 ? contains((IndexExtractor) other) : contains((BitMapExtractor) other); } @@ -117,12 +119,11 @@ public interface BloomFilter extends IndexExtractor, BitMapExtractor { boolean contains(IndexExtractor indexExtractor); /** - * Creates a new instance of the BloomFilter with the same properties as the current one. + * Creates a new instance of this {@link BloomFilter} with the same properties as the current one. * - * @param <T> Type of BloomFilter. - * @return a copy of this BloomFilter + * @return a copy of this {@link BloomFilter}. */ - <T extends BloomFilter> T copy(); + T copy(); // update operations @@ -142,7 +143,7 @@ public interface BloomFilter extends IndexExtractor, BitMapExtractor { * @see #estimateN() * @see Shape */ - default int estimateIntersection(final BloomFilter other) { + default int estimateIntersection(final BloomFilter<?> other) { Objects.requireNonNull(other, "other"); final double eThis = getShape().estimateN(cardinality()); final double eOther = getShape().estimateN(other.cardinality()); @@ -157,7 +158,7 @@ public interface BloomFilter extends IndexExtractor, BitMapExtractor { } else if (Double.isInfinite(eOther)) { estimate = Math.round(eThis); } else { - final BloomFilter union = this.copy(); + final T union = this.copy(); union.merge(other); final double eUnion = getShape().estimateN(union.cardinality()); if (Double.isInfinite(eUnion)) { @@ -220,11 +221,11 @@ public interface BloomFilter extends IndexExtractor, BitMapExtractor { * @see #estimateN() * @see Shape */ - default int estimateUnion(final BloomFilter other) { + default int estimateUnion(final BloomFilter<?> other) { Objects.requireNonNull(other, "other"); - final BloomFilter cpy = this.copy(); - cpy.merge(other); - return cpy.estimateN(); + final T copy = this.copy(); + copy.merge(other); + return copy.estimateN(); } /** @@ -290,7 +291,7 @@ public interface BloomFilter extends IndexExtractor, BitMapExtractor { * @param other The bloom filter to merge into this one. * @return true if the merge was successful */ - default boolean merge(final BloomFilter other) { + default boolean merge(final BloomFilter<?> other) { return (characteristics() & SPARSE) != 0 ? merge((IndexExtractor) other) : merge((BitMapExtractor) other); } diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/BloomFilterExtractor.java b/src/main/java/org/apache/commons/collections4/bloomfilter/BloomFilterExtractor.java index 004c2e38f..3fcc0026f 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/BloomFilterExtractor.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/BloomFilterExtractor.java @@ -41,12 +41,14 @@ public interface BloomFilterExtractor { * </ul> * <p><em>All modifications to the Bloom filters are reflected in the original filters</em></p> * + * @param <T> The BloomFilter type. * @param filters The filters to be returned by the extractor. * @return THe BloomFilterExtractor containing the filters. */ - static BloomFilterExtractor fromBloomFilterArray(final BloomFilter... filters) { + static <T extends BloomFilter<T>> BloomFilterExtractor fromBloomFilterArray(final BloomFilter<?>... filters) { Objects.requireNonNull(filters, "filters"); return new BloomFilterExtractor() { + /** * This implementation returns a copy the original array, the contained Bloom filters * are references to the originals, any modifications to them are reflected in the original diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/CountingBloomFilter.java b/src/main/java/org/apache/commons/collections4/bloomfilter/CountingBloomFilter.java index 00e8a6231..60f597fbc 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/CountingBloomFilter.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/CountingBloomFilter.java @@ -54,7 +54,7 @@ import java.util.Objects; * @see CellExtractor * @since 4.5.0 */ -public interface CountingBloomFilter extends BloomFilter, CellExtractor { +public interface CountingBloomFilter extends BloomFilter<CountingBloomFilter>, CellExtractor { // Query Operations @@ -74,13 +74,6 @@ public interface CountingBloomFilter extends BloomFilter, CellExtractor { */ boolean add(CellExtractor other); - /** - * Creates a new instance of the CountingBloomFilter with the same properties as the current one. - * @return a copy of this CountingBloomFilter - */ - @Override - CountingBloomFilter copy(); - /** * Returns the maximum allowable value for a cell count in this Counting filter. * @return the maximum allowable value for a cell count in this Counting filter. @@ -114,7 +107,7 @@ public interface CountingBloomFilter extends BloomFilter, CellExtractor { * @param bloomFilter the Bloom filter the check for. * @return the maximum number of times the Bloom filter could have been inserted. */ - default int getMaxInsert(final BloomFilter bloomFilter) { + default int getMaxInsert(final BloomFilter<?> bloomFilter) { return getMaxInsert((BitMapExtractor) bloomFilter); } @@ -204,7 +197,7 @@ public interface CountingBloomFilter extends BloomFilter, CellExtractor { * @see #add(CellExtractor) */ @Override - default boolean merge(final BloomFilter other) { + default boolean merge(final BloomFilter<?> other) { Objects.requireNonNull(other, "other"); return merge((IndexExtractor) other); } @@ -288,7 +281,7 @@ public interface CountingBloomFilter extends BloomFilter, CellExtractor { * @see #isValid() * @see #subtract(CellExtractor) */ - default boolean remove(final BloomFilter other) { + default boolean remove(final BloomFilter<?> other) { return remove((IndexExtractor) other); } diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/LayerManager.java b/src/main/java/org/apache/commons/collections4/bloomfilter/LayerManager.java index 110a514d1..2afb352b3 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/LayerManager.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/LayerManager.java @@ -53,14 +53,14 @@ import java.util.function.Supplier; * @param <T> the {@link BloomFilter} type. * @since 4.5.0 */ -public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor { +public class LayerManager<T extends BloomFilter<T>> implements BloomFilterExtractor { /** * Builds new instances of {@link LayerManager}. * * @param <T> the {@link BloomFilter} type. */ - public static class Builder<T extends BloomFilter> implements Supplier<LayerManager<T>> { + public static class Builder<T extends BloomFilter<T>> implements Supplier<LayerManager<T>> { private Predicate<LayerManager<T>> extendCheck; private Supplier<T> supplier; @@ -131,7 +131,7 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor * @param <T> Type of BloomFilter. * @return A Consumer suitable for the LayerManager {@code cleanup} parameter. */ - public static <T extends BloomFilter> Consumer<Deque<T>> noCleanup() { + public static <T extends BloomFilter<T>> Consumer<Deque<T>> noCleanup() { return x -> { // empty }; @@ -147,7 +147,7 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor * @return A Consumer suitable for the LayerManager {@code cleanup} parameter. * @throws IllegalArgumentException if {@code maxSize <= 0}. */ - public static <T extends BloomFilter> Consumer<Deque<T>> onMaxSize(final int maxSize) { + public static <T extends BloomFilter<T>> Consumer<Deque<T>> onMaxSize(final int maxSize) { if (maxSize <= 0) { throw new IllegalArgumentException("'maxSize' must be greater than 0"); } @@ -165,7 +165,7 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor * @param <T> Type of BloomFilter. * @return A Consumer suitable for the LayerManager {@code cleanup} parameter. */ - public static <T extends BloomFilter> Consumer<Deque<T>> removeEmptyTarget() { + public static <T extends BloomFilter<T>> Consumer<Deque<T>> removeEmptyTarget() { return x -> { if (!x.isEmpty() && x.getLast().isEmpty()) { x.removeLast(); @@ -180,7 +180,7 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor * @param test Predicate. * @return A Consumer suitable for the LayerManager {@code cleanup} parameter. */ - public static <T extends BloomFilter> Consumer<Deque<T>> removeIf(final Predicate<? super T> test) { + public static <T extends BloomFilter<T>> Consumer<Deque<T>> removeIf(final Predicate<? super T> test) { return x -> x.removeIf(test); } @@ -202,7 +202,7 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor * @return A Predicate suitable for the LayerManager {@code extendCheck} parameter. * @throws IllegalArgumentException if {@code breakAt <= 0} */ - public static <T extends BloomFilter> Predicate<LayerManager<T>> advanceOnCount(final int breakAt) { + public static <T extends BloomFilter<T>> Predicate<LayerManager<T>> advanceOnCount(final int breakAt) { if (breakAt <= 0) { throw new IllegalArgumentException("'breakAt' must be greater than 0"); } @@ -226,7 +226,7 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor * @param <T> Type of BloomFilter. * @return A Predicate suitable for the LayerManager {@code extendCheck} parameter. */ - public static <T extends BloomFilter> Predicate<LayerManager<T>> advanceOnPopulated() { + public static <T extends BloomFilter<T>> Predicate<LayerManager<T>> advanceOnPopulated() { return lm -> !lm.last().isEmpty(); } @@ -242,12 +242,12 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor * @return A Predicate suitable for the LayerManager {@code extendCheck} parameter. * @throws IllegalArgumentException if {@code maxN <= 0} */ - public static <T extends BloomFilter> Predicate<LayerManager<T>> advanceOnSaturation(final double maxN) { + public static <T extends BloomFilter<T>> Predicate<LayerManager<T>> advanceOnSaturation(final double maxN) { if (maxN <= 0) { throw new IllegalArgumentException("'maxN' must be greater than 0"); } return manager -> { - final BloomFilter bf = manager.last(); + final T bf = manager.last(); return maxN <= bf.getShape().estimateN(bf.cardinality()); }; } @@ -259,13 +259,14 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor * @param <T> Type of BloomFilter. * @return A Predicate suitable for the LayerManager {@code extendCheck} parameter. */ - public static <T extends BloomFilter> Predicate<LayerManager<T>> neverAdvance() { + public static <T extends BloomFilter<T>> Predicate<LayerManager<T>> neverAdvance() { return x -> false; } private ExtendCheck() { } } + /** * Creates a new Builder with defaults of {@code ExtendCheck.neverAdvance()} and * {@code Cleanup.noCleanup()}. @@ -275,7 +276,7 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor * @see ExtendCheck#neverAdvance() * @see Cleanup#noCleanup() */ - public static <T extends BloomFilter> Builder<T> builder() { + public static <T extends BloomFilter<T>> Builder<T> builder() { return new Builder<>(); } @@ -337,13 +338,15 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor } /** - * Creates a deep copy of this LayerManager. - * <p><em>Filters in the copy are deep copies, not references, so changes in the copy - * are NOT reflected in the original.</em></p> - * <p>The {@code filterSupplier}, {@code extendCheck}, and the {@code filterCleanup} are shared between - * the copy and this instance.</p> + * Creates a deep copy of this {@link LayerManager}. + * <p> + * <em>Filters in the copy are deep copies, not references, so changes in the copy are NOT reflected in the original.</em> + * </p> + * <p> + * The {@code filterSupplier}, {@code extendCheck}, and the {@code filterCleanup} are shared between the copy and this instance. + * </p> * - * @return a copy of this layer Manager. + * @return a copy of this {@link LayerManager}. */ public LayerManager<T> copy() { final LayerManager<T> newMgr = new LayerManager<>(filterSupplier, extendCheck, filterCleanup, false); @@ -438,7 +441,7 @@ public class LayerManager<T extends BloomFilter> implements BloomFilterExtractor */ @Override public boolean processBloomFilters(final Predicate<BloomFilter> bloomFilterPredicate) { - for (final BloomFilter bf : filters) { + for (final T bf : filters) { if (!bloomFilterPredicate.test(bf)) { return false; } diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilter.java b/src/main/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilter.java index 9f5e3e4a4..207e0fe73 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilter.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilter.java @@ -59,10 +59,11 @@ import java.util.function.Predicate; * removes them. It also checks it a new layer should be added, and if so adds * it and sets the {@code target} before the operation.</li> * </ul> + * * @param <T> The type of Bloom Filter that is used for the layers. * @since 4.5.0 */ -public class LayeredBloomFilter<T extends BloomFilter> implements BloomFilter, BloomFilterExtractor { +public class LayeredBloomFilter<T extends BloomFilter<T>> implements BloomFilter<LayeredBloomFilter<T>>, BloomFilterExtractor { /** * A class used to locate matching filters across all the layers. */ @@ -70,9 +71,9 @@ public class LayeredBloomFilter<T extends BloomFilter> implements BloomFilter, B int[] result = new int[layerManager.getDepth()]; int bfIdx; int resultIdx; - BloomFilter bf; + BloomFilter<?> bf; - Finder(final BloomFilter bf) { + Finder(final BloomFilter<?> bf) { this.bf = bf; } @@ -180,6 +181,11 @@ public class LayeredBloomFilter<T extends BloomFilter> implements BloomFilter, B return contains(createFilter(indexExtractor)); } + /** + * Creates a new instance of this {@link LayeredBloomFilter} with the same properties as the current one. + * + * @return a copy of this {@link LayeredBloomFilter}. + */ @Override public LayeredBloomFilter<T> copy() { return new LayeredBloomFilter<>(shape, layerManager.copy()); @@ -191,7 +197,7 @@ public class LayeredBloomFilter<T extends BloomFilter> implements BloomFilter, B * @param bitMapExtractor the BitMapExtractor to create the filter from. * @return the BloomFilter. */ - private BloomFilter createFilter(final BitMapExtractor bitMapExtractor) { + private SimpleBloomFilter createFilter(final BitMapExtractor bitMapExtractor) { final SimpleBloomFilter bf = new SimpleBloomFilter(shape); bf.merge(bitMapExtractor); return bf; @@ -203,7 +209,7 @@ public class LayeredBloomFilter<T extends BloomFilter> implements BloomFilter, B * @param hasher the hasher to create the filter from. * @return the BloomFilter. */ - private BloomFilter createFilter(final Hasher hasher) { + private SimpleBloomFilter createFilter(final Hasher hasher) { final SimpleBloomFilter bf = new SimpleBloomFilter(shape); bf.merge(hasher); return bf; @@ -215,7 +221,7 @@ public class LayeredBloomFilter<T extends BloomFilter> implements BloomFilter, B * @param indexExtractor the IndexExtractor to create the filter from. * @return the BloomFilter. */ - private BloomFilter createFilter(final IndexExtractor indexExtractor) { + private SimpleBloomFilter createFilter(final IndexExtractor indexExtractor) { final SimpleBloomFilter bf = new SimpleBloomFilter(shape); bf.merge(indexExtractor); return bf; @@ -289,8 +295,8 @@ public class LayeredBloomFilter<T extends BloomFilter> implements BloomFilter, B * @return the merged bloom filter. */ @Override - public BloomFilter flatten() { - final BloomFilter bf = new SimpleBloomFilter(shape); + public SimpleBloomFilter flatten() { + final SimpleBloomFilter bf = new SimpleBloomFilter(shape); processBloomFilters(bf::merge); return bf; } diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/SetOperations.java b/src/main/java/org/apache/commons/collections4/bloomfilter/SetOperations.java index 85040ff45..5226b35b1 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/SetOperations.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/SetOperations.java @@ -112,7 +112,7 @@ public final class SetOperations { * @param second the second Bloom filter. * @return the Cosine similarity. */ - public static double cosineSimilarity(final BloomFilter first, final BloomFilter second) { + public static double cosineSimilarity(final BloomFilter<?> first, final BloomFilter<?> second) { final int numerator = andCardinality(first, second); // Given that the cardinality is an int then the product as a double will not // overflow, we can use one sqrt: diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/SimpleBloomFilter.java b/src/main/java/org/apache/commons/collections4/bloomfilter/SimpleBloomFilter.java index 1b646d4a5..f98fceeb8 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/SimpleBloomFilter.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/SimpleBloomFilter.java @@ -24,9 +24,10 @@ import java.util.function.LongPredicate; /** * A bloom filter using an array of bit maps to track enabled bits. This is a standard * implementation and should work well for most Bloom filters. + * * @since 4.5.0 */ -public final class SimpleBloomFilter implements BloomFilter { +public final class SimpleBloomFilter implements BloomFilter<SimpleBloomFilter> { /** * The array of bit map longs that defines this Bloom filter. Will be null if the filter is empty. @@ -96,6 +97,11 @@ public final class SimpleBloomFilter implements BloomFilter { return indexExtractor.processIndices(idx -> BitMaps.contains(bitMap, idx)); } + /** + * Creates a new instance of this {@link SimpleBloomFilter} with the same properties as the current one. + * + * @return a copy of this {@link SimpleBloomFilter}. + */ @Override public SimpleBloomFilter copy() { return new SimpleBloomFilter(this); @@ -140,7 +146,7 @@ public final class SimpleBloomFilter implements BloomFilter { } @Override - public boolean merge(final BloomFilter other) { + public boolean merge(final BloomFilter<?> other) { Objects.requireNonNull(other, "other"); if ((other.characteristics() & SPARSE) != 0) { merge((IndexExtractor) other); diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/SparseBloomFilter.java b/src/main/java/org/apache/commons/collections4/bloomfilter/SparseBloomFilter.java index e53a5a2ff..b7f15ddfa 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/SparseBloomFilter.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/SparseBloomFilter.java @@ -26,7 +26,7 @@ import java.util.function.LongPredicate; * implementation and should work well for most low cardinality Bloom filters. * @since 4.5.0 */ -public final class SparseBloomFilter implements BloomFilter { +public final class SparseBloomFilter implements BloomFilter<SparseBloomFilter> { /** * The bitSet that defines this BloomFilter. @@ -98,6 +98,11 @@ public final class SparseBloomFilter implements BloomFilter { return indexExtractor.processIndices(indices::contains); } + /** + * Creates a new instance of this {@link SparseBloomFilter} with the same properties as the current one. + * + * @return a copy of this {@link SparseBloomFilter}. + */ @Override public SparseBloomFilter copy() { return new SparseBloomFilter(this); @@ -120,7 +125,7 @@ public final class SparseBloomFilter implements BloomFilter { } @Override - public boolean merge(final BloomFilter other) { + public boolean merge(final BloomFilter<?> other) { Objects.requireNonNull(other, "other"); final IndexExtractor indexExtractor = (other.characteristics() & SPARSE) != 0 ? (IndexExtractor) other : IndexExtractor.fromBitMapExtractor(other); merge(indexExtractor); diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/WrappedBloomFilter.java b/src/main/java/org/apache/commons/collections4/bloomfilter/WrappedBloomFilter.java index a03ab0e85..9b3d9b629 100644 --- a/src/main/java/org/apache/commons/collections4/bloomfilter/WrappedBloomFilter.java +++ b/src/main/java/org/apache/commons/collections4/bloomfilter/WrappedBloomFilter.java @@ -22,17 +22,20 @@ import java.util.function.LongPredicate; /** * An abstract class to assist in implementing Bloom filter decorators. * + * @param <T> The WrappedBloomFilter type. + * @param <W> The <em>wrapped</em> BloomFilter type. * @since 4.5.0 */ -public abstract class WrappedBloomFilter implements BloomFilter { - private final BloomFilter wrapped; +public abstract class WrappedBloomFilter<T extends WrappedBloomFilter<T, W>, W extends BloomFilter<W>> implements BloomFilter<T> { + + private final W wrapped; /** * Wraps a Bloom filter. The wrapped filter is maintained as a reference * not a copy. Changes in one will be reflected in the other. * @param wrapped The Bloom filter. */ - public WrappedBloomFilter(final BloomFilter wrapped) { + public WrappedBloomFilter(final W wrapped) { this.wrapped = wrapped; } @@ -67,7 +70,7 @@ public abstract class WrappedBloomFilter implements BloomFilter { } @Override - public boolean contains(final BloomFilter other) { + public boolean contains(final BloomFilter<?> other) { return wrapped.contains(other); } @@ -82,7 +85,7 @@ public abstract class WrappedBloomFilter implements BloomFilter { } @Override - public int estimateIntersection(final BloomFilter other) { + public int estimateIntersection(final BloomFilter<?> other) { return wrapped.estimateIntersection(other); } @@ -92,7 +95,7 @@ public abstract class WrappedBloomFilter implements BloomFilter { } @Override - public int estimateUnion(final BloomFilter other) { + public int estimateUnion(final BloomFilter<?> other) { return wrapped.estimateUnion(other); } @@ -106,7 +109,7 @@ public abstract class WrappedBloomFilter implements BloomFilter { * * @return the wrapped BloomFilter. */ - protected BloomFilter getWrapped() { + protected W getWrapped() { return wrapped; } @@ -121,7 +124,7 @@ public abstract class WrappedBloomFilter implements BloomFilter { } @Override - public boolean merge(final BloomFilter other) { + public boolean merge(final BloomFilter<?> other) { return wrapped.merge(other); } diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilterExtractorTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilterExtractorTest.java index 32c7097c2..4f9112e73 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilterExtractorTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilterExtractorTest.java @@ -29,8 +29,8 @@ import org.junit.jupiter.api.Test; public abstract class AbstractBloomFilterExtractorTest { private final Shape shape = Shape.fromKM(17, 72); - BloomFilter one = new SimpleBloomFilter(shape); - BloomFilter two = new SimpleBloomFilter(shape); + SimpleBloomFilter one = new SimpleBloomFilter(shape); + SimpleBloomFilter two = new SimpleBloomFilter(shape); int[] nullCount = { 0, 0 }; int[] equalityCount = { 0 }; BiPredicate<BloomFilter, BloomFilter> counter = (x, y) -> { diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/BitMapExtractorFromWrappedBloomFilterTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/BitMapExtractorFromWrappedBloomFilterTest.java index 4040efb95..0c04e784b 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/BitMapExtractorFromWrappedBloomFilterTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/BitMapExtractorFromWrappedBloomFilterTest.java @@ -24,8 +24,8 @@ public class BitMapExtractorFromWrappedBloomFilterTest extends AbstractBitMapExt protected BitMapExtractor createEmptyExtractor() { return new WrappedBloomFilter(new DefaultBloomFilterTest.SparseDefaultBloomFilter(shape)) { @Override - public BloomFilter copy() { - final BloomFilter result = new DefaultBloomFilterTest.SparseDefaultBloomFilter(shape); + public DefaultBloomFilterTest.SparseDefaultBloomFilter copy() { + final DefaultBloomFilterTest.SparseDefaultBloomFilter result = new DefaultBloomFilterTest.SparseDefaultBloomFilter(shape); result.merge(getWrapped()); return result; } @@ -35,10 +35,10 @@ public class BitMapExtractorFromWrappedBloomFilterTest extends AbstractBitMapExt @Override protected BitMapExtractor createExtractor() { final Hasher hasher = new IncrementingHasher(0, 1); - final BloomFilter bf = new WrappedBloomFilter(new DefaultBloomFilterTest.SparseDefaultBloomFilter(shape)) { + final WrappedBloomFilter bf = new WrappedBloomFilter(new DefaultBloomFilterTest.SparseDefaultBloomFilter(shape)) { @Override - public BloomFilter copy() { - final BloomFilter result = new DefaultBloomFilterTest.SparseDefaultBloomFilter(shape); + public DefaultBloomFilterTest.SparseDefaultBloomFilter copy() { + final DefaultBloomFilterTest.SparseDefaultBloomFilter result = new DefaultBloomFilterTest.SparseDefaultBloomFilter(shape); result.merge(getWrapped()); return result; } diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/BloomFilterExtractorFromLayeredBloomFilterTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/BloomFilterExtractorFromLayeredBloomFilterTest.java index 644dc253a..4d81a49c1 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/BloomFilterExtractorFromLayeredBloomFilterTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/BloomFilterExtractorFromLayeredBloomFilterTest.java @@ -24,13 +24,15 @@ public class BloomFilterExtractorFromLayeredBloomFilterTest extends AbstractBloo @Override protected BloomFilterExtractor createUnderTest(final BloomFilter... filters) { final Builder<SimpleBloomFilter> builder = LayerManager.<SimpleBloomFilter>builder(); - if (!ArrayUtils.isEmpty(filters)) { + final BloomFilter bloomFilter0 = ArrayUtils.get(filters, 0); + final Shape shape0 = bloomFilter0 != null ? bloomFilter0.getShape() : null; + if (shape0 != null) { // Avoid an NPE in test code and let the domain classes decide what to do when there is no supplier set. - builder.setSupplier(() -> new SimpleBloomFilter(filters[0].getShape())); + builder.setSupplier(() -> new SimpleBloomFilter(shape0)); } final LayerManager<SimpleBloomFilter> layerManager = builder.setExtendCheck(LayerManager.ExtendCheck.advanceOnPopulated()) .setCleanup(LayerManager.Cleanup.noCleanup()).get(); - final LayeredBloomFilter underTest = new LayeredBloomFilter(filters[0].getShape(), layerManager); + final LayeredBloomFilter underTest = new LayeredBloomFilter(shape0, layerManager); for (final BloomFilter bf : filters) { underTest.merge(bf); } diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/DefaultBloomFilterTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/DefaultBloomFilterTest.java index 081bc0fbc..0ce88a0ea 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/DefaultBloomFilterTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/DefaultBloomFilterTest.java @@ -30,7 +30,9 @@ import org.junit.jupiter.api.Test; * Tests for the {@link BloomFilter}. */ public class DefaultBloomFilterTest extends AbstractBloomFilterTest<DefaultBloomFilterTest.AbstractDefaultBloomFilter> { - abstract static class AbstractDefaultBloomFilter implements BloomFilter { + + abstract static class AbstractDefaultBloomFilter<T extends AbstractDefaultBloomFilter<T>> implements BloomFilter<T> { + private final Shape shape; protected TreeSet<Integer> indices; @@ -146,7 +148,7 @@ public class DefaultBloomFilterTest extends AbstractBloomFilterTest<DefaultBloom /** * A default implementation of a Sparse bloom filter. */ - public static class SparseDefaultBloomFilter extends AbstractDefaultBloomFilter { + public static class SparseDefaultBloomFilter extends AbstractDefaultBloomFilter<SparseDefaultBloomFilter> { public SparseDefaultBloomFilter(final Shape shape) { super(shape); @@ -158,8 +160,8 @@ public class DefaultBloomFilterTest extends AbstractBloomFilterTest<DefaultBloom } @Override - public AbstractDefaultBloomFilter copy() { - final AbstractDefaultBloomFilter result = new SparseDefaultBloomFilter(getShape()); + public SparseDefaultBloomFilter copy() { + final SparseDefaultBloomFilter result = new SparseDefaultBloomFilter(getShape()); result.indices.addAll(indices); return result; } diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/LayerManagerTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/LayerManagerTest.java index 9aa60ae1c..9ba06459a 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/LayerManagerTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/LayerManagerTest.java @@ -45,8 +45,8 @@ public class LayerManagerTest { @ParameterizedTest @ValueSource(ints = {4, 10, 2, 1}) public void testAdvanceOnCount(final int breakAt) { - final Predicate<LayerManager<BloomFilter>> underTest = LayerManager.ExtendCheck.advanceOnCount(breakAt); - final LayerManager<BloomFilter> layerManager = testingBuilder().get(); + final Predicate<LayerManager<SimpleBloomFilter>> underTest = LayerManager.ExtendCheck.advanceOnCount(breakAt); + final LayerManager<SimpleBloomFilter> layerManager = testingBuilder().get(); for (int i = 0; i < breakAt - 1; i++) { assertFalse(underTest.test(layerManager), "at " + i); layerManager.getTarget().merge(TestingHashers.FROM1); @@ -62,8 +62,8 @@ public class LayerManagerTest { @Test public void testAdvanceOnPopulated() { - final Predicate<LayerManager<BloomFilter>> underTest = LayerManager.ExtendCheck.advanceOnPopulated(); - final LayerManager<BloomFilter> layerManager = testingBuilder().get(); + final Predicate<LayerManager<SimpleBloomFilter>> underTest = LayerManager.ExtendCheck.advanceOnPopulated(); + final LayerManager<SimpleBloomFilter> layerManager = testingBuilder().get(); assertFalse(underTest.test(layerManager)); layerManager.getTarget().merge(TestingHashers.FROM1); assertTrue(underTest.test(layerManager)); @@ -73,8 +73,8 @@ public class LayerManagerTest { public void testAdvanceOnSaturation() { final double maxN = shape.estimateMaxN(); int hashStart = 0; - final Predicate<LayerManager<BloomFilter>> underTest = LayerManager.ExtendCheck.advanceOnSaturation(maxN); - final LayerManager<BloomFilter> layerManager = testingBuilder().get(); + final Predicate<LayerManager<SimpleBloomFilter>> underTest = LayerManager.ExtendCheck.advanceOnSaturation(maxN); + final LayerManager<SimpleBloomFilter> layerManager = testingBuilder().get(); while (layerManager.getTarget().getShape().estimateN(layerManager.getTarget().cardinality()) < maxN) { assertFalse(underTest.test(layerManager)); layerManager.getTarget().merge(new IncrementingHasher(hashStart, shape.getNumberOfHashFunctions())); @@ -87,7 +87,7 @@ public class LayerManagerTest { @Test public void testBuilder() { - final LayerManager.Builder<BloomFilter> underTest = LayerManager.builder(); + final LayerManager.Builder<SimpleBloomFilter> underTest = LayerManager.builder(); NullPointerException npe = assertThrows(NullPointerException.class, underTest::get); assertTrue(npe.getMessage().contains("filterSupplier")); underTest.setSupplier(() -> null).setCleanup(null); @@ -105,7 +105,7 @@ public class LayerManagerTest { @Test public void testClear() { - final LayerManager<BloomFilter> underTest = LayerManager.builder().setSupplier(() -> new SimpleBloomFilter(shape)).get(); + final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(shape)).get(); underTest.getTarget().merge(TestingHashers.randomHasher()); underTest.next(); underTest.getTarget().merge(TestingHashers.randomHasher()); @@ -119,7 +119,7 @@ public class LayerManagerTest { @Test public void testCopy() { - final LayerManager<BloomFilter> underTest = LayerManager.builder().setSupplier(() -> new SimpleBloomFilter(shape)).get(); + final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(shape)).get(); underTest.getTarget().merge(TestingHashers.randomHasher()); underTest.next(); underTest.getTarget().merge(TestingHashers.randomHasher()); @@ -127,7 +127,7 @@ public class LayerManagerTest { underTest.getTarget().merge(TestingHashers.randomHasher()); assertEquals(3, underTest.getDepth()); - final LayerManager<BloomFilter> copy = underTest.copy(); + final LayerManager<SimpleBloomFilter> copy = underTest.copy(); assertNotSame(underTest, copy); // object equals not implemented assertNotEquals(underTest, copy); @@ -139,12 +139,12 @@ public class LayerManagerTest { @Test public void testForEachBloomFilter() { - final LayerManager<BloomFilter> underTest = LayerManager.builder().setSupplier(() -> new SimpleBloomFilter(shape)) + final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(shape)) .setExtendCheck(LayerManager.ExtendCheck.advanceOnPopulated()).get(); - final List<BloomFilter> lst = new ArrayList<>(); + final List<SimpleBloomFilter> lst = new ArrayList<>(); for (int i = 0; i < 10; i++) { - final BloomFilter bf = new SimpleBloomFilter(shape); + final SimpleBloomFilter bf = new SimpleBloomFilter(shape); bf.merge(TestingHashers.randomHasher()); lst.add(bf); underTest.getTarget().merge(bf); @@ -161,21 +161,21 @@ public class LayerManagerTest { @Test public void testGet() { final SimpleBloomFilter f = new SimpleBloomFilter(shape); - final LayerManager<BloomFilter> underTest = LayerManager.builder().setSupplier(() -> f).get(); + final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> f).get(); assertEquals(1, underTest.getDepth()); assertSame(f, underTest.get(0)); assertThrows(NoSuchElementException.class, () -> underTest.get(-1)); assertThrows(NoSuchElementException.class, () -> underTest.get(1)); } - private LayerManager.Builder<BloomFilter> testingBuilder() { - return LayerManager.builder().setSupplier(() -> new SimpleBloomFilter(shape)); + private LayerManager.Builder<SimpleBloomFilter> testingBuilder() { + return LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(shape)); } @Test public void testNeverAdvance() { - final Predicate<LayerManager<BloomFilter>> underTest = LayerManager.ExtendCheck.neverAdvance(); - final LayerManager<BloomFilter> layerManager = testingBuilder().get(); + final Predicate<LayerManager<SimpleBloomFilter>> underTest = LayerManager.ExtendCheck.neverAdvance(); + final LayerManager<SimpleBloomFilter> layerManager = testingBuilder().get(); assertFalse(underTest.test(layerManager)); for (int i = 0; i < 10; i++) { layerManager.getTarget().merge(TestingHashers.randomHasher()); @@ -185,7 +185,7 @@ public class LayerManagerTest { @Test public void testNextAndGetDepth() { - final LayerManager<BloomFilter> underTest = LayerManager.builder().setSupplier(() -> new SimpleBloomFilter(shape)).get(); + final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(shape)).get(); assertEquals(1, underTest.getDepth()); underTest.getTarget().merge(TestingHashers.randomHasher()); assertEquals(1, underTest.getDepth()); @@ -195,8 +195,8 @@ public class LayerManagerTest { @Test public void testNoCleanup() { - final Consumer<Deque<BloomFilter>> underTest = LayerManager.Cleanup.noCleanup(); - final Deque<BloomFilter> list = new LinkedList<>(); + final Consumer<Deque<SimpleBloomFilter>> underTest = LayerManager.Cleanup.noCleanup(); + final Deque<SimpleBloomFilter> list = new LinkedList<>(); for (int i = 0; i < 20; i++) { assertEquals(i, list.size()); list.add(new SimpleBloomFilter(shape)); @@ -207,8 +207,8 @@ public class LayerManagerTest { @ParameterizedTest @ValueSource(ints = {5, 100, 2, 1}) public void testOnMaxSize(final int maxSize) { - final Consumer<Deque<BloomFilter>> underTest = LayerManager.Cleanup.onMaxSize(maxSize); - final LinkedList<BloomFilter> list = new LinkedList<>(); + final Consumer<Deque<SimpleBloomFilter>> underTest = LayerManager.Cleanup.onMaxSize(maxSize); + final LinkedList<SimpleBloomFilter> list = new LinkedList<>(); for (int i = 0; i < maxSize; i++) { assertEquals(i, list.size()); list.add(new SimpleBloomFilter(shape)); @@ -231,11 +231,11 @@ public class LayerManagerTest { @Test public void testRemoveEmptyTarget() { - final Consumer<Deque<BloomFilter>> underTest = LayerManager.Cleanup.removeEmptyTarget(); - final LinkedList<BloomFilter> list = new LinkedList<>(); + final Consumer<Deque<SimpleBloomFilter>> underTest = LayerManager.Cleanup.removeEmptyTarget(); + final LinkedList<SimpleBloomFilter> list = new LinkedList<>(); // removes an empty filter - final BloomFilter bf = new SimpleBloomFilter(shape); + final SimpleBloomFilter bf = new SimpleBloomFilter(shape); list.add(bf); assertEquals(bf, list.get(0)); underTest.accept(list); @@ -273,7 +273,7 @@ public class LayerManagerTest { final boolean[] extendCheckCalled = { false }; final boolean[] cleanupCalled = { false }; final int[] supplierCount = { 0 }; - final LayerManager<BloomFilter> underTest = LayerManager.builder().setSupplier(() -> { + final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> { supplierCount[0]++; return new SimpleBloomFilter(shape); }).setExtendCheck(lm -> { diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilterTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilterTest.java index 270e139d5..c84bf88a0 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilterTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/LayeredBloomFilterTest.java @@ -40,7 +40,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom /** * A Predicate that advances after a quantum of time. */ - static class AdvanceOnTimeQuanta implements Predicate<LayerManager<TimestampedBloomFilter>> { + static class AdvanceOnTimeQuanta<T extends BloomFilter<T>> implements Predicate<LayerManager<TimestampedBloomFilter<T>>> { Duration quanta; AdvanceOnTimeQuanta(final Duration quanta) { @@ -48,7 +48,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom } @Override - public boolean test(final LayerManager<TimestampedBloomFilter> layerManager) { + public boolean test(final LayerManager<TimestampedBloomFilter<T>> layerManager) { // can not use getTarget() as it causes recursion. return layerManager.last().getTimestamp().plus(quanta).isBefore(Instant.now()); } @@ -80,9 +80,11 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom } } - static class NumberedBloomFilter extends WrappedBloomFilter { + static class NumberedBloomFilter extends WrappedBloomFilter<NumberedBloomFilter, SimpleBloomFilter> { + int value; int sequence; + NumberedBloomFilter(final Shape shape, final int value, final int sequence) { super(new SimpleBloomFilter(shape)); this.value = value; @@ -90,7 +92,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom } @Override - public BloomFilter copy() { + public NumberedBloomFilter copy() { return new NumberedBloomFilter(getShape(), value, sequence); } } @@ -98,22 +100,22 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom /** * A Bloom filter implementation that tracks the creation time. */ - public static class TimestampedBloomFilter extends WrappedBloomFilter { + public static class TimestampedBloomFilter<T extends BloomFilter<T>> extends WrappedBloomFilter<TimestampedBloomFilter<T>, T> { private final Instant timestamp; - TimestampedBloomFilter(final BloomFilter bf) { + TimestampedBloomFilter(final T bf) { this(bf, Instant.now()); } - TimestampedBloomFilter(final BloomFilter bf, final Instant timestamp) { + TimestampedBloomFilter(final T bf, final Instant timestamp) { super(bf); this.timestamp = timestamp; } @Override - public TimestampedBloomFilter copy() { - return new TimestampedBloomFilter(getWrapped().copy(), timestamp); + public TimestampedBloomFilter<T> copy() { + return new TimestampedBloomFilter<>(getWrapped().copy(), timestamp); } public Instant getTimestamp() { @@ -135,11 +137,11 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom * will span at most this much time. * @return LayeredBloomFilter with the above properties. */ - static LayeredBloomFilter<TimestampedBloomFilter> createTimedLayeredFilter(final Shape shape, final Duration duration, final Duration quanta) { - final LayerManager.Builder<TimestampedBloomFilter> builder = LayerManager.builder(); - final Consumer<Deque<TimestampedBloomFilter>> cleanup = Cleanup.removeEmptyTarget().andThen(new CleanByTime(duration)); - final LayerManager<TimestampedBloomFilter> layerManager = builder - .setSupplier(() -> new TimestampedBloomFilter(new SimpleBloomFilter(shape))) + static LayeredBloomFilter<TimestampedBloomFilter<SimpleBloomFilter>> createTimedLayeredFilter(final Shape shape, final Duration duration, final Duration quanta) { + final LayerManager.Builder<TimestampedBloomFilter<SimpleBloomFilter>> builder = LayerManager.builder(); + final Consumer<Deque<TimestampedBloomFilter<SimpleBloomFilter>>> cleanup = Cleanup.removeEmptyTarget().andThen(new CleanByTime(duration)); + final LayerManager<TimestampedBloomFilter<SimpleBloomFilter>> layerManager = builder + .setSupplier(() -> new TimestampedBloomFilter<>(new SimpleBloomFilter(shape))) .setCleanup(cleanup) .setExtendCheck(new AdvanceOnTimeQuanta(quanta) .or(LayerManager.ExtendCheck.advanceOnSaturation(shape.estimateMaxN()))) @@ -156,7 +158,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom * @param maxDepth The maximum depth of layers. * @return An empty layered Bloom filter of the specified shape and depth. */ - public static LayeredBloomFilter<BloomFilter> fixed(final Shape shape, final int maxDepth) { + public static LayeredBloomFilter<SimpleBloomFilter> fixed(final Shape shape, final int maxDepth) { return fixed(shape, maxDepth, () -> new SimpleBloomFilter(shape)); } @@ -170,7 +172,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom * @param supplier A supplier of the Bloom filters to create layers with. * @return An empty layered Bloom filter of the specified shape and depth. */ - public static <T extends BloomFilter> LayeredBloomFilter<T> fixed(final Shape shape, final int maxDepth, final Supplier<T> supplier) { + public static <T extends BloomFilter<T>> LayeredBloomFilter<T> fixed(final Shape shape, final int maxDepth, final Supplier<T> supplier) { final LayerManager.Builder<T> builder = LayerManager.builder(); builder.setExtendCheck(LayerManager.ExtendCheck.advanceOnPopulated()) .setCleanup(LayerManager.Cleanup.onMaxSize(maxDepth)).setSupplier(supplier); @@ -188,7 +190,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom // *** end of instrumentation *** @Override - protected LayeredBloomFilter<BloomFilter> createEmptyFilter(final Shape shape) { + protected LayeredBloomFilter<SimpleBloomFilter> createEmptyFilter(final Shape shape) { return LayeredBloomFilterTest.fixed(shape, 10); } @@ -208,8 +210,8 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom return makeFilter(IndexExtractor.fromIndexArray(values)); } - private LayeredBloomFilter<BloomFilter> setupFindTest() { - final LayeredBloomFilter<BloomFilter> filter = LayeredBloomFilterTest.fixed(getTestShape(), 10); + private LayeredBloomFilter<SimpleBloomFilter> setupFindTest() { + final LayeredBloomFilter<SimpleBloomFilter> filter = LayeredBloomFilterTest.fixed(getTestShape(), 10); filter.merge(TestingHashers.FROM1); filter.merge(TestingHashers.FROM11); filter.merge(new IncrementingHasher(11, 2)); @@ -220,7 +222,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom @Override @Test public void testCardinalityAndIsEmpty() { - final LayerManager<BloomFilter> layerManager = LayerManager.builder().setExtendCheck(ExtendCheck.neverAdvance()) + final LayerManager<SimpleBloomFilter> layerManager = LayerManager.<SimpleBloomFilter>builder().setExtendCheck(ExtendCheck.neverAdvance()) .setSupplier(() -> new SimpleBloomFilter(getTestShape())).get(); testCardinalityAndIsEmpty(new LayeredBloomFilter<>(getTestShape(), layerManager)); } @@ -230,11 +232,11 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom @Test public void testCleanup() { final int[] sequence = {1}; - final LayerManager layerManager = LayerManager.builder() + final LayerManager<NumberedBloomFilter> layerManager = LayerManager.<NumberedBloomFilter>builder() .setSupplier(() -> new NumberedBloomFilter(getTestShape(), 3, sequence[0]++)) .setExtendCheck(ExtendCheck.neverAdvance()) - .setCleanup(ll -> ll.removeIf(f -> (((NumberedBloomFilter) f).value-- == 0))).get(); - final LayeredBloomFilter underTest = new LayeredBloomFilter(getTestShape(), layerManager); + .setCleanup(ll -> ll.removeIf(f -> (f.value-- == 0))).get(); + final LayeredBloomFilter<NumberedBloomFilter> underTest = new LayeredBloomFilter<>(getTestShape(), layerManager); assertEquals(1, underTest.getDepth()); underTest.merge(TestingHashers.randomHasher()); underTest.cleanup(); // first count == 2 @@ -243,19 +245,19 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom assertEquals(2, underTest.getDepth()); underTest.merge(TestingHashers.randomHasher()); underTest.cleanup(); // first count == 0 - NumberedBloomFilter f = (NumberedBloomFilter) underTest.get(0); + NumberedBloomFilter f = underTest.get(0); assertEquals(1, f.sequence); assertEquals(2, underTest.getDepth()); underTest.cleanup(); // should be removed ; second is now 1st with value 1 assertEquals(1, underTest.getDepth()); - f = (NumberedBloomFilter) underTest.get(0); + f = underTest.get(0); assertEquals(2, f.sequence); underTest.cleanup(); // first count == 0 underTest.cleanup(); // should be removed. But there is always at least one assertEquals(1, underTest.getDepth()); - f = (NumberedBloomFilter) underTest.get(0); + f = underTest.get(0); assertEquals(3, f.sequence); // it is a new one. } /** @@ -282,7 +284,8 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom // create a filter that removes filters that are 4 seconds old // and quantises time to 1 second intervals. - final LayeredBloomFilter<TimestampedBloomFilter> underTest = createTimedLayeredFilter(shape, Duration.ofMillis(600), Duration.ofMillis(150)); + final LayeredBloomFilter<TimestampedBloomFilter<SimpleBloomFilter>> underTest = createTimedLayeredFilter(shape, Duration.ofMillis(600), + Duration.ofMillis(150)); for (int i = 0; i < 10; i++) { underTest.merge(TestingHashers.randomHasher()); @@ -314,7 +317,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom @Test public void testFindBitMapExtractor() { - final LayeredBloomFilter<BloomFilter> filter = setupFindTest(); + final LayeredBloomFilter<SimpleBloomFilter> filter = setupFindTest(); IndexExtractor indexExtractor = TestingHashers.FROM1.indices(getTestShape()); BitMapExtractor bitMapExtractor = BitMapExtractor.fromIndexExtractor(indexExtractor, getTestShape().getNumberOfBits()); @@ -332,7 +335,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom @Test public void testFindBloomFilter() { - final LayeredBloomFilter<BloomFilter> filter = setupFindTest(); + final LayeredBloomFilter<SimpleBloomFilter> filter = setupFindTest(); int[] expected = {0, 3}; int[] result = filter.find(TestingHashers.FROM1); assertArrayEquals(expected, result); @@ -344,7 +347,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom @Test public void testFindIndexExtractor() { IndexExtractor indexExtractor = TestingHashers.FROM1.indices(getTestShape()); - final LayeredBloomFilter<BloomFilter> filter = setupFindTest(); + final LayeredBloomFilter<SimpleBloomFilter> filter = setupFindTest(); int[] expected = {0, 3}; int[] result = filter.find(indexExtractor); @@ -360,7 +363,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom public final void testGetLayer() { final BloomFilter bf = new SimpleBloomFilter(getTestShape()); bf.merge(TestingHashers.FROM11); - final LayeredBloomFilter<BloomFilter> filter = LayeredBloomFilterTest.fixed(getTestShape(), 10); + final LayeredBloomFilter<SimpleBloomFilter> filter = LayeredBloomFilterTest.fixed(getTestShape(), 10); filter.merge(TestingHashers.FROM1); filter.merge(TestingHashers.FROM11); filter.merge(new IncrementingHasher(11, 2)); @@ -370,7 +373,7 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom @Test public void testMultipleFilters() { - final LayeredBloomFilter<BloomFilter> filter = LayeredBloomFilterTest.fixed(getTestShape(), 10); + final LayeredBloomFilter<SimpleBloomFilter> filter = LayeredBloomFilterTest.fixed(getTestShape(), 10); filter.merge(TestingHashers.FROM1); filter.merge(TestingHashers.FROM11); assertEquals(2, filter.getDepth()); @@ -384,10 +387,8 @@ public class LayeredBloomFilterTest extends AbstractBloomFilterTest<LayeredBloom @Test public final void testNext() { - final LayerManager<BloomFilter> layerManager = LayerManager.builder().setSupplier(() -> new SimpleBloomFilter(getTestShape())) - .get(); - - final LayeredBloomFilter<BloomFilter> filter = new LayeredBloomFilter<>(getTestShape(), layerManager); + final LayerManager<SimpleBloomFilter> layerManager = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(getTestShape())).get(); + final LayeredBloomFilter<SimpleBloomFilter> filter = new LayeredBloomFilter<>(getTestShape(), layerManager); filter.merge(TestingHashers.FROM1); filter.merge(TestingHashers.FROM11); assertEquals(1, filter.getDepth());