org.roaringbitmap.ConstantMemoryContainerAppender Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of RoaringBitmap Show documentation
Show all versions of RoaringBitmap Show documentation
Roaring bitmaps are compressed bitmaps (also called bitsets) which tend to outperform
conventional compressed bitmaps such as WAH or Concise.
package org.roaringbitmap;
import java.util.Arrays;
import java.util.function.Supplier;
import static org.roaringbitmap.Util.*;
/**
* This class can be used to write quickly values to a bitmap.
* The values are expected to be (increasing) sorted order.
* Values are first written to a temporary internal buffer, but
* the underlying bitmap can forcefully synchronize by calling "flush"
* (although calling flush to often would defeat the performance
* purpose of this class).
* The main use case for an ConstantMemoryContainerAppender is to get bitmaps quickly.
* You should benchmark your particular use case to see if it helps.
*
*
* {@code
*
* //...
*
*
* RoaringBitmapWriter writer =
* RoaringBitmapWriter.writer().constantMemory().get();
* for (int i :....) {
* writer.add(i);
* }
* writer.flush(); // important
* }
*
*/
public class ConstantMemoryContainerAppender> implements RoaringBitmapWriter {
private final boolean doPartialSort;
private final boolean runCompress;
private static final int WORD_COUNT = 1 << 10;
private final long[] bitmap;
private final Supplier newUnderlying;
private T underlying;
private boolean dirty = false;
private int currentKey;
/**
* Initialize an ConstantMemoryContainerAppender with a receiving bitmap
*
* @param doPartialSort indicates whether to sort the upper 16 bits of input data in addMany
* @param runCompress whether to run compress appended containers
* @param newUnderlying supplier of bitmaps where the data gets written
*/
ConstantMemoryContainerAppender(boolean doPartialSort,
boolean runCompress,
Supplier newUnderlying) {
this.newUnderlying = newUnderlying;
this.underlying = newUnderlying.get();
this.doPartialSort = doPartialSort;
this.runCompress = runCompress;
this.bitmap = new long[WORD_COUNT];
}
/**
* Grab a reference to the underlying bitmap
*
* @return the underlying bitmap
*/
@Override
public T getUnderlying() {
return underlying;
}
/**
* Adds the value to the underlying bitmap. The data might
* be added to a temporary buffer. You should call "flush"
* when you are done.
*
* @param value the value to add.
*/
@Override
public void add(int value) {
int key = (highbits(value));
if (key != currentKey) {
if (key < currentKey) {
underlying.add(value);
return;
} else {
appendToUnderlying();
currentKey = key;
}
}
int low = (lowbits(value));
bitmap[(low >>> 6)] |= (1L << low);
dirty = true;
}
@Override
public void addMany(int... values) {
if (doPartialSort) {
partialRadixSort(values);
}
for (int value : values) {
add(value);
}
}
@Override
public void add(long min, long max) {
appendToUnderlying();
underlying.add(min, max);
int mark = (int)((max >>> 16) + 1);
if (currentKey < mark) {
currentKey = mark;
}
}
/**
* Ensures that any buffered additions are flushed to the underlying bitmap.
*/
@Override
public void flush() {
currentKey += appendToUnderlying();
}
@Override
public void reset() {
currentKey = 0;
underlying = newUnderlying.get();
dirty = false;
}
private Container chooseBestContainer() {
Container container = new BitmapContainer(bitmap, -1).repairAfterLazy();
if (runCompress) {
container = container.runOptimize();
}
return container instanceof BitmapContainer ? container.clone() : container;
}
private int appendToUnderlying() {
if (dirty) {
assert currentKey <= 0xFFFF;
underlying.append((char) currentKey, chooseBestContainer());
Arrays.fill(bitmap, 0L);
dirty = false;
return 1;
}
return 0;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy