【Java 枚举 集合】枚举类Enum、映射EnumMap、集EnumSet
枚举Enum、映射EnumMap、集EnumSet
- 一、枚举Enum
- 1、概述
- 2、介绍
- ① valueOf
- ② values
- 3、分析
- ※ 模仿一个枚举类
- 二、枚举映射 EnumMap
- 1、概述
- 2、使用方法
- 3、应用场景
- 三、枚举集 EnumSet
- 1、概述
- 2、使用方法
本文使用 JDK 版本为 JDK1.15
一、枚举Enum
1、概述
一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。
- Java的枚举本质上是一个特殊的类,它可以通过
enum
关键字定义。 - 它可以定义构造器,但是不可被
public
修饰,所以不能被实例化。 - 它的构造器只是在构造枚举值得时候被调用。
- 它的内部也可以定义变量、方法。
2、介绍
枚举一般用于选择语句中,它提供的API如下:
为方便测试,我们定义这样的枚举类型:
public enum Color {WHITE,BLUE,GREEN,RED,YELLOW,BLACK //这里省略了分号,如果后续需定义其他成员,需加上分号
}
① valueOf
枚举一般应用于switch...case...default
语句中,配合内置的valueOf
方法提取字符串的值,具体使用案例如下:
public void whatColor(){switch (Color.valueOf("YELLOW")){case YELLOW:System.out.println("黄色");break;default:System.out.println("其他颜色");break;}
}
- 当我们试图将一个 不存在的元素 的字符串作为 参数 时,会抛出异常:
java.lang.IllegalArgumentException: No enum constant Color.XXX
我们打印输出,进行测试:
System.out.println(Color.valueOf("vovo"));
② values
- 枚举还提供了values方法,通过调用该方法,获取枚举类型内的所有内置元素,返回类型为一个枚举类型的数组(即Color类型):
我们打印输出
System.out.println(Arrays.toString(Color.values()));
- 可以看到,我们按顺序取到了所有的元素值。
- 那么,枚举类型的本质到底是什么?为什么没有返回 Object 类型 或是 String 类型 的数组?
3、分析
- 为了探寻,枚举类型的本质,我们使用
javap
指令,对 Color.java 文件进行反编译:
- 枚举类型本质上是一个继承自lang包下,Enum类的派生类。
- 它默认拥有一个 values 数组、valueOf 方法,以及一个静态代码块。
- 枚举类型的元素,本质上是与其相同类型的静态常量,只是名称有所不同 ,我们可以通过其名称获取相应的值。
※ 模仿一个枚举类
//Enum 类 不可被 我们随意 继承
public final class Color /*extends Enum<Color>*/{public static final Color WHITE;public static final Color BLUE;public static final Color GREEN;public static final Color RED;public static final Color YELLOW;public static final Color BLACK;static{WHITE = new Color("WHITE");BLUE = new Color("BLUE");GREEN = new Color("GREEN");RED = new Color("RED");YELLOW = new Color("YELLOW");BLACK = new Color("BLACK");}//定义变量colorprivate final String color;//私有的构造器private Color(String color) {this.color = color;}//静态方法 values();public static Color[] values() {return new Color[] {WHITE,BLUE,GREEN,RED,YELLOW,BLACK};}//静态方法 valueOf(String color);public static Color valueOf(String color) {switch (color) {case "WHITE":return Color.WHITE;case "BLUE":return Color.BLUE;case "GREEN":return Color.GREEN;case "RED":return Color.RED;case "YELLOW":return Color.YELLOW;case "BLACK":return Color.BLACK;default:throw new IllegalArgumentException("No enum constant: " + Color.class.getName() + "." + color);}}//为了防止其打印地址,我们只好重写toString方法,事实上enum类型并没有内置toString方法@Overridepublic String toString() {return this.color;}
}
上述类同样可以完成枚举类的功能,只是这样写十分繁琐,使用枚举类型可以帮助我们简化代码,而且看起来十分简洁明了。
二、枚举映射 EnumMap
1、概述
EnumMap是专门为枚举类型量身定做的Map实现,类似地还有EnumSet。虽然使用其它的Map实现(如HashMap)也能完成枚举类型实例到值得映射,但是使用EnumMap会更加高效:它只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以EnumMap使用数组来存放与枚举类型对应的值。这使得EnumMap的效率非常高。
《Effective Java》中作者建议用EnumMap代替叙述索引,最好不要用序数来索引数组,而要使用EnumMap。
EnumMap构造方法采用键类型的Class对象:这是一个有限制的类型令牌,它提供了运行时的泛型信息。
其中Class<K>
作为采用键类型的Class对象,说明EnumMap以枚举类型为键,可取出对应值。
2、使用方法
为方便说明,我们定义如下的星期Enum类,并创建对应的EnumMap:
enum Weekday{MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
}
初始化 键值:
这是 Java 中 Map、Set 初始化设定数值的途径,形式上类似于数组{}
,Map与Set使用双层花括号定义初始数值{{}}
。
//初始化直接放入键值
Map<Weekday,String> map = new EnumMap<>(Weekday.class){{put(Weekday.MONDAY,"星期一");put(Weekday.TUESDAY,"星期二");put(Weekday.WEDNESDAY,"星期三");put(Weekday.THURSDAY,"星期四");put(Weekday.FRIDAY,"星期五");put(Weekday.SATURDAY,"星期六");put(Weekday.SUNDAY,"星期日");
}};
双层花括号的意义?
- 外层花括号实际是定义了一个匿名内部类 (Anonymous Inner Class)。
- 内层花括号实际上是一个实例初始化块 (instance initializer block),这个块在内部匿名类构造时被执行。这个块之所以被叫做“实例初始化块”是因为它们被定义在了一个类的实例范围内。
上面代码如果是写在 EnumMapDemo 类中,编译后你会看到会生成 EnumMapDemo$1.class 文件,编译 .java 文件后得到结果:
剖析这种方式,发现其本质上创建了一个继承 EnumMap 的匿名内部类(内部类概述):
// 第一个{}代表 创建了一个 HashMap 的子类
class EnumMapDemo$1<K extends Enum<K>, V> extends EnumMap { { // 第二个{}中的代码放到了实例初始化块中去了put(Weekday.MONDAY, "星期一");put(Weekday.TUESDAY, "星期二");}EnumMapDemo$1(Class<K> keyType){ //super调用父类构造方法super(keyType); }
}
初始化后操作键值:
//先创建枚举映射
Map<Weekday,String> map = new EnumMap<>(Weekday.class);
//后放入键值
map.put(Weekday.MONDAY,"星期一");
map.put(Weekday.TUESDAY,"星期二");
map.put(Weekday.WEDNESDAY,"星期三");
map.put(Weekday.THURSDAY,"星期四");
map.put(Weekday.FRIDAY,"星期五");
map.put(Weekday.SATURDAY,"星期六");
map.put(Weekday.SUNDAY,"星期日");
3、应用场景
情景引入:
现有以 Java 语言编写的服务器、C# 语言 编写的客户端,二者为 C/S架构,均使用 Socket 进行通信。由于语言不相通,须手动构建请求、响应字符串,并指定状态码。
而数字难以识别,这时就可以在服务端使用 Enum 规定请求状态的英文、后以EnumMap<Enum,Integer>指定数字并以此做请求分类,简化我们的操作(图中:通信解析控制模块):
enum Status{ACCEPT, //20RESPONSE,//50SERVER_CLOSING,//90RESOURCES_NOT_FOUND,//60ERROR, //40SUCCESS //70//...
}
Map<Status,Integer> statusMap = new EnumMap<>(Status.class){{put(Status.ACCEPT,20);put(Status.RESPONSE,50);put(Status.SERVER_CLOSING,90);put(Status.RESOURCES_NOT_FOUND,60);put(Status.ERROR,40);put(Status.SUCCESS,70);//...
}};
也可以将值包装成类,内部附有状态码、方法字符串,利用反射自动寻找、处理业务。
三、枚举集 EnumSet
1、概述
EnumSet 是一个枚举类型元素集的高效实现。枚举类型只有有限个例,所以EnumSet 内部用位序列实现。如果对应的值在集中,则相应的位被置为1。
2、使用方法
EnumSet类没用公共的构造器。可以使用静态工厂方法构造这个集:
enum Weekday{MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
}
//全部值
EnumSet<Weekday> always = EnumSet.allOf(Weekday.class);
//无值
EnumSet<Weekday> never= EnumSet.noneOf(Weekday.class);
//范围值
EnumSet<Weekday> workday= EnumSet.range(Weekday.MONDAY,Weekday.FRIDAY);
//选中值
EnumSet<Weekday> mwf = EnumSet.of(Weekday.MONDAY,Weekday.SATURDAY,Weekday.FRIDAY)
⭐ E extends Enum 代表“E是一个枚举类型”。
⭐ 枚举类的特殊性正体现于此:所有的枚举类型都扩展于泛型 Enum 类(参考本文第一节)
【Java 枚举 集合】枚举类Enum、映射EnumMap、集EnumSet相关推荐
- java基础集合操作工具类Collections简述(java集合四)
对集合中的元素进行排序 Collections中的sort方法使用 public class ListDemo {public static void main(String[] args) {Lis ...
- Java学习——集合ArrayList类
1,集合ArrayList类底层就是用数组来实现的,其语法为: ArrayList objectName =new ArrayList<>(); 这个E一定要用引用数据类型 2,集合跟数组 ...
- Java—Set集合详解(HashSet/LinkedHashSet/TreeSet/EnumSet)
关注微信公众号:CodingTechWork,一起学习进步. Set集合介绍 Set集合的概念 Set集合类似于一个容器,程序把很多对象保存到Set集合中,Set集合对添加顺序不记录,当有重复的对 ...
- Java技能树-集合-ArrayList类
1 需求 2 接口 Class ArrayList<E> public class ArrayList<E> extends AbstractList<E> imp ...
- java.lang包—枚举类Enum
原文作者:山高我为 原文地址:java enum的用法详解 目录 一.enum关键字 二.Enum类源码 三.疑问 四.Enum常见用法 一.enum关键字 enum关键字是在Java1.5也就是Ja ...
- enum java 比较_Kotlin与Java比较:枚举类
前言 Kotlin作为JVM系的语言,起源于Java又不同于Java.通过在语言层面比较两者的区别,可以使得开发者能够快速学习,融会贯通. 枚举使用场景 使用枚举的场景非常明确,即只要一个类的对象是有 ...
- java arraylist枚举器遍历_Java基础(七)泛型数组列表ArrayList与枚举类Enum
一.泛型数组列表ArrayList 1.在Java中,ArrayList类可以解决运行时动态更改数组的问题.ArrayList使用起来有点像数组,但是在添加或删除元素时,具有自动调节数组容量的功能,而 ...
- Java中的枚举类是什么?enum关键字怎么使用?
枚举类 文章目录 枚举类 枚举类的使用:入门 自定义枚举类 方法一:自定义枚举类 方式二: enum 关键字定义枚举类(主要用该方式) Enum类的主要方法 使用enum关键字定义的枚举类实现接口 主 ...
- java枚举类Enum入门理解
目录 枚举的定义 JDK5.0之前只能自定义枚举类 自定义枚举类的理解: JDK5.0之后enum关键字定义枚举类 区别于自定义枚举类 enum的父类Enum的常用方法 toString方法和valu ...
最新文章
- 【转】用示例说明索引数据块中出现热块的场景,并给出解决方案
- 创建型模式--原型模式
- SolrQuery的使用
- 8086汇编-实验8-jmp指令的理解
- Jenkins将致力于提升稳定性、易用性和云原生兼容性
- 如何获取sharepoint列表_练习 34 - 获取列表元素 - Learn Python 3 The Hard Way
- HBase 架构详解
- mac json工具_工具类封装的思路 | 钉钉群机器人为例
- CSS样式表书写位置
- 数据库开发 - 事务 死锁分析与解决
- Python 解leetcode:728. Self Dividing Numbers
- 书单丨把握Java技术发展的新趋势!
- android开源音乐播放器简单demo,Android开源在线音乐播放器——波尼音乐
- 【Unity3D进阶4-8】Unity3D 游戏框架
- ISSCC2021 基于SRAM的存内计算16.3阅读记录
- Bootstrap(一)
- ural 1671 Anansi's Cobweb
- 使用EasyExcel下载,文件名乱码问题处理
- linux运行lnk,LNK 文件扩展名: 它是什么以及如何打开它?
- 国外lead教程---EMU之SSN用不用