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/27 20:48:19 UTC
[commons-collections] 01/03: Update the AbstractBloomFilter to not
use BitSet for cardinality.
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 9a496dc61cee95257b3a266a4d52138bea7f7e9a
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Mon Feb 24 23:01:39 2020 +0000
Update the AbstractBloomFilter to not use BitSet for cardinality.
The cardinality can be performed without memory allocation using
Long.bitCount.
---
.../bloomfilter/AbstractBloomFilter.java | 78 +++++++++++-----------
1 file changed, 39 insertions(+), 39 deletions(-)
diff --git a/src/main/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilter.java b/src/main/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilter.java
index e568bf5..9bbeb43 100644
--- a/src/main/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilter.java
+++ b/src/main/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilter.java
@@ -16,8 +16,8 @@
*/
package org.apache.commons.collections4.bloomfilter;
-import java.util.BitSet;
import java.util.PrimitiveIterator.OfInt;
+import java.util.function.LongBinaryOperator;
import org.apache.commons.collections4.bloomfilter.hasher.HashFunctionIdentity;
import org.apache.commons.collections4.bloomfilter.hasher.Hasher;
@@ -66,11 +66,11 @@ public abstract class AbstractBloomFilter implements BloomFilter {
final long[] mine = getBits();
final long[] theirs = other.getBits();
final int limit = Integer.min(mine.length, theirs.length);
- final long[] result = new long[limit];
+ int count = 0;
for (int i = 0; i < limit; i++) {
- result[i] = mine[i] & theirs[i];
+ count += Long.bitCount(mine[i] & theirs[i]);
}
- return BitSet.valueOf(result).cardinality();
+ return count;
}
/**
@@ -80,7 +80,11 @@ public abstract class AbstractBloomFilter implements BloomFilter {
*/
@Override
public int cardinality() {
- return BitSet.valueOf(getBits()).cardinality();
+ int count = 0;
+ for (final long bits : getBits()) {
+ count += Long.bitCount(bits);
+ }
+ return count;
}
/**
@@ -182,27 +186,8 @@ public abstract class AbstractBloomFilter implements BloomFilter {
@Override
public int orCardinality(final BloomFilter other) {
- verifyShape(other);
- final long[] mine = getBits();
- final long[] theirs = other.getBits();
- long[] remainder = null;
- long[] result = null;
- if (mine.length > theirs.length) {
- result = new long[mine.length];
- remainder = mine;
- } else {
- result = new long[theirs.length];
- remainder = theirs;
-
- }
- final int limit = Integer.min(mine.length, theirs.length);
- for (int i = 0; i < limit; i++) {
- result[i] = mine[i] | theirs[i];
- }
- if (limit < result.length) {
- System.arraycopy(remainder, limit, result, limit, result.length - limit);
- }
- return BitSet.valueOf(result).cardinality();
+ // Logical OR
+ return opCardinality(other, (a, b) -> a | b);
}
/**
@@ -253,26 +238,41 @@ public abstract class AbstractBloomFilter implements BloomFilter {
*/
@Override
public int xorCardinality(final BloomFilter other) {
+ // Logical XOR
+ return opCardinality(other, (a, b) -> a ^ b);
+ }
+
+ /**
+ * Perform the operation on the matched longs from this filter and the other filter
+ * and count the cardinality.
+ *
+ * <p>The remaining unmatched longs from the larger filter are always counted. This
+ * method is suitable for OR and XOR cardinality.
+ *
+ * @param other the other Bloom filter.
+ * @param operation the operation (e.g. OR, XOR)
+ * @return the cardinality
+ */
+ private int opCardinality(final BloomFilter other, LongBinaryOperator operation) {
verifyShape(other);
final long[] mine = getBits();
final long[] theirs = other.getBits();
- long[] remainder = null;
- long[] result = null;
+ long[] small;
+ long[] big;
if (mine.length > theirs.length) {
- result = new long[mine.length];
- remainder = mine;
+ big = mine;
+ small = theirs;
} else {
- result = new long[theirs.length];
- remainder = theirs;
-
+ small = mine;
+ big = theirs;
}
- final int limit = Integer.min(mine.length, theirs.length);
- for (int i = 0; i < limit; i++) {
- result[i] = mine[i] ^ theirs[i];
+ int count = 0;
+ for (int i = 0; i < small.length; i++) {
+ count += Long.bitCount(operation.applyAsLong(small[i], big[i]));
}
- if (limit < result.length) {
- System.arraycopy(remainder, limit, result, limit, result.length - limit);
+ for (int i = small.length; i < big.length; i++) {
+ count += Long.bitCount(big[i]);
}
- return BitSet.valueOf(result).cardinality();
+ return count;
}
}