Java 位域
Java位域
这个概念是在 Effective Java中了解到的, 可以通过EnumSet来代替位域这种方式表达.
并不是很常见的概念, 因此记录下.
如果在这之前恰好了解过 bitmap这种数据结构就更好了。
不了解也没有关系。
bitmap 就是用bit的每一位来代表一个特殊的状态值, 或者说标签属性等等.
举例来说, 8位的数值, 用 0000 0001 代表 北, 0000 0010 代表南, 0000 0100 代表西 依次类推.
那么当我们拿到一串bit, 如:
0100 0000 自然可以去对应的映射关系表中查找到 究竟是属于哪一种类型, 如果我们想同时传递两个数值呢?
只需要 0000 0011 这样就可以表示 北 南 两个方向了, 当然 至多可以表示 8个方向.
我们来试试这种表示方式:
public class Direction {
public static final short NORTH = 1;
public static final short SOUTH = 1 << 2;
public static final short WEST = 1 << 3;
public static final short EAST = 1 << 4;
public static final short SOUTH_EAST = 1 << 8;
}
在这里我只是简略的定义了其中5中.
那么可能会有一个问题, 既然使用 short来表示, 为什么不用 1 2 3 ... 8 来表示数据呢? 这样我们甚至都不需要2 的 8次方, 只需要 3位就能够表示所有数据了.
但是不妨让我们再来想一想, 在使用 1 ~ 8 的方式中如何同时传入多种状态呢?
在这里是不是必须使用 一个 short[] 去接收数据?
那么用位有什么好处呢?
void array(NORTH | SOUTH | SOUTH_EAST)
在方法的调用上 可以采用这种直观易懂且计算速度快的方式, 而在传入值 不难发现 最终只有一个值:
1000 0011
这一个数值即表示了包含了相应的三种状态.
而这就是 java中 位域的使用方式.
那么进一步来看, 当我们不再满足 8位 甚至需要更多种状态值的时候 可以切换到 int long 甚至于 bitmap. 接收无限位。
但仅仅是位域这种表示 我们仅仅支持 64种以下的状态类型, 因为 java种最长的基本类型 也就只有64位了。
那么继续来看看这种位域有什么缺陷呢?
使用int 类型 或 long类型, 没有办法加入一些自定义的东西, 通常情况下 在这种地方使用枚举是更好地选择。
否则的话所有的地方依然要使用 switch判断的方式, 另外由于 int定义为 static final 时 本身就是编译时常量,
如果有人依赖他, 将来即使这里的数值更新了, 比如删掉两三个, 即使不重新编译, 对方的class文件依然不会出错。 但事实上, 出错是一种必然。
就上面的例子来说, 我们想要返回所有的String 该怎么办?
必然是 switch case return "南" 类似的方式.
那么切换成枚举类型呢?
public enum EnumDirection {
NORTH("north"), EAST("east"), SOUTH("south"), WEST("south");
private final String name;
private EnumDirection(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
枚举类型的好处,不再赘述。
那与今天的主题, 位域有什么关系呢?
我们知道,位域的优点 占用内存小, 表示方便, 传递值方便, 性能高.
EnumSet, 让我抄一段描述:
这个类实现Set接口,提供了丰富的功能,类型安全性,以及可以从任何其他Set实现中得到的互用性。但是在内部具体的实现上,每个EnumSet内容都表示为位矢量。如果底层的枚举类型有64个或者更少的元素——大多数如此。整个EnumSet就用单个long来表示,因此它的性能比的上位域的性能。批处理,如removeAll和retainAll,都是利用位算法来实现的。就像手工替代位域实现得那样。
是的, 是位运算.
就看一段代码:
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;
}
我们关注到最后一行, 如上述EnumDirection, WEST 的 ordinal() 即是4, 也就意味着 它值在这里被理解为 1 << 4
而通过 elements 传入enumSet 的集合, 如:
EnumSet<EnumDirection> enumSet = EnumSet.of(EnumDirection.EAST, EnumDirection.NORTH);
不难获知 enumSet 的 elements值为 0000 0011 当然 这里是 long类型, 我只写了最后8位, 而
0000 0011 & 0000 1000 必然是等于 0的 因此 contains 返回false.
这是极其高效的方式. 而目的也正在于解决 int型 位域的种种弊端.
Java 位域的更多相关文章
- Spark案例分析
一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...
- effective java——32用EnumSet代替位域
什么是位域?为什么用到它?先来看一个例子: public class Test { public static final byte STYLE_BOLD = 1<<0; // 1 pub ...
- effective java 学习心得
目的 记录一下最主要学习心得,不然凭我这种辣鸡记忆力分分钟就忘记白看了... 用静态工厂方法代替构造器的最主要好处 1.不必每次都创建新的对象 Boolean.valueOf Long.valueOf ...
- Effective java笔记(五),枚举和注解
30.用enum代替int常量 枚举类型是指由一组固定的常量组成合法值的类型.在java没有引入枚举类型前,表示枚举类型的常用方法是声明一组不同的int常量,每个类型成员一个常量,这种方法称作int枚 ...
- Java基础常见英语词汇
Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的 ['prəʊɡræmɪŋ]编程 OO: object ...
- [转]JAVA虚拟机的生命周期
JAVA虚拟机体系结构 JAVA虚拟机的生命周期 一个运行时的Java虚拟机实例的天职是:负责运行一个java程序.当启动一个Java程序时,一个虚拟机实例也就诞生了.当该程序关闭退出,这个虚拟机实例 ...
- Effective Java 阅读笔记——枚举和注解
30:用enum代替int常量 当需要一组固定常量的时候,应该使用enum代替int常量,除了对于手机登资源有限的设备应该酌情考虑enum的性能弱势之外. 31:用实例域代替序数 应该给enum添加i ...
- Java高级之类结构的认识
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! Java体系包括,各种版本的虚拟机,可执行文件,各种第三方类库,Java API类库,Java语言 ...
- [Effective Java]第六章 枚举和注解
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
随机推荐
- 特征价格(Hedonic price)
特征价格法,又称 Hedonic 模型法和效用估价法,认为房地产由众多不同的特征组成,而房地产价格是由所有特征带给人们的效用决定的.由于各特征的数量及组合方式不同,使得房地产的价格产生差异.因此,如能 ...
- Openstack部署总结:“部署过程Error: Local ip for ovs agent must be set when tunneling is enabled”问题
问题叙述性说明 正在使用RDO当多节点部署测试,因为使用了一些老机器和机器类型的差异(一些HP的PC,有些DELL的PC).以下错误出现: Applying 192.168.40.107_neutro ...
- ISO/IEC 27001 信息安全管理体系认证
一. 信息安全管理体系标准业务介绍 1. 背景介绍 信息作为组织的重要资产,需要得到妥善保护.但随着信息技术的高速发展,特别是Internet的问世及网上交易的启用,许多信息安全的问题也纷纷出现:系统 ...
- WPF:拖动父窗口行为
原文 WPF:拖动父窗口行为 这次只是一个快速的帖子:当我点击并拖动特定的UIElement时,我需要能够重新定位WPF窗口.目的是重新创建在标准Windows标题栏上单击和拖动的行为(在我的情况下, ...
- Mybatis缓存 缓存配置文件 good
一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Se ...
- WPF获取读取电脑指定文件夹中的指定文件的地址
//保存指定文件夹中的指定文件的地址 string List<string> mListUri = new List<string>(); //文件夹地址 string fol ...
- 圆周卷积(circular convolution)
1. 定义与概念 圆周卷积也叫循环卷积, 2. 实现(matlab) 以圆周的形式卷积两个信号: >> z = ifft(fft(x).*fft(y));
- 零元学Expression Blend 4 - Chapter 25 以Text相关功能就能简单做出具有设计感的登入画面
原文:零元学Expression Blend 4 - Chapter 25 以Text相关功能就能简单做出具有设计感的登入画面 本章将交大家如何运用Blend 4 内的Text相关功能做出有设计感的登 ...
- LINE_NO in format of XXXX example -> Line 10 is 0010
select case when length(line_no) = 1 then to_char(line_no) when length(line_no) = 2 then '00' || lin ...
- Attention is all you need及其在TTS中的应用Close to Human Quality TTS with Transformer和BERT
论文地址:Attention is you need 序列编码 深度学习做NLP的方法,基本都是先将句子分词,然后每个词转化为对应的的词向量序列,每个句子都对应的是一个矩阵\(X=(x_1,x_2,. ...