zl程序教程

您现在的位置是:首页 >  工具

当前栏目

EnumSet源码分析

源码 分析
2023-09-14 08:57:57 时间
1、内部元素为枚举; 2、内部表示为位向量,使用“位标志”的替换形式。(类似0x1000000,按bit存储,用位运算进行相关操作); 3、全部是静态方法static; 4、根据传入的枚举类型判断组成长度,小于等于64则返回RegularEnumSet,否则JumboEnumSet。
/**
* Creates an empty enum set with the specified element type.
*/
public static E extends Enum E EnumSet E noneOf(Class E elementType) {
Enum ? [] universe = getUniverse(elementType);
if (universe == null)
throw new ClassCastException(elementType + " not an enum");

if (universe.length = 64)
return new RegularEnumSet (elementType, universe);
else
return new JumboEnumSet (elementType, universe);
}
------------------------------------------------------------------------------


RegularEnumSet
5、add源码
/**
* Adds the specified element to this set if it is not already present.
* @throws NullPointerException if tt e /tt is null
*/
public boolean add(E e) {
typeCheck(e); //
long oldElements = elements;
elements |= (1L ((Enum ? )e).ordinal());
return elements != oldElements;
}
每个枚举值都对应着自己的ordinal,第一个枚举值的ordinal为0,第二个为1,以此类推。
看看RegularEnumSet中elements的定义吧。关键点:位向量、2^k bit则说明存在该元素(每位都为1)。
/**
* Bit vector representation of this set. The 2^k bit indicates the
* presence of universe[k] in this set.
*/
private long elements = 0L;
1、取枚举值的ordinal,初始为0; 2、1 ordinal ; 3、与elements做 |= 运算。 a.添加ordinal为0的枚举值,则计算后elements为1 b.添加ordinal为1的枚举值,则计算后elements为( 01|10 ) = 11(B) c.添加ordinal为2的枚举值,则计算后elements为(011 | 100) = 111     So,EnumSet就是用long型来存储枚举,支持64位(long64位)。 而ordinal是个什么鬼呢?     是Enum抽象类的一个属性,源码如下:
private final int ordinal;
/**
* Returns the ordinal of this enumeration constant (its position
* in its enum declaration, where the initial constant is assigned
* an ordinal of zero).
*/
public final int ordinal() {
return ordinal;
}
注意看:这里被调用的是ordinal()方法,以便于后续版本更新时,保持良好的兼容性(即使计算方式改变了,也不会影响原来的工程)。 6、contains 源码

public boolean contains(Object e) {
if (e == null)
return false;
Class ? eClass = e.getClass();
if (eClass != elementType eClass.getSuperclass() != elementType)
return false;
return (elements (1L ((Enum ? )e).ordinal())) != 0;
}
1、1L ((Enum)e).ordinal() ; 2、与elements做 运算。     ordinal为2,则elements为111(B); 1L ((Enum ? )e).ordinal() 值为 100(B); elements (1L ((Enum ? )e).ordinal()) = 111(B) 111不等于0,说明包含该元素。
利用 long 和 位运算 实现EnumSet的快速存储和判断。 7、size源码
public int size() {
return Long.bitCount(elements);
}
bitCount返回的是参数二进制码中1的个数。如110(B)返回2。 源码如下,太过高深,在此就不剖析了。  public static int bitCount(long i)     {         i -= i   1   6148914691236517205L;         i = (i   3689348814741910323L) + (i   2   3689348814741910323L);         i = i + (i   4)   1085102592571150095L;         i += i          i += i          i += i          return (int)i   127;     }
/**
* Bit vector representation of this set. The ith bit of the jth
* element of this array represents the presence of universe[64*j +i]
* in this set.
*/
private long elements[];
由RegularEnumSet中的long型转为long型数组。
public boolean add(E e) {
typeCheck(e);
int eOrdinal = e.ordinal();
int eWordNum = eOrdinal 6; // 无符号右移,高位补0,去掉低位
// eWordNum 表示 eOrdinal 的高位
 // 左移乘2,右移除2,移位位数对32取模( i 33 等价于 i 1)
long oldElements = elements[eWordNum];
elements[eWordNum] |= (1L eOrdinal); // 核心,Enum前64个元素全部放在elements[0]中
 // elements[0]的值的二进制 第i位为1,则表示Enum的第i个元素存在于该集合,
 // 引申[64*j +i],elements[j]的第i个元素为1。
boolean result = (elements[eWordNum] != oldElements);
if (result)
size++;
return result;
}



public boolean contains(Object e) {
if (e == null)
return false;
Class ? eClass = e.getClass();
if (eClass != elementType eClass.getSuperclass() != elementType)
return false;
int eOrdinal = ((Enum ? )e).ordinal();
return (elements[eOrdinal 6] (1L eOrdinal)) != 0;
}


NOte:正数一直无符号右移,将变为0。

LinkedList源码分析 Java中List是一个必须要掌握的基础知识,List是一个接口,实现List接口的基础类有很多,其中最具有代表性的两个:ArrayList和LinkedList。
java集合系列(3)ArrayList(源码分析) 这篇文章开始介绍ArrayList。ArrayList基本上是我们在平时的开发当中,使用最多的一个集合类了,它是一个其容量能够动态增长的动态数组。所以这篇文章,旨在从源码的角度进行分析和理解。为了使得文章更加有条理,还是先给出这篇文章的大致脉络: 首先,ArrayList的基本介绍和源码API(只给出方法分析,重要的方法给出详细代码)。 然后,介绍遍历ArrayList的几种方式 接下来,叙述一下ArrayList与其他集合关键字的区别和优缺点 最后,进行一个总结
java集合系列(2)Collection(源码分析) 前一篇博客,我们基本上认识了集合,从这篇博客开始参考API文档,和源码分析,详细的介绍每个集合类的使用,力求在源码的角度来分析,加深理解。
【集合框架】JDK1.8源码分析HashSet && LinkedHashSet(八) 分析完了List的两个主要类之后,我们来分析Set接口下的类,HashSet和LinkedHashSet,其实,在分析完HashMap与LinkedHashMap之后,再来分析HashSet与LinkedHashSet,就会变成异常简单,下面开始进行分析。
【集合框架】JDK1.8源码分析之ArrayList(六) 分析了Map中主要的类之后,下面我们来分析Collection下面几种常见的类,如ArrayList、LinkedList、HashSet、TreeSet等。下面通过JDK源码来一起分析ArrayList底层是如何实现的。(PS:把JVM看完了之后终于可以有成片的时间来阅读源码了,感觉简直不能更爽)。
Java集合源码分析之超级接口:Collection Collection Collection是List、Queue和Set的超集,它直接继承于Iterable,也就是所有的Collection集合类都支持for-each循环。除此之外,Collection也是面向接口编程的典范,通过它可以在多种实现类间转换,这也是面向对象编程的魅力之一。 在阅读源码前,我们可以先自行想象一下,如果我们想封装下数组或链表以方便操作,我们需要封装哪些功能呢?比如:统计大小、插入或删除数据、清空、是否包含某条数据,等等。而Collection就是对这些常用操作进行提取,只是其很全面、很通用。下面我们看看它都提供了哪些方法。
Java集合干货——ArrayList源码分析 ArrayList源码分析 在之前的文章中我们提到过ArrayList,ArrayList可以说是每一个学java的人使用最多最熟练的集合了,但是知其然不知其所以然。关于ArrayList的具体实现,一些基本的都也知道,譬如数组实现,线程不安全等等,但是更加具体的就很少去了解了,例如:初始化的长度,扩容等。
zxiaofan 【zxiaofan.com】Life is all about choices!生命不息,学习不止。