From 28ccc0645c4a0d0c50128fadbaccec051b8e556e Mon Sep 17 00:00:00 2001 From: al Date: Fri, 9 Jun 2017 00:16:19 -0400 Subject: [PATCH 1/3] Add intersect method to bloom filter --- .../stream/membership/BloomFilter.java | 17 +++++++++++++++++ .../stream/membership/BloomFilterTest.java | 12 ++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/main/java/com/clearspring/analytics/stream/membership/BloomFilter.java b/src/main/java/com/clearspring/analytics/stream/membership/BloomFilter.java index a374b088a..eeb8995ad 100644 --- a/src/main/java/com/clearspring/analytics/stream/membership/BloomFilter.java +++ b/src/main/java/com/clearspring/analytics/stream/membership/BloomFilter.java @@ -144,6 +144,23 @@ public Filter merge(Filter... filters) { return merged; } + /** + * Intersect a Bloom Filter with a number of other bloom filters. + * @param filters + * @return a new Bloom Filter that has each filter bit set if and only if all the input bloom filters had that bit set + */ + public Filter intersect(Filter... filters) { + BitSet intersection = (BitSet) this.filter().clone(); + BloomFilter intersectionBloomFilter = new BloomFilter(this.getHashCount(), intersection); + for (Filter otherFilter : filters) { + if (!(otherFilter instanceof BloomFilter || this.hashCount != otherFilter.hashCount)) { + throw new IllegalArgumentException(("Cannot merge filters of different class or size")); + } + intersection.and(((BloomFilter) otherFilter).filter()); + } + return intersectionBloomFilter; + } + /** * @return a BloomFilter that always returns a positive match, for testing */ diff --git a/src/test/java/com/clearspring/analytics/stream/membership/BloomFilterTest.java b/src/test/java/com/clearspring/analytics/stream/membership/BloomFilterTest.java index 178d53c6a..04734c89f 100644 --- a/src/test/java/com/clearspring/analytics/stream/membership/BloomFilterTest.java +++ b/src/test/java/com/clearspring/analytics/stream/membership/BloomFilterTest.java @@ -76,6 +76,18 @@ public void testMerge() { assertTrue(mergeBf.isPresent("c")); } + @Test + public void testIntersect() { + bf.add("a"); + bf.add("b"); + bf2.add("a"); + bf2.add("c"); + BloomFilter intersectionBf = (BloomFilter) bf.intersect(bf2); + assertTrue(intersectionBf.isPresent("a")); + assertFalse(intersectionBf.isPresent("b")); + assertFalse(intersectionBf.isPresent("c")); + } + @Test(expected=IllegalArgumentException.class) public void testMergeException() { BloomFilter bf3 = new BloomFilter(ELEMENTS*10, 1); From 6e557c8f14ee4ab53a23c9c55db28c68467be381 Mon Sep 17 00:00:00 2001 From: al Date: Fri, 9 Jun 2017 00:26:11 -0400 Subject: [PATCH 2/3] Minor tweak - ensure unit test blooms are reset with each test --- .../clearspring/analytics/stream/membership/BloomFilterTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/clearspring/analytics/stream/membership/BloomFilterTest.java b/src/test/java/com/clearspring/analytics/stream/membership/BloomFilterTest.java index 04734c89f..59a59a1b6 100644 --- a/src/test/java/com/clearspring/analytics/stream/membership/BloomFilterTest.java +++ b/src/test/java/com/clearspring/analytics/stream/membership/BloomFilterTest.java @@ -55,6 +55,7 @@ public BloomFilterTest() { @Before public void clear() { bf.clear(); + bf2.clear(); } @Test From 3c4978311594ea3fc9ea016efb56f0c8c3915da0 Mon Sep 17 00:00:00 2001 From: al Date: Fri, 9 Jun 2017 00:29:04 -0400 Subject: [PATCH 3/3] Fix bloom filter compatibility check --- .../clearspring/analytics/stream/membership/BloomFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/clearspring/analytics/stream/membership/BloomFilter.java b/src/main/java/com/clearspring/analytics/stream/membership/BloomFilter.java index eeb8995ad..9fc5561ab 100644 --- a/src/main/java/com/clearspring/analytics/stream/membership/BloomFilter.java +++ b/src/main/java/com/clearspring/analytics/stream/membership/BloomFilter.java @@ -153,7 +153,7 @@ public Filter intersect(Filter... filters) { BitSet intersection = (BitSet) this.filter().clone(); BloomFilter intersectionBloomFilter = new BloomFilter(this.getHashCount(), intersection); for (Filter otherFilter : filters) { - if (!(otherFilter instanceof BloomFilter || this.hashCount != otherFilter.hashCount)) { + if (!(otherFilter instanceof BloomFilter) || this.hashCount != otherFilter.hashCount) { throw new IllegalArgumentException(("Cannot merge filters of different class or size")); } intersection.and(((BloomFilter) otherFilter).filter());