2012-06-16 12 views
10

En Java, me gustaría almacenar (> 10'000) matrices de valores booleanos (booleanos []) con longitud 32 en el disco y leerlos más adelante para su posterior cálculo y comparación.Java: almacenar de manera eficiente boolean [32]?

Dado que una sola matriz tendrá una longitud de 32, me pregunto si tiene sentido almacenarla como un valor entero para acelerar la lectura y escritura (en una máquina de 32 bits). ¿Sugeriría usar BitSet y luego convertir a int? ¿O incluso te olvidas de usar int y bytes?

+1

¿Qué es más importante para usted: almacenamiento eficiente o lectura/escritura eficiente (es decir, rápida)? –

+0

Creo que la lectura/escritura rápida es mucho más importante en esta aplicación – navige

+1

¿Desea simplemente escribir y leer todas las matrices una vez, o necesita acceso aleatorio a matrices específicas? – Behe

Respuesta

11

Para el almacenamiento binario, utilice int y una DataOutputStream (DataInputStream para la lectura).

Creo que las matrices booleanas se almacenan como byte o int arrays internamente en Java, por lo que puede considerar evitar la sobrecarga y mantener la codificación int todo el tiempo, es decir, no usar booleano [].

En cambio, tener algo como

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's 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; 
    } 
} 
+0

+1, ahora, esto es definitivamente mejor que BitSet para los requisitos de OP. –

+0

¡Tiene mucho sentido! ¡Muchas gracias! – navige

+0

Corregido un error en el conjunto y movido los ayudantes estáticos a la parte inferior. Es probable que desee volver a verificar los conteos de bits en el asistente bitsInNibble. Háganos saber si todo funciona como se espera para su tarea :) –

1

Tengo la fuerte impresión de que ningún tipo de compresión que se va a hacer para empacar sus valores booleanos se aumentar el tiempo de leer y escribir. (mi error, claramente me faltaba mi medicamento). Preferirás ganar en términos de almacenamiento.

BitSet es una opción sensata desde el punto de vista de su lógica comercial. Internamente almacena una larga, que puedes convertir a una int. Sin embargo, dado que BitSet es lo suficientemente prudente como para no mostrarle sus partes privadas, necesita obtener cada índice de bits en secuencia. Esto significa que supongo que no hay una ventaja real de convertir a un int en lugar de simplemente usar bytes directamente.

Por lo tanto, la solución Roll-to-own de Stefan Haustein (extendida según sea necesario para imitar a BitSet) es preferible para su requisito de almacenamiento, ya que no incurre en gastos indirectos innecesarios.

+0

La primera frase ciertamente no es cierta: el almacenamiento está organizado en bytes o en unidades más grandes, y varios órdenes de magnitud más lentas que el acceso a la memoria y cálculos simples. –

+0

Tiene razón acerca de la organización y la relación de acceso a la memoria, sin embargo, también debe tener en cuenta los cachés. Voy a arreglar mi respuesta para dar cuenta de eso. –

+1

No veo cómo las memorias caché están involucradas aquí. Tenga en cuenta que esto no se trata de compresión, sino de almacenar un bit como un bit único en lugar de un byte o más. –

Cuestiones relacionadas