60

If I have an integer that I'd like to perform bit manipulation on, how can I load it into a java.util.BitSet? How can I convert it back to an int or long? I'm not so concerned about the size of the BitSet -- it will always be 32 or 64 bits long. I'd just like to use the set(), clear(), nextSetBit(), and nextClearBit() methods rather than bitwise operators, but I can't find an easy way to initialize a bit set with a numeric type.

Arnaud
  • 7,259
  • 10
  • 50
  • 71
ataylor
  • 64,891
  • 24
  • 161
  • 189
  • 2
    Personally, I'd say raw bit manipulation is the way to go here. It really isn't that complicated, and as you say I don't see a simple way to get an int or long into a BitSet. – Michael Myers Mar 18 '10 at 22:07

7 Answers7

65

The following code creates a bit set from a long value and vice versa:

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

EDITED: Now both directions, @leftbrain: of cause, you are right

Arne Burmeister
  • 20,046
  • 8
  • 53
  • 94
48

Add to finnw answer: there are also BitSet.valueOf(long[]) and BitSet.toLongArray(). So:

int n = 12345;
BitSet bs = BitSet.valueOf(new long[]{n});
long l = bs.toLongArray()[0];
Bobulous
  • 12,967
  • 4
  • 37
  • 68
Grigory Kislin
  • 16,647
  • 10
  • 125
  • 197
  • If the bitset has no "1", bs.toLongArray()[0] will throw ArrayIndexOutOfBoundsException exception! – Qianyue Sep 14 '21 at 08:17
20

Java 7 has BitSet.valueOf(byte[]) and BitSet.toByteArray()

If you are stuck with Java 6 or earlier, you can use BigInteger if it is not likely to be a performance bottleneck - it has getLowestSetBit, setBit and clearBit methods (the last two will create a new BigInteger instead of modifying in-place.)

finnw
  • 47,861
  • 24
  • 143
  • 221
5

To get a long back from a small BitSet in a 'streamy' way:

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

Vice-versa:

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

N.B.: Using BitSet::valueOf and BitSet::toLongArray is of course easier.

charlie
  • 1,478
  • 10
  • 20
0

Pretty much straight from the documentation of nextSetBit

value=0;
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
 value += (1 << i)
 }
user3799584
  • 917
  • 1
  • 9
  • 18
  • 1
    This will fail for a BitSet larger than 32 or 64 bits, in such a case you'll need to handle an `int[]` or `long[]` at the output. But OP explicitly doesn't care, so fair enough. Just a few minor glitches: in case of a long you should `1L << i`, to prevent overflow, and an OR like `value |= 1L << i` is enough. – charlie Jul 04 '16 at 12:46
0

For Kotlin those extensions can be used.

BitSet to Int extension:

fun BitSet.toInt() =
    toLongArray()
        .getOrNull(0)
        ?.toInt()
        ?: 0

Int to BitSet extension:

fun Int.toBitSet(size: Int): BitSet {
    val byteArray = byteArrayOf(toByte())

    return BitSet.valueOf(
        if (byteArray.size == size) byteArray
        else byteArray.copyOf(size))
}

Usage example:

val intValue = 1

val bitSetValue = intValue.toBitSet(size = 2)
println("bitSetValue: $bitSetValue")

val firstValue = bitSetValue.get(0)
println("firstValue: $firstValue")

val secondValue = bitSetValue.get(1)
println("secondValue: $secondValue")

bitSetValue.set(0, true)
bitSetValue.set(1, false)
println("bitSetValue: $bitSetValue")

val newIntValue = bitSetValue.toInt()
println("newIntValue: $newIntValue")
Eugene Babich
  • 1,271
  • 15
  • 25
-3

Isn't the public void set(int bit) method what your looking for?

kukudas
  • 4,834
  • 5
  • 44
  • 65
  • 6
    That sets one single bit with the index you provide. I'd like to set each bit that's set in the integer. – ataylor Mar 18 '10 at 22:17