BitSet的内部原理以及使用指南

深入学习Java基础知识
2021-05-17 14:29 · 阅读时长5分钟
小课

在Java开发中,我们一般使用boolean类型来存储布尔值(true/false),但是我们有没有想过一个boolean类型的值会占用1个byte的内存,但是其实我们只需要1bit的内存就可以表示true/false了,也就是说我们有很大部分内存浪费了,如果是大量存储的话,那浪费的内存数量就很可观了。

其实Java SDK中提供了BitSet来优化这个问题,只使用1bit来表示true/false,下面就来思考一下它是如何实现的。首先,在Java中是没有只占用1bit的数据类型,所以只能使用byte/int/short等类型来存储,再通过位运算来操作某个bit位,简单起见,我们使用byte类型来举例说明。一个byte类型占8bit,我们用一个byte来存储8个标识位,默认设置8个标识位都为0

byte seg = 0

seg对应8个bit位存储的值为

0 0 0 0 0 0 0 0 

一、设置标识位

如果要设置index=3的标识位为1,需要使用左移位运算<<和按位或运算|来实现

seg |= 1 << 3

执行完之后,seg对应8个bit位存储的值为

0 0 0 0 1 0 0 0

如果要设置index=7的标识位为1,执行类似的操作

seg |= 1 << 7

执行完之后,seg对应8个bit位存储的值为

1 0 0 0 1 0 0 0

二、清除标识位

假设当前seg对应8个bit位存储的值为

1 0 0 0 1 0 0 0

如果要清除index=3的标识位,需要使用左移位运算<<、按位非运算~和按位与运算&来实现

seg &= ~(1 << 3)

执行完之后,seg对应8个bit位存储的值为

1 0 0 0 0 0 0 0

如果要清除index=7的标识位,执行类似的操作

seg &= ~(1 << 7)

执行完之后,seg对应8个bit位存储的值为

0 0 0 0 0 0 0 0

三、获取标识位

假设当前seg对应8个bit位存储的值为

1 0 0 0 1 0 0 0

如果要获取index=3位置的标识位,需要使用左移位运算<<和按位与运算&来实现

boolean isTrue = (seg & 1 << 3) > 0

1 0 0 0 1 0 0 0

                               &

0 0 0 0 1 0 0 0

                               =

0 0 0 0 1 0 0 0

计算结果大于0,说明标识位是1,反之则为0

四、BitSet使用

BitSet内部的原理就是利用位运算来实现的,不过它不是使用byte类型来存储数据,而是用long类型,这样一个元素就能存储64bit,在寻找index的真实bit位存储位置时,需要用index除以64或者使用位运算右移6位,这些BitSet内部都已经封装好了,直接使用即可,需要注意点的是,BitSet不是线程安全的,如果要保证线程安全需要自己加锁处理

加载中...
bitset位运算