用EnumSet代替位域
用EnumSet代替位域
如果一个枚举类型的元素主要用在集合中,一般使用int枚举模式,将2的不同倍数赋予每个常量:
// Bit field enumeration constants - OBSOLETE
public class Test{
public static final int STYLE_BOLD = 1<<0;//1
public static final int STYLE_INALIC = 1<<2;//2
public static final int STYLE_UNDERLINE = 1<<3;//4
public static final int STYLE_STRIKETHROUGH = 1<<4;//8
//Parameter is bitwise OR of zero or more STYLE_ constants
public void applyStyles(int styles){...}
}
这种表示法让你用OR位运算将几个常量合并到一个集合中,称作位域:
test.applyStyles(STYLE_BOLD | STYLE_INALIC);
位域表示法也允许利用位操作,有效地执行像union(并集)和intersection(交集)这样的操作集合。但位域有着int枚举常量的所有缺点,甚至更多。当位域以数字形式打印时,翻译位域比翻译简单的int枚举常量要困难的多。甚至要遍历域表示的所有元素也没有很容易的方法。
有些程序员优先使用枚举而非int常量,他们在需要传递多组常量集合时,仍然倾向于使用位域。其实没有理由这么做,因为还有更好的方法代替。Java.util包还提供了EnumSet类来有效的表示从单个枚举类型中提取的多个值的多个集合。这个类实现了Set接口,提供了丰富的功能、类安全性,以及可以从任何其他Set实现中得到的互用性。但是在内部具体实现上,每个EnumSet内容都表示为位矢量。如果底层的枚举类型有64个或者更少的元素——大多如此——整个EnumSet就是用单个long来表示,因此它的性能比得上位域的性能。批处理,如removerAll和retainAll,都是利用位算法来实现,就像手工替位域实现得那样。但是可以避免手工位操作时容易出现的错误以及不太雅观的代码,因为EnumSet替你完成了这项艰巨的工作。
下面是前一个范例改成用枚举代替位域后的代码,它更简单、更加清楚,也更加安全:
// EnumSet -a modern replacement for bit fields
public class Test{
public enum Style{BOLD, ITALIC, UNDERLINE, STRIKETHROUGH}
//Any Set could be passed in, but EnumSet is clearly best
public void applyStyles(Set<Style> styles){...}
}
下面是将EnumSet实例传递给applyStyles方法的客户端代码。EnumSet提供了丰富的静态工厂来创建集合,其中一个如这个代码所示:
test.applyStyles(EnumSet.of(Style.BOLD,Style.ITALIC));
注意applyStyles方法采用的是Set<Style>而非EnumSet<Style>。虽然看起来好像所有的客户端都可以将EnumSet传到这个方法,但是最好的还是接受接口类型而非接受实现类型。这是考虑到可能会有特殊的客户端要传递一些其他的Set实现,并且没有什么明显的缺点。
总而言之,正是因为枚举类型要用在集合(Set)中,所以没有理由用位域来表示它。EnumSet类位域的简介和性能优势及枚举类型的所有的优点于一身。实际上EnumSet有个缺点,即截至Java1.6发行版,它都无法创建不可变的EnumSet,但是这一点很可能在即将出现的版本中得到修复。同时可以用Collections.unmodifiableSet将EnumSet封装起来,但是简洁性和性能会受到影响。
ps:官方java 1.8API解释
Like most collection implementations, EnumSet is not synchronized. If multiple threads access an enum set concurrently, and at least one of the threads modifies the set, it should be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the enum set. If no such object exists, the set should be "wrapped" using the Collections.synchronizedSet(java.util.Set) method. This is best done at creation time, to prevent accidental unsynchronized access:
Set<MyEnum> s = Collections.synchronizedSet(EnumSet.noneOf(MyEnum.class));
用EnumSet代替位域的更多相关文章
- effective java——32用EnumSet代替位域
什么是位域?为什么用到它?先来看一个例子: public class Test { public static final byte STYLE_BOLD = 1<<0; // 1 pub ...
- 第32条:用EnumSet代替位域
如果一个枚举类型的元素主要用在集合中,一般使用int枚举模式,将2的不同倍数赋予每个常量: public class Text { public static final int STYLE_BOLD ...
- 位域(bit fields)简介
使用位域或位操作移动一个字节中的位 Java中EnumSet代替位域代码详解 关于位域的一些东西 深入理解Java枚举类型(enum) 位域是指信息在存储时,并不需要占用一个完整的字节, 而只需占几个 ...
- effective java 学习心得
目的 记录一下最主要学习心得,不然凭我这种辣鸡记忆力分分钟就忘记白看了... 用静态工厂方法代替构造器的最主要好处 1.不必每次都创建新的对象 Boolean.valueOf Long.valueOf ...
- Effective java笔记(五),枚举和注解
30.用enum代替int常量 枚举类型是指由一组固定的常量组成合法值的类型.在java没有引入枚举类型前,表示枚举类型的常用方法是声明一组不同的int常量,每个类型成员一个常量,这种方法称作int枚 ...
- 【Java基础】枚举和注解
在Java1.5版本中,引入了两个类型:枚举类型enum type和注解类型annotation type. Num1:用enum代替int常量 枚举类型enum type是指由一组固定的常量组成合法 ...
- Effective Java 读书笔记之五 枚举和注解
Java1.5中引入了两个新的应用类型家族,新的类为枚举类型,新的接口为注解类型. 一.用enum代替int常量 1.枚举值由一组固定的常量组成合法值的类型. 二.用实例域代替序数 1.不要根据枚举的 ...
- Effective Java 阅读笔记——枚举和注解
30:用enum代替int常量 当需要一组固定常量的时候,应该使用enum代替int常量,除了对于手机登资源有限的设备应该酌情考虑enum的性能弱势之外. 31:用实例域代替序数 应该给enum添加i ...
- [Effective Java]第六章 枚举和注解
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
随机推荐
- mongodb学习之:主从复制
在sql server能够做到读写分离,双机热备份和集群部署,这些在mongodb也能做到.首先来看主从复制.我们就在一台电脑上进行操作 第一步:分别建立master和slave两个文件夹 第二步:开 ...
- Jquery AJAX如何使用Promise/Deferred实现顺序执行?
有的时候有我有N个AJAX请求,第下个请求可能要依赖上个请求的返回值, 可以用 $.ajax("test1.php").then(function(data) { // data ...
- linux内核container_of宏定义分析
看见一个哥们分析container_of很好,转来留给自己看 一.#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMB ...
- target!
工作到现在也有8个月了,从学生时代想从事嵌入是开发,到工作中从事android开发,跨度还是比较大的:曾经想从事这些消费类电子产品的开发,想从一个用户变成一个生产者,但是真正进入到这一行之后,才知道在 ...
- bleve搜索引擎是支持基于field搜索的
Query String Query The query language query allows humans to describe complex queries using a simple ...
- 提高scroll性能
在DevTools中开始渲染,向下滑动一点点滚动条,然后停止滚动. 在结果中,注意frames总是在30ftps线上面,甚至都木有很接近69ftps线的(事实上帧执行的太缓慢以致于60ftps线在图上 ...
- windows下使用emacs+plink远程编辑erlang文件
1)plink.exe属于putty套件, 注册到环境变量;emacs的bin目录也要注册到环境变量中; 2)在.emacs中增加如下: (require 'tramp)(setq tramp-def ...
- Python: PS 滤镜--表面模糊
本文用 Python 实现 PS 滤镜中的表面模糊,具体的算法原理和效果可以参考之前的博客: http://blog.csdn.net/matrix_space/article/details/528 ...
- 「ZJOI2007」「LuoguP1169」棋盘制作(并查集
题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8×88 \times 88×8大小的黑白相间的方阵,对应八八六十四卦 ...
- HiddenHttpMethodFilter
操作步骤: 在web.xml中配置: 删除操作: 其他操作即为将DELETE换成INPUT/POST/GET