枚举详解之EnumSet、EnumMap用法
枚举简单例子
/**
* @author shuliangzhao
* @Title: Color
* @ProjectName design-parent
* @Description: TODO
* @date 2019/6/12 22:35
*/
public enum Color {
YELLOW,
RED,
BLUE,
PURPLE,
BLACK;
}
/**
* @author shuliangzhao
* @Title: ColorEnumTest
* @ProjectName design-parent
* @Description: TODO
* @date 2019/6/12 22:37
*/
public class ColorEnumTest {
public static void main(String[] args) {
Color color = Color.BLUE;
switch (color) {
case RED:
System.out.println("红色");
break;
case BLUE:
System.out.println("蓝色");
break;
case PURPLE:
System.out.println("紫色");
break;
case BLACK:
System.out.println("黑色");
break;
case YELLOW:
System.out.println("黄色");
break;
default:
System.out.println("蓝色");
break;
}
}
}
测试结果
Color枚举的本质就是一个类,编译器会自动为我们生成Color类,通过反编译得到该类如下:
final class Color extends Enum {
//编译器为我们添加的静态的values()方法
public static Color[] values()
{
return (Color[])$VALUES.clone();
}
//编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
public static Color valueOf(String s)
{
return (Color)Enum.valueOf(com/sl/emun/Color, s);
}
//私有构造函数
private Color(String s, int i)
{
super(s, i);
}
//前面定义的7种枚举实例
public static final Color YELLOW;
public static final Color RED;
public static final Color BLUE;
public static final Color PURPLE;
public static final Color BLACK;
private static final Color $VALUES[];
static
{
//实例化枚举实例
YELLOW = new Color("YELLOW", 0);
RED = new Color("RED", 1);
BLUE = new Color("BLUE", 2);
PURPLE = new Color("PURPLE", 3);
BLACK = new Color("BLACK", 4);
$VALUES = (new Color[] {
YELLOW, RED, BLUE, PURPLE, BLACK
});
}
}
可以看出每个枚举类型颜色是该Color类的一个实例对象,该构成方式和单例模式有些类似,故可以用只有一个枚举类型的枚举作为单例模式,而且枚举的构造器由编译器管理安全性十分高,既可以防止反射破解也可以防止反序列破解。
EnumMap用法
/**
* @author shuliangzhao
* @Title: EnumMapTest
* @ProjectName design-parent
* @Description: TODO
* @date 2019/6/12 22:49
*/
public class EnumMapTest {
public static void main(String[] args) {
EnumMap<Color,String> enumMap = new EnumMap(Color.class);
enumMap.put(Color.BLACK,"黑色");
enumMap.put(Color.BLUE,"蓝色");
System.out.println(enumMap);
System.out.println(enumMap.get(Color.BLUE));
}
}
运行结果
EnumMap put方法
public V put(K key, V value) {
typeCheck(key);
int index = key.ordinal();
Object oldValue = vals[index];
vals[index] = maskNull(value);
if (oldValue == null)
size++;
return unmaskNull(oldValue);
}
首先调用typeCheck检查键的类型,如果类型不对,会抛出异常。类型正确的话,调用ordinal获取索引index,并将值value放入值数组vals[index]中。EnumMap允许值为null,为了区别null值与没有值,EnumMap将null值包装成了一个特殊的对象,有两个辅助方法用于null的打包和解包,打包方法为maskNull,解包方法为unmaskNull。
get方法
public V get(Object key) {
return (isValidKey(key) ?
unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
}
键有效的话,通过ordinal方法取索引,然后直接在值数组vals里找。isValidKey的代码与typeCheck类似,但是返回boolean值而不是抛出异常。
以上就是EnumMap的基本实现原理,内部有两个数组,长度相同,一个表示所有的键,一个表示对应的值,值为null表示没有该键值对,键都有一个对应的索引,根据索引可直接访问和操作其键和值,效率很高。
EnumSet
EnumSet这是一个用来操作Enum的集合,是一个抽象类,它有两个继承类:JumboEnumSet和RegularEnumSet。在使用的时候,需要确定枚举类型。它的特点也是速度非常快,为什么速度很快呢?因为每次add的时候,每个枚举值只占一个长整型的一位。
EnumSet.noneOf()方法创建一个空的set
public class EnumSetTest {
public static void main(String[] args) {
EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
System.out.println(enumSet);
enumSet.add(Color.BLUE);
enumSet.add(Color.PURPLE);
System.out.println(enumSet);
}
}
运行结果
EnumSet.allOf()方法创建一个满的set
/**
* @author shuliangzhao
* @Title: EnumSetTest
* @ProjectName design-parent
* @Description: TODO
* @date 2019/6/12 23:24
*/
public class EnumSetTest {
public static void main(String[] args) {
/*EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
System.out.println(enumSet);
enumSet.add(Color.BLUE);
enumSet.add(Color.PURPLE);
System.out.println(enumSet);*/
EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
System.out.println(enumSet);
}
}
运行结果
EnumSet.range创建指定范围set
public class EnumSetTest {
public static void main(String[] args) {
/*EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
System.out.println(enumSet);
enumSet.add(Color.BLUE);
enumSet.add(Color.PURPLE);
System.out.println(enumSet);
EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
System.out.println(enumSet);*/
EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
System.out.println(enumSet);
}
}
EnumSet.complementOf补集创建set
public class EnumSetTest {
public static void main(String[] args) {
/*EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
System.out.println(enumSet);
enumSet.add(Color.BLUE);
enumSet.add(Color.PURPLE);
System.out.println(enumSet);
EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
System.out.println(enumSet);*/
EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
System.out.println(enumSet);
EnumSet<Color> enumSet1 = EnumSet.complementOf(enumSet);
System.out.println(enumSet1);
}
}
运行结果
EnumSet.copyOf复制创建set
public class EnumSetTest {
public static void main(String[] args) {
/*EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
System.out.println(enumSet);
enumSet.add(Color.BLUE);
enumSet.add(Color.PURPLE);
System.out.println(enumSet);
EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
System.out.println(enumSet);
EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
System.out.println(enumSet);
EnumSet<Color> enumSet1 = EnumSet.complementOf(enumSet);
System.out.println(enumSet1);*/
EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
System.out.println(enumSet);
EnumSet<Color> enumSet1 = EnumSet.copyOf(enumSet);
System.out.println(enumSet1);
}
}
运行结果
EnumSet.copyOf复制创建集合
public class EnumSetTest {
public static void main(String[] args) {
/*EnumSet<Color> enumSet = EnumSet.noneOf(Color.class);
System.out.println(enumSet);
enumSet.add(Color.BLUE);
enumSet.add(Color.PURPLE);
System.out.println(enumSet);
EnumSet<Color> enumSet = EnumSet.allOf(Color.class);
System.out.println(enumSet);
EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
System.out.println(enumSet);
EnumSet<Color> enumSet1 = EnumSet.complementOf(enumSet);
System.out.println(enumSet1);
EnumSet<Color> enumSet = EnumSet.range(Color.YELLOW,Color.BLUE);
System.out.println(enumSet);
EnumSet<Color> enumSet1 = EnumSet.copyOf(enumSet);
System.out.println(enumSet1);*/
List<Color> colors = new ArrayList<>();
colors.add(Color.PURPLE);
colors.add(Color.BLUE);
colors.add(Color.BLUE);
System.out.println(colors);
EnumSet<Color> enumSet = EnumSet.copyOf(colors);
System.out.println(enumSet);
}
}
运行结果
注意:通过结果可以看出ArrayList内放置的元素可以重复,而EnumSet内放置的元素不重复。
枚举详解之EnumSet、EnumMap用法的更多相关文章
- linux 详解useradd 命令基本用法
linux 详解useradd 命令基本用法 时间:2019-03-24 本文章向大家介绍linux 详解useradd 命令基本用法,主要包括linux 详解useradd 命令基本用法使用实例.应 ...
- [转] - JAR文件包及jar命令详解 ( MANIFEST.MF的用法 )
常常在网上看到有人询问:如何把 java 程序编译成 .exe 文件.通常回答只有两种,一种是制作一个可执行的 JAR 文件包,然后就可以像. chm 文档一样双击运行了:而另一种是使用 JET 来进 ...
- 详解python中@的用法
python中@的用法 @是一个装饰器,针对函数,起调用传参的作用. 有修饰和被修饰的区别,‘@function'作为一个装饰器,用来修饰紧跟着的函数(可以是另一个装饰器,也可以是函数定义). 代码1 ...
- yield关键字详解与三种用法
本篇文章比较硬核, 适合有一定Python基础的读者阅读, 如果您对Python还不甚了解可以先关注我哦, 我会持续更新Python技术文章 yield详解 yield与return相同每次调用都会返 ...
- java基础篇---枚举详解
在JDK1.5之前,JAVA可以有两种方式定义新类型:类和接口,对于大部分面向对象编程,有这两种似乎就足够了,但是在一些特殊情况就不合适.例如:想要定义一个Color类,它只能有Red,Green,B ...
- nmap详解之原理与用法
前言 nmap是一款开源免费的网络发现(Network Discovery)和安全审计(Security Auditing)工具.软件名字Nmap是Network Mapper的简称.Nmap最初是由 ...
- 实用的PHP功能详解(一)_php glob()用法
一.使用glob()查找文件 大部分PHP函数的函数名从字面上都可以理解其用途,但是当你看到 glob() 的时候,你也许并不知道这是用来做什么的,其实glob()和scandir() 一样,可以用来 ...
- C# 控件双缓冲控制 ControlStyles 枚举详解
ControlStyles 枚举 .NET Framework 4 指定控件的样式和行为. 此枚举有一个 FlagsAttribute 特性,通过该特性可使其成员值按位组合. 命名空间: Sy ...
- Java 枚举详解
为什么要用枚举 在博客系统中,一篇文章有且可能有这几种状态, 数据库中article文章表中state字段存储数值,表示其状态: 0(已发表Published) 1(草稿Draft) 2(撤回撤回(D ...
随机推荐
- (C/C++学习)23.C++中指针的长度
引言:先看下面一个程序会打印出什么? #include<iostream> using namespace std; int main() { int a = 2; int *p = &a ...
- vticker.js--垂直滚动插件
一.使用要求 列表必须是ul>li的格式 html代码 <div class=" myvticker'"> <ul> <li>1.新闻标题 ...
- 每日命令:(6)rmdir
今天学习一下linux中命令: rmdir命令.rmdir是常用的命令,该命令的功能是删除空目录,一个目录被删除之前必须是空的.(注意,rm - r dir命令可代替rmdir,但是有很大危险性.)删 ...
- PAT 1126 Eulerian Path
In graph theory, an Eulerian path is a path in a graph which visits every edge exactly once. Similar ...
- 调试pcb板子的步骤
在从外边焊回来的板子中查找问题的时候,如果只是简单的 一通乱调,很有可能一下子就调好了,但是大多数的时候是调了半天,不知道接下来该如何进行,因此,严格的按照步骤走,是个不错的想法: 1.拿到板子的第一 ...
- Java基础学习总结(77)——Java枚举再总结
在Java SE5之前,我们要使用枚举类型时,通常会使用static final 定义一组int常量来标识,代码如下 public static final int MAN = 0; public s ...
- vue.js编程式路由导航 --- 由浅入深
编程式路由导航 实例中定义一个方法,这个方法绑定在标签上 然后就设置路由跳转 语法 this.$router.history.push('要跳转路由的地址') <!DOCTYPE html> ...
- JVM即时编译(JIT)
Java解释执行过程: 代码装入-代码校验-代码执行 Java字节码的执行方式分为两种:即使编译方式和解释执行方式.即时编译是值解释器先将字节码编译成机器码,然后执行该机器码.解释执行的方式是指解释器 ...
- ISO 7064:1983.MOD11-2校验码计算法 : (身份证校验码-18位)
/* 假设某一17位数字是 17位数字 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 加权因子 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 计算17位 ...
- Java深入浅出系列(四)——深入剖析动态代理--从静态代理到动态代理的演化
静态代理 如上图,在程序执行之前.程序猿就要编写Proxy.然后进行编译,即在程序执行之前,代理类的字节码文件就已经生成了(Proxy类的class文件已经存在了). 静态代理尽管在增强现有的接口业务 ...