2010-03-18 9 views
42

Si tengo un número entero en el que me gustaría realizar la manipulación de bits, ¿cómo puedo cargarlo en un java.util.BitSet? ¿Cómo puedo convertirlo de nuevo a int o long? No estoy tan preocupado por el tamaño del BitSet - siempre será de 32 o 64 bits de longitud. Solo me gustaría utilizar los métodos set(), clear(), nextSetBit() y nextClearBit() en lugar de los operadores bit a bit, pero no puedo encontrar una manera fácil de inicializar un conjunto de bits con un tipo numérico.BitSet hacia y desde entero/largo

+1

Personalmente, diría que la manipulación de bits sin formato es el camino a seguir aquí. Realmente no es tan complicado, y como dices, no veo una manera simple de obtener un int o long en un BitSet. –

Respuesta

47

El siguiente código crea un conjunto de bits de un valor de largo y viceversa:

public class Bits { 

    public static BitSet convert(long value) { 
    BitSet bits = new BitSet(); 
    int index = 0; 
    while (value != 0L) { 
     if (value % 2L != 0) { 
     bits.set(index); 
     } 
     ++index; 
     value = value >>> 1; 
    } 
    return bits; 
    } 

    public static long convert(BitSet bits) { 
    long value = 0L; 
    for (int i = 0; i < bits.length(); ++i) { 
     value += bits.get(i) ? (1L << i) : 0L; 
    } 
    return value; 
    } 
} 

EDITADO: Ahora ambas direcciones, @leftbrain: de causa, usted tiene razón

+6

Creo que la línea (valor% 1L! = 0) debe ser (valor% 2L! = 0) –

+0

'if (value & 1! = 0)' porque queremos verificar si el bit 0 está establecido, '%' es operador de módulo, y 'siempre es 0 ya que todos los números son divisibles por 1 – ithkuil

+1

FYI, esto está creando un conjunto de bits en orden little-endian –

-2

¿No es el método public void set(int bit) lo que buscas?

+6

Eso establece un solo bit con el índice que usted proporciona. Me gustaría establecer cada bit que se establece en el entero. – ataylor

17

Java 7 tiene BitSet.valueOf(byte[]) y BitSet.toByteArray()

Si usted está atascado con Java 6 o anterior, puede utilizar BigInteger si no es probable que sea un cuello de botella - que tiene getLowestSetBit, setBit y clearBit métodos (los dos últimos creará un nuevo BigInteger en lugar de modificar en el lugar.)

1

Más o menos directamente de la documentación de nextSetBit

value=0; 
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) { 
value += (1 << i) 
} 
+0

Esto no funcionará para un BitSet mayor de 32 o 64 bits, en tal caso deberá manejar un 'int []' o 'long []' en la salida. Pero a OP explícitamente no le importa, es lo suficientemente justo. Solo unos pocos fallos técnicos menores: en caso de una larga, debe '1L << i', para evitar el desbordamiento, y un OR como' valor | = 1L << i' es suficiente. – charlie

3

Para obtener una long volver de un pequeñaBitSet en un 'streamy' manera :

long l = bitSet.stream() 
     .takeWhile(i -> i < Long.SIZE) 
     .mapToLong(i -> 1L << i) 
     .reduce(0, (a, b) -> a | b); 

Viceversa:

BitSet bitSet = IntStream.range(0, Long.SIZE - 1) 
     .filter(i -> 0 != (l & 1L << i)) 
     .collect(BitSet::new, BitSet::set, BitSet::or); 

N.B .: Usar BitSet::valueOf y BitSet::toLongArray es, por supuesto, más fácil.

Cuestiones relacionadas