Java: эффективно хранить логические [32]?

В Java я хотел бы хранить ( > 10'000) массивы логических значений (boolean []) с длиной 32 на диск и читать их позже позже для дальнейших вычислений и сравнения.

Поскольку один массив будет иметь длину 32, интересно, имеет ли смысл хранить его как целочисленное значение, чтобы ускорить чтение и запись (на 32-битной машине). Предлагаете ли вы использовать BitSet, а затем преобразовать в int? Или даже забыть о int и использовать байты?

Ответ 1

Для двоичного хранения используйте int и DataOutputStream (DataInputStream для чтения).

Я думаю, что логические массивы хранятся в байтах или внутренних массивах внутри Java, поэтому вам может потребоваться избегать накладных расходов и постоянно поддерживать кодировку int, т.е. вообще не использовать boolean [].

Вместо этого сделайте что-то вроде

public class BooleanArray32 {
  private int values;

  public boolean get(int pos) {
    return (values & (1 << pos)) != 0;
  }

  public void set(int pos, boolean value) {
     int mask = 1 << pos;
     values = (values & ~mask) | (value ? mask : 0);
  }

  public void write(DataOutputStream dos) throws IOException {
    dos.writeInt(values);
  }

  public void read(DataInputStream dis) throws IOException {
    values = dis.readInt();
  }

  public int compare(BooleanArray32 b2) {
     return countBits(b2.values & values);
  }

  // From http://graphics.stanford.edu/~seander/bithacks.html
  // Disclaimer: I did not fully double check whether this works for Java signed ints
  public static int countBits(int v) {
    v = v - ((v >>> 1) & 0x55555555);                    // reuse input as temporary
    v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);     // temp
    return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; 
  }
} 

Ответ 2

У меня сильное впечатление, что любое сжатие, которое вы собираетесь сделать для упаковки ваших логических значений, будет увеличивать время чтения и записи. (моя ошибка, я явно пропускал мои лекарства). Вы скорее выиграете с точки зрения хранения.

BitSet - это разумный выбор на стороне вашей бизнес-логики. Он внутренне хранит длинный, который вы можете преобразовать в int. Однако, так как BitSet достаточно хвалит, чтобы не показывать вам своих рядовых, вам нужно получить каждый бит-индекс в последовательности. Это означает, что я полагаю, что нет реального преимущества преобразования в int, а не просто использования байтов напрямую.

Ваше собственное решение Stefan Haustein (расширенное по мере необходимости для имитации BitSet), поэтому предпочтительнее для вашего требования к хранению, так как вы не берете на себя лишние накладные расходы.