Effective Java 第三版——36. 使用EnumSet替代位属性
Tips
《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化。
在这里第一时间翻译成中文版。供大家学习分享之用。
36. 使用EnumSet替代位属性
如果枚举类型的元素主要用于集合中,一般来说使用int枚举模式(条目 34),下面将2的不同倍数赋值给每个常量:
// Bit field enumeration constants - OBSOLETE!
public class Text {
public static final int STYLE_BOLD = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 1; // 2
public static final int STYLE_UNDERLINE = 1 << 2; // 4
public static final int STYLE_STRIKETHROUGH = 1 << 3; // 8
// Parameter is bitwise OR of zero or more STYLE_ constants
public void applyStyles(int styles) { ... }
}
这种表示方式允许你使用按位或(or)运算将几个常量合并到一个称为位属性(bit field)的集合中:
text.applyStyles(STYLE_BOLD | STYLE_ITALIC);
位属性表示还允许你使用按位算术有效地执行集合运算,如并集和交集。 但是位属性具有int枚举常量等的所有缺点。 当打印为数字时,解释位属性比简单的int枚举常量更难理解。 没有简单的方法遍历所有由位属性表示的元素。 最后,必须预测在编写API时需要的最大位数,并相应地为位属性(通常为int或long)选择一种类型。 一旦你选择了一个类型,你就不能超过它的宽度(32或64位)而不改变API。
一些程序员使用枚举优于int常量,当他们需要传递常量集合时仍然使用位属性。 没有理由这样做,因为存在更好的选择。 java.util包提供了EnumSet
类来有效地表示从单个枚举类型中提取的值集合。 这个类实现了Set接口,提供了所有其他Set实现的丰富性,类型安全性和互操作性。 但是在内部,每个EnumSet都表示为一个位矢量(bit vector)。 如果底层的枚举类型有64个或更少的元素,并且大多数情况下,整个EnumSet
用单个long表示,所以它的性能与位属性的性能相当。 批量操作(如removeAll和retainAll)是使用按位算术实现的,就像你为位属性手动操作一样。 但是完全避免了手动位混乱的丑陋和错误倾向:EnumSet
为你做了很大的努力。
下面是前一个使用枚举和枚举集合替代位属性的示例。 它更短,更清晰,更安全:
// EnumSet - a modern replacement for bit fields
public class Text {
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
类提供了一组丰富的静态工厂,可以轻松创建集合,其中一个代码如下所示:
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
请注意,applyStyles
方法采用Set<Style>
而不是EnumSet<Style>
参数。 尽管所有客户端都可能会将EnumSet
传递给该方法,但接受接口类型而不是实现类型通常是很好的做法(条目 64)。 这允许一个不寻常的客户端通过其他Set实现的可能性。
总之,仅仅因为枚举类型将被用于集合中,所以没有理由用位属性来表示它。 EnumSet
类将位属性的简洁性和性能与条目 34中所述的枚举类型的所有优点相结合。EnumSet
的一个真正缺点是,它不像Java 9那样创建一个不可变的EnumSet
,但是在即将发布的版本中可能会得到补救。 同时,你可以用Collections.unmodifiableSet
封装一个EnumSet
,但是简洁性和性能会受到影响。
Effective Java 第三版——36. 使用EnumSet替代位属性的更多相关文章
- Effective Java 第三版——37. 使用EnumMap替代序数索引
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- 《Effective Java 第三版》目录汇总
经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...
- 《Effective Java 第三版》新条目介绍
版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...
- Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——32.合理地结合泛型和可变参数
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——46. 优先考虑流中无副作用的函数
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java第三版(一) ——用静态工厂代替构造器
此文做为<Effective Java>系列的第一篇,所以有必要大概说下此书的特点,当然很多人可能都看过,毕竟是有着Java四大名著之一的大名在外,不过总会有萌新不了解,例如我!<E ...
- Effective Java 第三版——3. 使用私有构造方法或枚类实现Singleton属性
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——7. 消除过期的对象引用
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
随机推荐
- hdu3261
题意: 求至少出现k次的最长字符串(可重复) 题解: 后缀数组维护height数组只要找连续k个的最小值 代码: #include <cstdio> #include <algori ...
- Codeforces Round #319 (Div. 2) D - Invariance of Tree
Invariance of Tree 题目大意:给你一个有1-n组成的序列p,让你构造一棵树,如果节点a和b之间有一条边,则p[a]和p[b]之间也有一条边. 思路:没啥思路,看了题解菜爆. 我们可以 ...
- Windows 7下载安装 Visual C++ 6.0(VC6) 全程图解
说实话我也一直没有试过,所以也想当然的认为Win7下就不能安装VC6,压根就100%不兼容?一直使用高版本的VS(如VS2008和现在用的VS2010)的我今天亲身在Win7下安装一次试试. 注:文中 ...
- POJ1417 True Liars 并查集 动态规划 (种类并查集)
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1417 题意概括 有一群人,p1个好人,p2个坏人. 他们说了n句话.(p1+p2<=600,n ...
- 【Java】 剑指offer(62) 圆圈中最后剩下的数字
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 0, 1, …, n-1这n个数字排成一个圆圈,从数字0开始每 ...
- Map的知识点梳理(不包含collections工具类)
一:基础公共方法(map不再是简单的加索引,可以直接命名key,通过key进行遍历) 1.常见的map子类 HashTable:底层是哈希表结构.不允许null键和null值,线程同步 HashMap ...
- 分布式系统缓存系列之guava cache
guava是google的一个开源java框架,其github地址是 https://github.com/google/guava.guava工程包含了若干被Google的 Java项目广泛依赖 ...
- Django 学习第一天——django 基本介绍和环境搭建
web 应用设计模式(MTV MVC): MTV: M:models 模型:负责业务数据对象与数据库对象: T:templates 模板:负责如何把数据展示给用户: V:views 视图:负责业务逻辑 ...
- 开始使用Reflection
用于 reflection 的类,如 Method,可以在 java.lang.relfect 包中找到.使用这些类的时候必须要遵循三个步骤:第一步是获得你想操作的类的 java.lang.Class ...
- 2827: 千山鸟飞绝 非旋treap
国际惯例的题面:看起来很不可做的样子,我们先来整理一下题意吧.就是,维护每个点曾经拥有过的最大的两个属性值,支持把点的位置移动.我们用map对每个位置进行离散化,对每个位置建立一个平衡树.为了方便分离 ...