Java EnumSet工作原理初窥
EnumSet是Java枚举类型的泛型容器,Java既然有了SortedSet、TreeSet、HashSet等容器,为何还要多一个EnumSet<T>呢?答案肯定是EnumSet有一定的特性,举个例子,EnumSet的速度很快。其他特性就不一一列举了,毕竟本文的内容不是介绍EnumSet的特性。
首先以事实说话,存在这样一个EnumSet,它有50个枚举值T0~T49,将50个值插入到容器(HashSet、EnumSet)中,为一个操作,将50个枚举值移出做为第二个操作。把第一个和第二个操作执行的总时间设定为一个周期,拿HashSet操作的一个周期和EnumSet的一个周期做比较自然没什么意义,所以我们用50个周期的和做为比较,HashSet耗费9ms,EnumSet耗费4ms(这个结果只说明同样的操作EnumSet比HashSet更快,不做为其他参考依据,因为这个时间不是线程独占时间)。以下是代码和结果:
public class EnumSetTest{
private static EnumTest[] enumTestArr = EnumTest.values();
public static void main(String[] args) {
Set set = new HashSet<EnumTest>();
int i = 0;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println("HashSet...Begin " + df.format(new Date()));
while (i <= 1000) {
addEnumerate(set);
removeEnumerate(set);
i++;
}
System.out.println("HashSet...End " + df.format(new Date()));
EnumSet<EnumTest> enumSet = EnumSet.noneOf(EnumTest.class);
i = 0;
System.out.println("EnumSet...Begin " + df.format(new Date()));
while (i <= 1000) {
addEnumerate(enumSet);
removeEnumerate(enumSet);
i++;
}
System.out.println("EnumSet...End " + df.format(new Date()));
}
/*
* HashSet...Begin 2015-01-03 21:11:51.579
* HashSet...End 2015-01-03 21:11:51.588
* EnumSet...Begin 2015-01-03 21:11:51.589
* EnumSet...End 2015-01-03 21:11:51.593
* */
private static void addEnumerate(Set set) {
for (EnumTest t : enumTestArr) {
set.add(t);
}
}
private static void removeEnumerate(Set set) {
for (EnumTest t : enumTestArr) {
set.remove(t);
}
}
}
那为什么EnumSet比较快呢,EnumSet是一个抽象方法,本次测试是用到的EnumSet的实现RegularEnumSet,RegularEnumSet add方法的源码如下:
public boolean add(E e) {
typeCheck(e);
long oldElements = elements;
elements |= (1L << ((Enum)e).ordinal());
return elements != oldElements;
从Add方法的源码可以看出add方法实际只是对长整型数据element做了一个操作,也就是说EnumSet实际上将枚举值保存在一个长整型数据上。没个枚举值占用一bit。每次添加做的主要操作是1、类型检查 2、 添加枚举值 3、判断枚举值是否已经添加过了。
现在模拟一个场景来说明EnumSet工作原理。新建一个EnumSet(Set1),并向Set1中添加EnumTest.T3(ordinal:3),代码如下
EnumSet<EnumTest> set1 = EnumSet.noneOf(EnumTest.class);
set1.add(EnumTest.T3);

element本来有64个bit,这里就简略画了。这里有一个问题,就是枚举值的个数超过64个怎么办?超过64个了就用EnumSet的另一个实现JumboEnumSet。
本文到此就结束了,至于JumboEnumSet的工作原理和RegularEnumSet其他方法的工作原理请自行探索吧。所有源码都可以在http://grepcode.com/ 找到。
Java EnumSet工作原理初窥的更多相关文章
- 全面解读Java NIO工作原理(3)
全面解读Java NIO工作原理(3) 2011-12-14 10:31 Rollen Holt Rollen Holt的博客 我要评论(0) 字号:T | T JDK 1.4 中引入的新输入输出 ( ...
- 全面解读Java NIO工作原理(2)
全面解读Java NIO工作原理(2) 2011-12-14 10:31 Rollen Holt Rollen Holt的博客 我要评论(0) 字号:T | T JDK 1.4 中引入的新输入输出 ( ...
- Java虚拟机工作原理详解 (一)
一.类加载器 首先来看一下java程序的执行过程. 从这个框图很容易大体上了解java程序工作原理.首先,你写好java代码,保存到硬盘当中.然后你在命令行中输入 javac YourClassNam ...
- Java虚拟机工作原理详解
原文地址:http://blog.csdn.net/bingduanlbd/article/details/8363734 一.类加载器 首先来看一下java程序的执行过程. 从这个框图很容易大体上了 ...
- Java虚拟机工作原理具体解释
一.类载入器 首先来看一下java程序的运行过程. 从这个框图非常easy大体上了解java程序工作原理.首先,你写好java代码,保存到硬盘其中.然后你在命令行中输入 javac YourClass ...
- Java虚拟机工作原理
Java虚拟机工作原理 首先我想从宏观上介绍一下Java虚拟机的工作原理.从最初的我们编写的Java源文件(.java文件)是如何一步步执行的,如下图所示,首先Java源文件经过前端编译器(javac ...
- java复习要点(一)------- java语言的特点、java的工作原理、配置环境变量、java命令的使用
一.java语言的特点: (1)简单并面向对象 (2)鲁棒并安全: java语言在编译及运行程序时,都要进行严格的检查,防止不匹配问题的发生.如果引用一个非法类型,或执行一个非法类型操作,java减肥 ...
- Java HashMap工作原理及实现
Java HashMap工作原理及实现 2016/03/20 | 分类: 基础技术 | 0 条评论 | 标签: HASHMAP 分享到:3 原文出处: Yikun 1. 概述 从本文你可以学习到: 什 ...
- 全面解读Java NIO工作原理(4)
全面解读Java NIO工作原理(4) 2011-12-14 10:31 Rollen Holt Rollen Holt的博客 我要评论(0) 字号:T | T JDK 1.4 中引入的新输入输出 ( ...
随机推荐
- uLua学习之使用协程(终)
前言 今天是本系列的第六篇文章,也是最后一篇,我们来看看uLua中如何来实现协程吧.首先,让我们明确协程的概念.在百度百科上的是这样说的,协程更适合于用来实现彼此熟悉的程序组件,如合作式多任务,迭代器 ...
- python 学习之FAQ:find 与 find_all 使用
FAQ记录 1. 错误源码 错误源码如下 def fillUnivList(_html,_ulist): soup =BeautifulSoup(_html,'html.parser') fo ...
- Dll注入:注册表注入
在系统中每一个进程加载User32.dll时,会受到DLL_PROCESS_ATTACH通知,当User32.dll对其进行处理时,会取得注册表键值HKEY_LOCAL_MACHINE\Softwar ...
- HTML5新特性 video '►'
var play = document.createElement('button') play.setAttribute('title','play') play.innerHTML = '►' 创 ...
- checkbox 最多选两项
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- shell脚本,利用awk计算指定范围内的和。
期望得到结果如下: vivi 42800Tom 32500John 104500 解题方法如下: 1.利用数组来进行解题.
- 理解Express 中间件
Express 中间件 Express程序基本上是一系列中间件函数的调用.中间件就是一个函数, 接受 req.res.next几个参数. 中间件函数可以执行任何代码, 对请求和响应对象进行修改, 结束 ...
- vue 服务代理 调用第三方api
项目中前期需要调用第三方API来获取汇率.因为直接调用会有跨域的问题,所以使用来服务代理. 在config配置代理可以这样写: 而调用接口就可以这样写: 坑:配置完成后一直报500,开始怀疑人生.最后 ...
- SVN不显示状态图标
1,输入win+R,输入regedit,调出注册表信息 2,按下Ctrl+F,在注册表里搜索“ShellIconOverlayIdentifiers” 3,将TortoiseAdded.Tortois ...
- 洛谷P1048采药
这道题一看就知道是01背包,我门用f[i]来表示时间剩余i时的最大的价值 一共只有两种选择取或者不取,可以得到方程式f[i]=max(f[i],f[i-a[i]]+v[i])(a[i]是表示时间,v[ ...