Очень компактный Bitarray в Java
Я ищу очень компактный способ хранения плотной битрейты переменной длины в Java. Прямо сейчас, я использую BitSet
, но, кажется, использует в среднем 1.5 * n бит пространства для хранения битового вектора размера n. Как правило, это не проблема, но в этом случае битрейты, которые хранятся, являются довольно значительной частью области памяти приложения. Таким образом, это действительно помогло бы им быть немного меньше.
Пространство, требуемое BitSet, по-видимому, связано с тем, что массив длин, используемый для обратной структуры данных, имеет тенденцию удваиваться каждый раз, когда он расширяется, чтобы содержать больше бит:
// BitSet resizing code
private void ensureCapacity(int wordsRequired) {
if (words.length < wordsRequired) {
// Allocate larger of doubled size or required size
int request = Math.max(2 * words.length, wordsRequired);
words = Arrays.copyOf(words, request);
sizeIsSticky = false;
}
}
Я мог бы написать свою собственную альтернативную реализацию BitSet, которая более консервативно структурирует структуру данных. Но мне бы очень не хотелось дублировать функциональные возможности, которые уже есть в стандартных библиотеках классов, если мне это не нужно.
Ответы
Ответ 1
Если вы создаете BitSet
с помощью конструктора BitSet(int nbits)
, вы можете указать емкость. Если вы угадаете, что емкость неправильная, и перейдите, она удвоит размер.
Класс BitSet
имеет метод trimToSize
, который является private и вызывается writeObject и clone(). Если вы клонируете свой объект или сериализуете его, он будет обрезать его до нужной длины (предполагая, что класс расширил его с помощью метода securityCapacity).
Ответ 2
Вы можете воспользоваться сжатыми альтернативами BitSet. См. Например:
https://github.com/lemire/javaewah
http://roaringbitmap.org/