BitSet до и от целого / длинного - PullRequest
51 голосов
/ 19 марта 2010

Если у меня есть целое число, для которого я хочу выполнить битовую манипуляцию, как я могу загрузить его в java.util.BitSet? Как я могу преобразовать его обратно в int или long? Меня не очень беспокоит размер BitSet - он всегда будет длиной 32 или 64 бита. Я просто хотел бы использовать методы set(), clear(), nextSetBit() и nextClearBit() вместо побитовых операторов, но я не могу найти простой способ инициализации набора битов числовым типом.

Ответы [ 6 ]

51 голосов
/ 19 марта 2010

Следующий код создает бит из длинного значения и наоборот:

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;
  }
}

Отредактировано: теперь оба направления, @leftbrain: причины, вы правы

34 голосов
/ 25 марта 2014

Добавить к ответу finnw: есть также BitSet.valueOf(long[]) и BitSet.toLongArray(). Итак:

int n = 12345;
BitSet bs = BitSet.valueOf(new long[]{n});
long l = bs.toLongArray()[0];
18 голосов
/ 02 февраля 2011

Java 7 имеет <a href="http://download.oracle.com/javase/7/docs/api/java/util/%42it%53et.html#value%4ff%28byte%5b%5d%29" rel="noreferrer">BitSet.valueOf(byte[])</a> и <a href="http://download.oracle.com/javase/7/docs/api/java/util/%42it%53et.html#to%42yte%41rray%28%29" rel="noreferrer">BitSet.toByteArray()</a>

Если вы застряли с Java 6 или более ранней версией, вы можете использовать BigInteger, если маловероятно, что это узкое место в производительности - у него есть методы getLowestSetBit, setBit и clearBit (последние два создадут новый BigInteger вместо изменения на месте.)

3 голосов
/ 04 июля 2016

Чтобы получить long обратно из small BitSet в 'streamy' way:

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

И наоборот:

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

N.B .: Использование BitSet::valueOf и BitSet::toLongArray, конечно, проще.

1 голос
/ 15 июля 2014

Практически прямо из документации nextSetBit

value=0;
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
 value += (1 << i)
 }
0 голосов
/ 19 марта 2010

Не является ли метод public void set(int bit) тем, что вы ищете?

...