java - как создать и управлять битовым массивом длиной 10 миллионов бит
Я только что столкнулся с проблемой; это было легко решить в псевдо-коде, но когда я начал кодировать его на java; я начал понимать, что не знаю, с чего начать...
вот, что мне нужно делать:
- мне нужен битный массив размером 10 миллионов (бит) (назовем его A).
- мне нужно иметь возможность установить элементы в этом массиве в 1 или 0 (a[99000]=1).
- мне нужно перебрать 10 миллионов элементов.
4 ответов
"правильный" способ в Java-использовать уже существующий класс BitSet, указанный Hunter McMillen. Если вы выясняете, как большой битовый массив управляется исключительно с целью обдумывания интересной проблемы, то вычисление положения бита в массиве байтов-это просто базовая модульная арифметика.
public class BitArray {
private static final int ALL_ONES = 0xFFFFFFFF;
private static final int WORD_SIZE = 32;
private int bits[] = null;
public BitArray(int size) {
bits = new int[size / WORD_SIZE + (size % WORD_SIZE == 0 ? 0 : 1)];
}
public boolean getBit(int pos) {
return (bits[pos / WORD_SIZE] & (1 << (pos % WORD_SIZE))) != 0;
}
public void setBit(int pos, boolean b) {
int word = bits[pos / WORD_SIZE];
int posBit = 1 << (pos % WORD_SIZE);
if (b) {
word |= posBit;
} else {
word &= (ALL_ONES - posBit);
}
bits[pos / WORD_SIZE] = word;
}
}
byte[] A = new byte[10000000];
A[99000] = 1;
for(int i = 0; i < A.length; i++) {
//do something
}
Если вам действительно нужны биты, вы можете использовать boolean и пусть true = 1, а false = 0.
boolean[] A = new boolean[10000000];
//etc
вот более оптимизированная реализация phatfingers 'BitArray'
class BitArray {
private static final int MASK = 63;
private final long len;
private long bits[] = null;
public BitArray(long size) {
if ((((size-1)>>6) + 1) > 2147483647) {
throw new IllegalArgumentException(
"Field size to large, max size = 137438953408");
}else if (size < 1) {
throw new IllegalArgumentException(
"Field size to small, min size = 1");
}
len = size;
bits = new long[(int) (((size-1)>>6) + 1)];
}
public boolean getBit(long pos) {
return (bits[(int)(pos>>6)] & (1L << (pos&MASK))) != 0;
}
public void setBit(long pos, boolean b) {
if (getBit(pos) != b) { bits[(int)(pos>>6)] ^= (1L << (pos&MASK)); }
}
public long getLength() {
return len;
}
}
поскольку мы используем поля 64, мы расширяем максимальный размер до 137438953408-бит, что примерно соответствует 16 ГБ ОЗУ. Кроме того, мы используем маски и битовые сдвиги вместо операций деления и по модулю, уменьшая время вычисления. Улучшение довольно существенное.