JDK源码阅读计划(Day12) BitSet

JDK11

BitMap原理&使用场景

用一个bit来存放一个状态的容器。由于对内存占用少,适合用于处理大规模数据和数据状态不多的情况。毕竟一个bit只对应两个状态。

BitMap 最简单的说明图,蓝色代表有值

图来自ref

假设原来有个int数组[1,2,3,6,7]需要用5*32bit=160bit来保存存储空间。

但如果把元素的值作为下标每个下标用一个bit来表示,如0表示不存在该元素,1表示存在。那么只需要在内存空间开辟一个bit大小为8的数组。

  • 场景一:

O(1)的海量数据的查重。

  • 场景二:

判断两个数组重复元素。原先方案需要做一个两层for循环,现在只需要两个bitMap做与操作。

  • 场景三:

如果数据分布不均匀,如数组是1,100,100000000,那么为了存储100000000需要开100000001个bit,造成较大空间浪费。可以使用roaring map

  • 场景四:

Bloom Filter的实现

类继承关系

public class BitSet implements Cloneable, Serializable

BitSet虽然叫做Set,在java.util包中,但事实上和Set,List这些接口一点关系都没有

重要成员

可以看到最重要BitSet本质上就是用一个long数组来存储bit的信息,默认每一个long可以存储64bit

 /*
     * BitSets are packed into arrays of "words."  Currently a word is
     * a long, which consists of 64 bits, requiring 6 address bits.
     * The choice of word size is determined purely by performance concerns.
     */
    private static final int ADDRESS_BITS_PER_WORD = 6;
    
    // 每个word所占的位数:64bit,(这里所谓的word就是long类型)
    private static final int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
    private static final int BIT_INDEX_MASK = BITS_PER_WORD - 1;
    
    /* Used to shift left or right for a partial word mask */
    private static final long WORD_MASK = 0xffffffffffffffffL;
    
    /**
     * The internal field corresponding to the serialField "bits".
     */
    /*
     * 存储word,其实就是存储位集中的bit
     * 在计算位的时候,需要从左到右取出word,并从右到左排列。
     */
    private long[] words;
    
    /**
     * The number of words in the logical size of this BitSet.
     */
    // 位集正在被使用的字的长度
    private transient int wordsInUse = 0;
    
    /**
     * Whether the size of "words" is user-specified.  If so, we assume
     * the user knows what he's doing and try harder to preserve it.
     */
    // 字的大小是否为用户指定
    private transient boolean sizeIsSticky = false;

构造函数

  • 默认构造函数

默认初始会为words数组分配一个元素

 /**
     * Creates a new bit set. All bits are initially {@code false}.
     */
    // 构造可以存储64个bit的位集(即1个word)
    public BitSet() {
   
        // 由给定的bit数量,构造一个匹配大小的long数组存储bit
        initWords(BITS_PER_WORD);
        
        sizeIsSticky = false;
    }

我们来看initWords,作用是根据bitSet的bit的大小来判断需要分配多少个word

 /*
     * 由给定的bit数量,构造一个匹配大小的long数组存储bit。
     * 这里会向上取整,比如输入60,则虽然不足64位,却也构造包含一个long的word数组。
     */
    private void initWords(int nbits) {
   
        // 计算指定索引处的bit所在的word的索引
        //64-1 =  1 1111
        int size = wordIndex(nbits - 1);
        words = new long[size + 1];
    }
/**
     * Given a bit index, return word index containing it.
     */
    // 计算指定索引处的bit所在的word的索引
    private static int wordIndex(int bitIndex) {
   
        //1 1111 >> 6 = 0 说明 0-63bit对应的word索引为0
        return bitIndex >> ADDRESS_BITS_PER_WORD;
    }
    

其他构造函数

// 构造至少可以存储nbits个bit的位集
    public BitSet(int nbits) {
   
        // nbits can't be negative; size 0 is OK
        if(nbits<0) {
   
            throw new NegativeArraySizeException("nbits < 0: " + nbits);
        }
    
        // 由给定的bit数量,构造一个匹配大小的long数组存储bit
        initWords(nbits);
    
        sizeIsSticky = true;
    }
    
    /**
     * Creates a bit set using words as the internal representation.
     * The last word (if there is one) must be non-zero.
     */
    // 构造可以存储words.length个word的位集,且该位集正在被使用
    private BitSet(long[] words) {
   
        this.words = words;
        this.wo
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值