Java位操作:如何将long类型的指定位设置为0或1?How to set/unset a bit at specific position of a long?
Java位操作:如何將long類型的指定位設置為0或1?
How to set/unset a bit at specific position of a long?
To set a bit, use:
x |= 0b1; // set LSB bit x |= 0b10; // set 2nd bit from LSBto erase a bit use:
x &= ~0b1; // unset LSB bit (if set) x &= ~0b10; // unset 2nd bit from LSBto toggle a bit use:
x ^= 0b1;Notice I use 0b?. You can also use any integer, eg:
x |= 4; // sets 3rd bit x |= 0x4; // sets 3rd bit x |= 0x10; // sets 9th bitHowever, it makes it harder to know which bit is being changed.
Using binary allows you to see which exact bits will be set/erased/toggled.
To dynamically set at bit, use:
x |= (1 << y); // set the yth bit from the LSB(1 << y) shifts the …001 y places left, so you can move the set bit y places.
You can also set multiple bits at once:
x |= (1 << y) | (1 << z); // set the yth and zth bit from the LSBOr to unset:
x &= ~((1 << y) | (1 << z)); // unset yth and zth bitOr to toggle:
x ^= (1 << y) | (1 << z); // toggle yth and zth bit拓展:除了以上方法外,也可使用 Java BitSet API
參考:https://www.baeldung.com/java-bitset
4. The BitSet API
Now that we know enough about the theory, it’s time to see what the BitSet API looks like.
For starters, let’s compare the memory footprint of a BitSet instance with 1024 bits with the boolean[] we saw earlier:
BitSet bitSet = new BitSet(1024);System.out.println(GraphLayout.parseInstance(bitSet).toPrintable());This will print both the shallow size of the BitSet instance and the size of its internal array:
java.util.BitSet@75412c2fd object externals:ADDRESS SIZE TYPE PATH VALUE70f97d208 24 java.util.BitSet (object)70f97d220 144 [J .words [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]As shown above, it uses a long[] with 16 elements (16 * 64 bits = 1024 bits) internally. Anyway, this instance is using 168 bytes in total, while the *boolean[]* were using 1024 bytes.
The more bits we have, the more the footprint difference increases. For example, to store 1024 * 1024 bits, the boolean[] consumes 1 MB, and the BitSet instance consumes around 130 KB.
4.1. Constructing BitSets
The simplest way to create a BitSet instance is to use the no-arg constructor:
BitSet bitSet = new BitSet();This will create a *BitSet* instance with a *long[]* of size one. Of course, it can automatically grow this array if needed.
It’s also possible to create a BitSet with an initial number of bits:
BitSet bitSet = new BitSet(100_000);Here, the internal array will have enough elements to hold 100,000 bits. This constructor comes in handy when we already have a reasonable estimate on the number of bits to store. In such use cases, it can prevent or decrease the unnecessary copying of array elements while growing it.
It’s even possible to create a BitSet from an existing long[], byte[], LongBuffer, and ByteBuffer. For instance, here we’re creating a BitSet instance from a given long[]:
BitSet bitSet = BitSet.valueOf(new long[] { 42, 12 });There are three more overloaded versions of the valueOf() static factory method to support the other mentioned types.
4.2. Setting Bits
We can set the value of a particular index to true using the set(index) method:
BitSet bitSet = new BitSet();bitSet.set(10); assertThat(bitSet.get(10)).isTrue();As usual, the indices are zero-based. It’s even possible to set a range of bits to *true* using the *set(fromInclusive, toExclusive)* method:
bitSet.set(20, 30); for (int i = 20; i <= 29; i++) {assertThat(bitSet.get(i)).isTrue(); } assertThat(bitSet.get(30)).isFalse();As is evident from the method signature, the beginning index is inclusive, and the ending one is exclusive.
When we say setting an index, we usually mean setting it to true. Despite this terminology, we can set a particular bit index to false using the set(index, boolean) method:
bitSet.set(10, false); assertThat(bitSet.get(10)).isFalse();This version also supports setting a range of values:
bitSet.set(20, 30, false); for (int i = 20; i <= 29; i++) {assertThat(bitSet.get(i)).isFalse(); }4.3. Clearing Bits
Instead of setting a specific bit index to false, we can simply clear it using the clear(index) method:
bitSet.set(42); assertThat(bitSet.get(42)).isTrue();bitSet.clear(42); assertThat(bitSet.get(42)).isFalse();Moreover, we can also clear a range of bits with the clear(fromInclusive, toExclusive) overloaded version:
bitSet.set(10, 20); for (int i = 10; i < 20; i++) {assertThat(bitSet.get(i)).isTrue(); }bitSet.clear(10, 20); for (int i = 10; i < 20; i++) {assertThat(bitSet.get(i)).isFalse(); }Interestingly, if we call this method without passing any arguments, it’ll clear all the set bits:
bitSet.set(10, 20); bitSet.clear(); for (int i = 0; i < 100; i++) { assertThat(bitSet.get(i)).isFalse(); }As shown above, after calling the clear() method, all bits are set to zero.
4.4. Getting Bits
So far, we used the get(index) method quite extensively. When the requested bit index is set, then this method will return *true*. Otherwise, it’ll return *false*:
bitSet.set(42);assertThat(bitSet.get(42)).isTrue(); assertThat(bitSet.get(43)).isFalse();Similar to set and clear, we can get a range of bit indices using the get(fromInclusive, toExclusive) method:
bitSet.set(10, 20); BitSet newBitSet = bitSet.get(10, 20); for (int i = 0; i < 10; i++) {assertThat(newBitSet.get(i)).isTrue(); }As shown above, this method returns another BitSet in the [20, 30) range of the current one. That is, index 20 of the bitSet variable is equivalent to index zero of the newBitSet variable.
4.5. Flipping Bits
To negate the current bit index value, we can use the *flip(index)* method. That is, it’ll turn true values to false and vice versa:
bitSet.set(42); bitSet.flip(42); assertThat(bitSet.get(42)).isFalse();bitSet.flip(12); assertThat(bitSet.get(12)).isTrue();Similarly, we can achieve the same thing for a range of values using the flip(fromInclusive, toExclusive) method:
bitSet.flip(30, 40); for (int i = 30; i < 40; i++) {assertThat(bitSet.get(i)).isTrue(); }4.6. Length
There are three length-like methods for a BitSet. The *size()* method returns the number of bits the internal array can represent. For instance, since the no-arg constructor allocates a long[] array with one element, then the size() will return 64 for it:
BitSet defaultBitSet = new BitSet(); assertThat(defaultBitSet.size()).isEqualTo(64);With one 64-bit number, we can only represent 64 bits. Of course, this will change if we pass the number of bits explicitly:
BitSet bitSet = new BitSet(1024); assertThat(bitSet.size()).isEqualTo(1024);Moreover, the *cardinality()* method represents the number of set bits in a *BitSet*:
assertThat(bitSet.cardinality()).isEqualTo(0); bitSet.set(10, 30); assertThat(bitSet.cardinality()).isEqualTo(30 - 10);At first, this method returns zero as all bits are false. After setting the [10, 30) range to true, then the cardinality() method call returns 20.
Also, the *length()* method returns the one index after the index of the last set bit:
assertThat(bitSet.length()).isEqualTo(30); bitSet.set(100); assertThat(bitSet.length()).isEqualTo(101);At first, the last set index is 29, so this method returns 30. When we set the index 100 to true, then the length() method returns 101. It’s also worth mentioning that this method will return zero if all bits are clear.
Finally, the isEmpty() method returns false when there is at least one set bit in the BitSet. Otherwise, it’ll return true:
assertThat(bitSet.isEmpty()).isFalse(); bitSet.clear(); assertThat(bitSet.isEmpty()).isTrue();總結
以上是生活随笔為你收集整理的Java位操作:如何将long类型的指定位设置为0或1?How to set/unset a bit at specific position of a long?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试必会系列 - 5.3 LVS负载均衡
- 下一篇: leetcode 415. 字符串相加(