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,并以超链接形式标明文章原始出处,否则将 ...
随机推荐
- 将枚举转成SelectListItem
代码如下: /// <summary> /// 将一个枚举转化成一个List<SelectListItem> /// </summary> /// <type ...
- Windows搭建Eclipse+JDK+SDK的Android --安卓开发入门级
一 相关下载 (1) java JDK下载: 进入该网页: http://java.sun.com/javase/downloads/index.jsp (或者直接点击下载)例如以下图: 选择 ...
- 上传图片时,使用GDI+中重绘方式将CMYK图片转为RGB图片
原文:上传图片时,使用GDI+中重绘方式将CMYK图片转为RGB图片 我们知道,如果网站上传图片时,如果用户上传的是CMYK图片,那么在网站上将是无法显示的,通常的现象是出现一个红叉.下面使用将Ima ...
- uwp - 解决“Microsoft.EntityFrameworkCore.Tools –Pre因为在此系统上禁止运行脚本”
在uwp使用ef时,需要安装“Microsoft.EntityFrameworkCore.Tools –Pre” ,如果安装失败提示:“无法加载文件 \.nuget\packages\Microsof ...
- Some Very Good VC++/MFC Resources Besides Codeproject.com
Some Very Good VC++/MFC Resources Besides Codeproject.com http://www.naughter.com/ (VC++/MFC huge co ...
- JDBC学习笔记——简单的连接池
1.使用LinkedList保存连接 即使是最简单的JDBC操作,也需要包含 ...
- WPF图片浏览器(显示大图、小图等)
原文:WPF图片浏览器(显示大图.小图等) 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/wangshubo1989/article/details ...
- 线程操纵UI问题
WPF只允许UI线程修改UI,其他线程必须通过Invoke.委托(安全性)Winform可以开启/关闭“只允许UI线程修改UI” 在WPF中非UI线程修改UI的方法 非UI线程直接修改UI,会报错 S ...
- WPF中任意Object的XAML代码格式化输出
原文:WPF中任意Object的XAML代码格式化输出 有时候,我们需要将WPF中的控件自身的XAML代码输出成文本,那么,我们可以使用System.Windows.Markup.XamlWriter ...
- 【Gerrit】Add a Member
add user email:XXXX@163.com username:XXXX( songfei) Add Step: System Server:1. ssh 服务器用户 ...