2010-05-18 39 views
7

¿Me falta algo dolorosamente obvio? ¿O nadie en el mundo realmente usa java.util.BitSet?java.util.BitSet - set() no funciona como se esperaba

La siguiente prueba falla:

@Test 
public void testBitSet() throws Exception { 
    BitSet b = new BitSet(); 
    b.set(0, true); 
    b.set(1, false); 
    assertEquals(2, b.length()); 
} 

Es muy claro para mí por qué no terminar con un BitSet de longitud 2 y el valor 10. Me asomé a la fuente de java.util.BitSet , y en la inspección ocasional parece que no hace suficiente distinción entre un bit que se ha establecido como falso y un bit que nunca se ha establecido en ningún valor ...

(Tenga en cuenta que establecer explícitamente el tamaño del BitSet en el el constructor no tiene ningún efecto, por ejemplo:

BitSet b = new BitSet(2); 
+1

"¿O es que simplemente nadie en el mundo en realidad utilizar java.util. BitSet? " ... sí, claro, saca el otro, ¡tiene campanas! –

+0

@Stephen ¿cuál otro? ;-) – denishaskin

+1

el * otro * otro! –

Respuesta

6

Las personas usan BitSet; sin embargo, lo usan para algo diferente de lo que usted pretende. Probablemente sea mejor pensar en BitSet como una forma muy compacta y eficiente en memoria de Set<Integer> que tiene la peculiar propiedad de no poder poner números negativos en ella.

Es muy común con BitSet s utilizarlos en el patrón de

for (int id = set.nextSetBit(0); id >= 0; id = set.nextSetBit(id + 1)) { 
    // do stuff to a set index 
} 

después de hacer algo para llenarlos. Esto es equivalente a iterar sobre los elementos del Set.

+0

Buena explicación. Básicamente, parece que BitSet no es muy adecuado para representar un campo de bits de longitud fija (o matriz de bits). – denishaskin

+0

Bueno, para una longitud * fija *, si no confías en el BitSet para mantener la longitud para ti, está bien. Si desea que el BitSet maneje la longitud para usted, se sentirá decepcionado. –

8

Usted conjunto de bits más alta (como en "establecido en 1") es el bit 0. Así que la longitud debe ser 1.

Ver el JavaDoc for length:

longitud public int()

Devuelve el "tamaño lógico" de este BitSet: el índice del bit más alto establecido en el BitSet más uno. Devuelve cero si el BitSet no contiene bits establecidos.

Tal vez usted está buscando size aunque es posible que sea de mayor de dos si bits son asignados a una determinada resolución (digamos límites de 16 bits)?

+0

ZZ, lo limpié para asegurarme de que estaba limpio (y lo hice +1), espero que no te importe. Dado que inicialmente entendí mal "establecer" como "se ha establecido en cualquier cosa", los mortales menores también pueden tener ese problema :-) – paxdiablo

+0

@paxdiablo: Mucho más claro. ¡Gracias! –

2

Dado que el conjunto de bits está respaldado por un largo [], el tamaño mínimo es 64 (porque 1 largo es 64 bits). El tamaño se incrementa en un múltiplo de 64 y, por alguna razón, no han mantenido el número de bits que pretendía representar cuando utiliza el constructor que toma un int.

3

Esto también me desconcertó, no estoy seguro de la razón de ser de la funcionalidad actual más bien inesperada de BitSet. Sin embargo ya que no es definitiva, podemos utilizar algunos abrazo y extender las tácticas y hacer lo siguiente para obtener una BitSet fijo con la semántica de longitud como se esperaba:

import java.util.BitSet; 

/** 
* Variation of BitSet which does NOT interpret the highest bit synonymous with 
* its length. 
* 
* @author [email protected] 
*/ 
public class FixedBitSet extends BitSet{ 

    int fixedLength; 

    public FixedBitSet(int fixedLength){ 
     super(fixedLength); 
     this.fixedLength = fixedLength; 
    } 

    @Override 
    public int length() { 
     return fixedLength; 
    } 
} 
0

Buena Casper! ¡Su pequeña mejora debería haber estado presente en la definición original de BitSet java!También sugiero esto (append() y concat() son útiles para diversos usos)

import java.util.BitSet; 

public class fixBitSet extends BitSet { 

    public int fsize = 0; 

    public void set(int k, boolean value) { 
    if (k >= fsize) 
     fsize = k + 1; 
    super.set(k, value); 
    } 

    public void append(fixBitSet bs) { 
    for (int k = 0; k < bs.fsize; k++) 
     super.set(fsize + k, bs.get(k)); 
    fsize += bs.fsize; 
    } 

    public static fixBitSet concat(fixBitSet[] vbs) { 
    final fixBitSet bs = new fixBitSet(); 
    for (fixBitSet xbs : vbs) 
     bs.append(xbs); 
    return (bs); 
    } 

} 
1

// Abhay Dandekar

import java.util.BitSet; 

public class TestBitSet { 

    public static void main(String[] args) { 

     BitSet bitSet = new BitSet(); 
     System.out.println("State 0 : " + bitSet.size() + " : " + bitSet.length()); 

     bitSet.set(0, true); 
     bitSet.set(1, true); 
     System.out.println("State 1 : " + bitSet.size() + " : " + bitSet.length()); 

     bitSet.set(2, false); 
     bitSet.set(3, false); 
     System.out.println("State 2 : " + bitSet.size() + " : " + bitSet.length()); 

     bitSet.set(4, true); 
     System.out.println("State 3 : " + bitSet.size() + " : " + bitSet.length()); 

    } 
} 

un programa Java simple de mostrar lo que sucede en su interior. Algunos puntos a tener en cuenta:

  1. BitSet está respaldado por una larga

  2. Todos los valores por defecto son falsas

  3. Al regresar la longitud, devuelve el índice + 1 de la más alta "verdadero "valor en el conjunto.

La salida de abajo debe ser capaz de explicarse a sí misma:

State 0 : 64 : 0 

State 1 : 64 : 2 

State 2 : 64 : 2 

State 3 : 64 : 5 

Así puntos para concluir:

  1. No utilice la longitud de concluir la hay de bits modificada

  2. Se puede utilizar en escenarios como filtros de floración. Más sobre filtros Bloom se googled ..;)

Esperanza esto ayuda

Saludos,

Abhay Dandekar

Cuestiones relacionadas