java - как создать и управлять битовым массивом длиной 10 миллионов бит

Я только что столкнулся с проблемой; это было легко решить в псевдо-коде, но когда я начал кодировать его на java; я начал понимать, что не знаю, с чего начать...

вот, что мне нужно делать:

  1. мне нужен битный массив размером 10 миллионов (бит) (назовем его A).
  2. мне нужно иметь возможность установить элементы в этом массиве в 1 или 0 (a[99000]=1).
  3. мне нужно перебрать 10 миллионов элементов.

4 ответов


использовать BitSet (как уже отметил Хантер Макмиллен в комментарии). Вы можете легко get и set бит. Для итерации просто используйте normal for петли.


"правильный" способ в 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 ГБ ОЗУ. Кроме того, мы используем маски и битовые сдвиги вместо операций деления и по модулю, уменьшая время вычисления. Улучшение довольно существенное.