Skip to content
This repository was archived by the owner on Jul 7, 2020. It is now read-only.

Commit 5620c2c

Browse files
committed
Add support for intersection to BloomFilter.
1 parent 7e38ed9 commit 5620c2c

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

src/main/java/com/clearspring/analytics/stream/membership/BloomFilter.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,27 @@ public Filter merge(Filter... filters) {
144144
return merged;
145145
}
146146

147+
public void intersectInPlace(BloomFilter other) {
148+
if (this.getHashCount() != other.getHashCount()) {
149+
throw new IllegalArgumentException("Cannot intersect filters of different sizes");
150+
}
151+
this.filter().and(other.filter());
152+
}
153+
154+
public BloomFilter intersect(BloomFilter... filters) {
155+
BloomFilter intersected = new BloomFilter(this.getHashCount(), (BitSet) this.filter().clone());
156+
157+
if (filters == null) {
158+
return intersected;
159+
}
160+
161+
for (BloomFilter filter : filters) {
162+
intersected.intersectInPlace(filter);
163+
}
164+
165+
return intersected;
166+
}
167+
147168
/**
148169
* @return a BloomFilter that always returns a positive match, for testing
149170
*/

src/test/java/com/clearspring/analytics/stream/membership/BloomFilterTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,54 @@ public void testMergeException() {
8484
BloomFilter mergeBf = (BloomFilter) bf3.merge(bf);
8585
}
8686

87+
@Test
88+
public void testIntersectInPlace() {
89+
BloomFilter bf3 = new BloomFilter(ELEMENTS, spec.bucketsPerElement);
90+
for (int i = 0; i < 20; ++i) {
91+
bf.add(Integer.toString(i));
92+
}
93+
for (int i = 10; i < 30; ++i) {
94+
bf2.add(Integer.toString(i));
95+
}
96+
for (int i = 10; i < 20; ++i) {
97+
bf3.add(Integer.toString(i));
98+
}
99+
bf.intersectInPlace(bf2);
100+
for (int i = 0; i < 30; ++i) {
101+
String iString = Integer.toString(i);
102+
if (bf3.isPresent(iString)) {
103+
assertTrue(bf.isPresent(iString));
104+
} else {
105+
assertFalse(bf.isPresent(iString));
106+
}
107+
}
108+
}
109+
110+
@Test(expected=IllegalArgumentException.class)
111+
public void testIntersectInPlaceException() {
112+
BloomFilter bf3 = new BloomFilter(ELEMENTS*10, 1);
113+
bf3.intersectInPlace(bf);
114+
}
115+
116+
@Test
117+
public void testIntersect() {
118+
for (int i = 0; i < 20; ++i) {
119+
bf.add(Integer.toString(i));
120+
}
121+
for (int i = 10; i < 30; ++i) {
122+
bf2.add(Integer.toString(i));
123+
}
124+
BloomFilter bf3 = bf.intersect(bf2);
125+
for (int i = 0; i < 30; ++i) {
126+
String iString = Integer.toString(i);
127+
if (bf.isPresent(iString) && bf2.isPresent(iString)) {
128+
assertTrue(bf3.isPresent(iString));
129+
} else {
130+
assertFalse(bf3.isPresent(iString));
131+
}
132+
}
133+
}
134+
87135
@Test
88136
public void testFalsePositivesInt() {
89137
FilterTest.testFalsePositives(bf, FilterTest.intKeys(), FilterTest.randomKeys2());

0 commit comments

Comments
 (0)