Refactor internals for org.apache.commons.collections4.bloomfilter

Create new package-private methods to refactor commons code patterns
This commit is contained in:
Gary Gregory 2024-10-04 09:38:10 -04:00
parent 23379c1ff9
commit 2191713fdd
8 changed files with 43 additions and 11 deletions

View File

@ -77,7 +77,7 @@ public interface BitMapExtractor {
static BitMapExtractor fromIndexExtractor(final IndexExtractor extractor, final int numberOfBits) {
Objects.requireNonNull(extractor, "extractor");
final long[] result = new long[BitMaps.numberOfBitMaps(numberOfBits)];
final long[] result = BitMaps.newBitMap(numberOfBits);
extractor.processIndices(i -> {
BitMaps.set(result, i);
return true;

View File

@ -111,6 +111,28 @@ public class BitMaps {
return (int) (remainder >= divisor ? remainder - divisor : remainder);
}
/**
* Creates a new bitmap for the number of bit maps (longs) required for the numberOfBits parameter.
*
* <p><em>If the input is negative the behavior is not defined.</em></p>
*
* @param numberOfBits the number of bits to store in the array of bit maps.
* @return a new bitmap.
*/
static long[] newBitMap(final int numberOfBits) {
return new long[numberOfBitMaps(numberOfBits)];
}
/**
* Creates a new bitmap for given shape parameter.
*
* @param shape the shape.
* @return a new bitmap.
*/
static long[] newBitMap(final Shape shape) {
return newBitMap(shape.getNumberOfBits());
}
/**
* Calculates the number of bit maps (longs) required for the numberOfBits parameter.
*
@ -123,6 +145,16 @@ public class BitMaps {
return (numberOfBits - 1 >> DIVIDE_BY_64) + 1;
}
/**
* Calculates the number of bit maps (longs) required for the shape parameter.
*
* @param shape the shape.
* @return the number of bit maps necessary.
*/
static int numberOfBitMaps(final Shape shape) {
return numberOfBitMaps(shape.getNumberOfBits());
}
/**
* Sets the bit in the bit maps.
* <p><em>Does not perform range checking</em></p>

View File

@ -72,7 +72,7 @@ public final class IndexFilter {
* @param shape The shape that is being generated.
*/
BitMapTracker(final Shape shape) {
bits = new long[BitMaps.numberOfBitMaps(shape.getNumberOfBits())];
bits = BitMaps.newBitMap(shape);
}
@Override
@ -106,7 +106,7 @@ public final class IndexFilter {
private IndexFilter(final Shape shape, final IntPredicate consumer) {
this.size = shape.getNumberOfBits();
this.consumer = consumer;
if (BitMaps.numberOfBitMaps(shape.getNumberOfBits()) * Long.BYTES < (long) shape.getNumberOfHashFunctions()
if (BitMaps.numberOfBitMaps(shape) * Long.BYTES < (long) shape.getNumberOfHashFunctions()
* Integer.BYTES) {
this.tracker = new BitMapTracker(shape);
} else {

View File

@ -483,7 +483,7 @@ public final class Shape {
* (number of indexes) is less than or equal to 2*number of bit maps the
* cardinality is sparse within the shape.
*/
return cardinality <= BitMaps.numberOfBitMaps(getNumberOfBits()) * 2;
return cardinality <= BitMaps.numberOfBitMaps(this) * 2;
}
@Override

View File

@ -51,7 +51,7 @@ public final class SimpleBloomFilter implements BloomFilter {
public SimpleBloomFilter(final Shape shape) {
Objects.requireNonNull(shape, "shape");
this.shape = shape;
this.bitMap = new long[BitMaps.numberOfBitMaps(shape.getNumberOfBits())];
this.bitMap = BitMaps.newBitMap(shape);
this.cardinality = 0;
}

View File

@ -66,7 +66,7 @@ public final class SparseBloomFilter implements BloomFilter {
@Override
public long[] asBitMapArray() {
final long[] result = new long[BitMaps.numberOfBitMaps(shape.getNumberOfBits())];
final long[] result = BitMaps.newBitMap(shape);
for (final int i : indices) {
BitMaps.set(result, i);
}
@ -154,7 +154,7 @@ public final class SparseBloomFilter implements BloomFilter {
@Override
public boolean processBitMaps(final LongPredicate consumer) {
Objects.requireNonNull(consumer, "consumer");
final int limit = BitMaps.numberOfBitMaps(shape.getNumberOfBits());
final int limit = BitMaps.numberOfBitMaps(shape);
/*
* because our indices are always in order we can shorten the time necessary to
* create the longs for the consumer

View File

@ -152,14 +152,14 @@ public abstract class AbstractBloomFilterTest<T extends BloomFilter> {
idx[0]++;
return true;
});
assertEquals(BitMaps.numberOfBitMaps(getTestShape().getNumberOfBits()), idx[0]);
assertEquals(BitMaps.numberOfBitMaps(getTestShape()), idx[0]);
idx[0] = 0;
createEmptyFilter(getTestShape()).processBitMaps(i -> {
idx[0]++;
return true;
});
assertEquals(BitMaps.numberOfBitMaps(getTestShape().getNumberOfBits()), idx[0]);
assertEquals(BitMaps.numberOfBitMaps(getTestShape()), idx[0]);
}
@Test
@ -413,7 +413,7 @@ public abstract class AbstractBloomFilterTest<T extends BloomFilter> {
@Test
public void testMergeWithBitMapExtractor() {
final int bitMapCount = BitMaps.numberOfBitMaps(getTestShape().getNumberOfBits());
final int bitMapCount = BitMaps.numberOfBitMaps(getTestShape());
for (int i = 0; i < 5; i++) {
final long[] values = new long[bitMapCount];
for (final int idx : DefaultIndexExtractorTest.generateIntArray(getTestShape().getNumberOfHashFunctions(), getTestShape().getNumberOfBits())) {

View File

@ -121,7 +121,7 @@ public class DefaultIndexExtractorTest extends AbstractIndexExtractorTest {
public void testFromBitMapExtractor() {
for (int i = 0; i < 5; i++) {
final int[] expected = generateIntArray(7, 256);
final long[] bits = new long[BitMaps.numberOfBitMaps(256)];
final long[] bits = BitMaps.newBitMap(256);
for (final int bitIndex : expected) {
BitMaps.set(bits, bitIndex);
}