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 LSB

to erase a bit use:

x &= ~0b1; // unset LSB bit (if set)
x &= ~0b10; // unset 2nd bit from LSB

to 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 bit

However, 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 LSB

Or to unset:

x &= ~((1 << y) | (1 << z)); // unset yth and zth bit

Or 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?相关推荐

  1. java中小数后加f_在 Java 中,小数默认为 ,如果要指定 类型请在小数后加 F/f 。_学小易找答案...

    [填空题]Java 语言采用双字节的 编码. [单选题]马斯洛需要层次论所提出的5种需要:生理需要.安全需要.归属需要.( ).自我实现需要 [填空题]String s= " abc &qu ...

  2. java的数据类型、变量类型笔记总结

    1. 引用类型 在Java中,引用类型的变量非常类似于C/C++的指针.引用类型指向一个对象,指向对象的变量是引用变量.这些变量在声明时被指定为一个特定的类型,比如 Employee.Puppy 等. ...

  3. java字节数_Java各种类型占用的字节数

    数据类型 大小(二进制位数) 范围 默认值 byte(字节) 8 -128 - 127 0 shot(短整型) 16 -32768 - 32768 0 int(整型) 32 -2147483648-2 ...

  4. java类型转换答案,在java中支持两种类型的类型转换,自动类型转换和强制类型转换。父类转化为子类需要强制转换。...

    在java中支持两种类型的类型转换,自动类型转换和强制类型转换.父类转化为子类需要强制转换. 更多相关问题 计算机病毒通过()传染扩散得极快,危害最大. 当一个现象的数量由小变大,另一个现象的数量相反 ...

  5. java中检查性异常类_Java异常处理、java语言推崇使用检查类型异常

    异常处理是java语言的重要特性之一,<Three Rules for effective Exception Handling>一文中是这么解释的:它主要帮助我们在debug的过程中解决 ...

  6. java位操作_关于java按位操作运算

    <1>.在了解位移之前,先了解一下正数和负数的二进制表示形式以及关系: 举例15和-15: 15 的原码: 00000000 00000000 00000000 00001111 补码: ...

  7. Java获取泛型类的实际类型的实例

    文章目录 泛型速解 强类型 共用性 继承泛型父类获取具体类型的实例 泛型速解 泛型是类型的参数. 强类型 在JDK中,最常见的的用法就是容器类的元素类型的指定.以List为例,通过List<元素 ...

  8. java中两种异常类型_Java中的三种异常类型

    java中两种异常类型 Errors are the bane of users and programmers alike. Developers obviously don't want thei ...

  9. scala和java类_Scala(和Java)中的类和类型有什么区别?

    当你说"打字"时,我会假设你的意思是静态类型.但我很快就会讨论动态类型. 静态类型是程序的一部分的属性,可以静态证明(静态意味着"不运行它").在静态类型语言中 ...

最新文章

  1. 454. 4Sum II ——查找本质:hash最快,二分次之
  2. kafka分区停留在UnderReplicated状态
  3. 实战经验:如何定位控制文件热点块,即读取延迟高的块所在的ASM磁盘
  4. 「项目已被 macOS 使用,不能打开」的处理办法
  5. OpenCV的第一个小程序:读取图像并显示
  6. php 旅游网毕业论文,旅游网站毕业设计论文(优质范文6篇)
  7. UEFI开发与调试---文件操作
  8. st计算机编程语言,SoMAChineST编程语言介绍.pdf
  9. 生活中的逻辑谬误03.滑坡谬误
  10. 【​观察】做好数据到介质的连接者 新数据时代浪潮存储的行与思
  11. 自动化情侣微信早安信息定时推送
  12. select 函数用法
  13. 如何快速掌握技术和知识点
  14. 计算机网络实验IP数据报分片,实验报告三IP数据分片.doc
  15. 24道ES必知必会的面试题整理一波,从早上卷起来
  16. 有趣的数学问题-鸽巢原理
  17. Qt 网络发送带中文字符串
  18. C++ LeetCode简单程序:罗马数字转整数
  19. NVIDIA 显卡介绍
  20. 智能辅助标注——数据标注领域新突破

热门文章

  1. 中石油训练赛 - 位置(模拟+思维)
  2. 二叉树前序遍历python输出_Python 二叉树查找 前序 中序 后序遍历
  3. pythonrequests解析_Python requests获取网页常用方法解析
  4. 排序算法-07归并排序(python实现)
  5. 数据分析与挖掘实战-窃电漏电用户的发现
  6. lpt算法c语言程序,LPT算法的性能(近似).ppt
  7. C++开发中的pImpl方法
  8. UDT协议实现分析——连接的建立
  9. python新式类和经典类的区别?
  10. 面试指南|GO高性能编程精华PDF