jdk源码解析--BitSet类

Posted 我的IT技术路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdk源码解析--BitSet类相关的知识,希望对你有一定的参考价值。

Bitset类创建一种特殊类型的数组来保存位值。BitSet中数组大小会随需要增加。Bitset的每一个元素都有一个boolean值,每个值相互独立,并且都有一个非负整数指引。Jdk大概是上面那样介绍这个类的,好吧,现在我们主要看下其具体的实现逻辑。

先看下这个类的实现基本框架:

1. public class BitSet implements Cloneable, java.io.Serializable {  

2.     private final static int ADDRESS_BITS_PER_WORD = 6;//一个long型对应6个字节  

3.     private final static int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;//初始化长度  

4.     private final static int BIT_INDEX_MASK = BITS_PER_WORD - 1;  

5.     private static final long WORD_MASK = 0xffffffffffffffffL;  

6.     private long[] words;//内部使用long存入每个位集  

7.     private transient int wordsInUse = 0;//words数组已经使用的个数  

8.     private transient boolean sizeIsSticky = false;//是否指定words数组的大小  

9.     public BitSet() {  

10.         initWords(BITS_PER_WORD);  

11.         sizeIsSticky = false;  

12.     }  

13.     public BitSet(int nbits) {  

14.         // 不能小于0  

15.         if (nbits < 0)  

16.             throw new NegativeArraySizeException("nbits < 0: " + nbits);  

17.   

18.         initWords(nbits);//初始化长度  

19.         sizeIsSticky = true;  

20.     }  

21. }  

实现的函数逻辑:

Valueof:这个函数有几种实现方法,分别是将Long类,Byte类型,相应的buffer类型转换成BitSet类。

1. public static BitSet valueOf(long[] longs) {  

2.         int n;  

3.         for (n = longs.length; n > 0 && longs[n - 1] == 0; n--)//定位到数组中不为0的位置  

4.             ;  

5.         return new BitSet(Arrays.copyOf(longs, n));//创建一个新的BitSet  

6.     }  

1. public static BitSet valueOf(ByteBuffer bb) {  

2.         bb = bb.slice().order(ByteOrder.LITTLE_ENDIAN);  

3.         int n;  

4.         for (n = bb.remaining(); n > 0 && bb.get(n - 1) == 0; n--)//将0去除掉  

5.             ;  

6.         long[] words = new long[(n + 7) / 8];//计算words的长度,并初始化  

7.         bb.limit(n);  

8.         int i = 0;  

9.         while (bb.remaining() >= 8)//大于8,直接取出long类型  

10.             words[i++] = bb.getLong();  

11.         for (int remaining = bb.remaining(), j = 0; j < remaining; j++)//剩余不满8处理  

12.             words[i] |= (bb.get() & 0xffL) << (8 * j);  

13.         return new BitSet(words);  

14.     }  

Flip:BitSet当前位置的补码

1. public void flip(int bitIndex) {  

2.         if (bitIndex < 0)  

3.             throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);  

4.   

5.         int wordIndex = wordIndex(bitIndex);//将bitindex转换到wordindex  

6.         expandTo(wordIndex);//扩容  

7.   

8.         words[wordIndex] ^= (1L << bitIndex);//求补  

9.   

10.         recalculateWordsInUse();//重新计算  

11.         checkInvariants();//校验  

12.     }  

13. private static int wordIndex(int bitIndex) {  

14.         return bitIndex >> ADDRESS_BITS_PER_WORD;  

15.     }  

16. private void expandTo(int wordIndex) {  

17.         int wordsRequired = wordIndex+1;  

18.         if (wordsInUse < wordsRequired) {//系统扩容  

19.             ensureCapacity(wordsRequired);  

20.             wordsInUse = wordsRequired;  

21.         }  

22.     }  

23. private void ensureCapacity(int wordsRequired) {  

24.         if (words.length < wordsRequired) {  

25.             // Allocate larger of doubled size or required size  

26.             int request = Math.max(2 * words.length, wordsRequired);//扩容,2倍或者是最大长度  

27.             words = Arrays.copyOf(words, request);//系统拷贝  

28.             sizeIsSticky = false;  

29.         }  

30.     }  

31. private void recalculateWordsInUse() {//重新计算已经使用的长度  

32.         // Traverse the bitset until a used word is found  

33.         int i;  

34.         for (i = wordsInUse-1; i >= 0; i--)//从后往前查找到不为0的位置  

35.             if (words[i] != 0)  

36.                 break;  

37.   

38.         wordsInUse = i+1// 已经使用的大小  

39.     }  

40. private void checkInvariants() {//校验  

41.         assert(wordsInUse == 0 || words[wordsInUse - 1] != 0);  

42.         assert(wordsInUse >= 0 && wordsInUse <= words.length);  

43.         assert(wordsInUse == words.length || words[wordsInUse] == 0);  

44.     }  

Set:将指定的位置设置为true

1. public void set(int bitIndex) {  

2.         if (bitIndex < 0)  

3.             throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);  

4.   

5.         int wordIndex = wordIndex(bitIndex);//获取位置  

6.         expandTo(wordIndex);//扩容  

7.   

8.         words[wordIndex] |= (1L << bitIndex); // 设置为true  

9.   

10.         checkInvariants();//校验  

11.     }  

Clear:将指定位置设置为false

1. public void clear(int fromIndex, int toIndex) {  

2.         checkRange(fromIndex, toIndex);//检验范围  

3.   

4.         if (fromIndex == toIndex)//如果头尾相等  

5.             return;  

6.   

7.         int startWordIndex = wordIndex(fromIndex);//找到开始点  

8.         if (startWordIndex >= wordsInUse)  

9.             return;  

10.   

11.         int endWordIndex = wordIndex(toIndex - 1);//找到末尾点  

12.         if (endWordIndex >= wordsInUse) {  

13.             toIndex = length();  

14.             endWordIndex = wordsInUse - 1;  

15.         }  

16.   

17.         long firstWordMask = WORD_MASK << fromIndex;  

18.         long lastWordMask  = WORD_MASK >>> -toIndex;  

19.         if (startWordIndex == endWordIndex) {  

20.             //如果只有一个字节  

21.             words[startWordIndex] &= ~(firstWordMask & lastWordMask);  

22.         } else {  

23.             // 多个字节  

24.             // 处理第一个字节  

25.             words[startWordIndex] &= ~firstWordMask;  

26.   

27.             // 处理中间字节  

28.             for (int i = startWordIndex+1; i < endWordIndex; i++)  

29.                 words[i] = 0;  

30.   

31.             // 处理最后一个字节  

32.             words[endWordIndex] &= ~lastWordMask;  

33.         }  

34.   

35.         recalculateWordsInUse();//重新计算使用的个数  

36.         checkInvariants();//校验  

37.     }  

Get:获取指定位置的值

1. public boolean get(int bitIndex) {  

2.         if (bitIndex < 0)  

3.             throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);  

4.   

5.         checkInvariants();//校验  

6.   

7.         int wordIndex = wordIndex(bitIndex);//获取值  

8.         return (wordIndex < wordsInUse)//如果是已用范围内  

9.             && ((words[wordIndex] & (1L << bitIndex)) != 0);//取出值不为0   

10.     }  

nextSetBit:返回从指定位置开始的第一个true的位置

1. public int nextSetBit(int fromIndex) {  

2.         if (fromIndex < 0)  

3.             throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);  

4.   

5.         checkInvariants();//检验  

6.   

7.         int u = wordIndex(fromIndex);//求出index对应的位子  

8.         if (u >= wordsInUse)//如果大于已经使用的  

9.             return -1;  

10.   

11.         long word = words[u] & (WORD_MASK << fromIndex);  

12.   

13.         while (true) {  

14.             if (word != 0)//找到不为 0的值  

15.                 return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);  

16.             if (++u == wordsInUse)//如果没找到  

17.                 return -1;  

18.             word = words[u];  

19.         }  

20.     }  

nextClearBit:从指定位置返回第一个false的值

previousSetBit:从指定位置之前返回第一个true的值

previousClearBit:从指定位置之前返回第一个false的值,这几个函数和上面的实现类似,读者自行解读。

Length

1. public int length() {  

2.         if (wordsInUse == 0)  

3.             return 0;  

4.   

5.         return BITS_PER_WORD * (wordsInUse - 1) +  

6.             (BITS_PER_WORD - Long.numberOfLeadingZeros(words[wordsInUse - 1]));//返回计算的长度  

7.     }  

Intersects:返回两个bitset是否有相同的位置为true

1. public boolean intersects(BitSet set) {  

2.         for (int i = Math.min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--)//取两者的最小值开始  

3.             if ((words[i] & set.words[i]) != 0)//如果两个值都是true  

4.                 return true;  

5.         return false;  

6.     }  

Cardinality统计bitsettrue的数字

1. public int cardinality() {  

2.         int sum = 0;  

3.         for (int i = 0; i < wordsInUse; i++)  

4.             sum += Long.bitCount(words[i]);//累计true的位置  

5.         return sum;  

6.     }  

And:逻辑与

1. public void and(BitSet set) {  

2.         if (this == set)  

3.             return;  

4.   

5.         while (wordsInUse > set.wordsInUse)//先将多余的位置置为false  

6.             words[--wordsInUse] = 0;  

7.   

8.         // Perform logical AND on words in common  

9.         for (int i = 0; i < wordsInUse; i++)//进行与操作  

10.             words[i] &= set.words[i];  

11.   

12.         recalculateWordsInUse();  

13.         checkInvariants();  

14.     }  

Or,xor,andnot实现类似,注意andnot是与已知的bitset取反后按位与。剩下的hashcode,equalsclone等基本方法,实现相对简单,读者可自行查看源码。

Stream:返回的是对应的整型流

1. public IntStream stream() {//转换为对应的整型流  

2.         class BitSetIterator implements PrimitiveIterator.OfInt {//迭代器  

3.             int next = nextSetBit(0);  

4.   

5.             @Override  

6.             public boolean hasNext() {  

7.                 return next != -1;  

8.             }  

9.   

10.             @Override  

11.             public int nextInt() {  

12.                 if (next != -1) {  

13.                     int ret = next;  

14.                     next = nextSetBit(next+1);  

15.                     return ret;  

16.                 } else {  

17.                     throw new NoSuchElementException();  

18.                 }  

19.             }  

20.         }  

21.   

22.         return StreamSupport.intStream(  

23.                 () -> Spliterators.spliterator(  

24.                         new BitSetIterator(), cardinality(),  

25.                         Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED),  

26.                 Spliterator.SIZED | Spliterator.SUBSIZED |  

27.                         Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED,  

28.                 false);  

29.     }  

 


以上是关于jdk源码解析--BitSet类的主要内容,如果未能解决你的问题,请参考以下文章

jdk源码解析--LongAdder类

jdk源码解析--String 类

jdk源码解析--WeakReference/softReference类

jdk源码解析--Writer类

JDK1.8 动态代理机制及源码解析

jdk源码解析--ThreadPoolExecutor类