EnumMap 的用法
EnumMap
在使用上跟 HashMap
差不多,但是 EnumMap
的性能更好,所以,如果键为 Enum
类型时,建议使用 EnumMap
代替 HashMap
。
public enum Color {
YELLOW, RED, BLUE, BLACK
}
public static void main(String[] args) {
EnumMap<Color, Integer> colorMap = new EnumMap<>(Color.class);
for (Color value : Color.values()) {
colorMap.put(value, value.ordinal());
}
colorMap.forEach((k, v) -> System.out.println(k + " -> " + v));
}
输出结果如下
YELLOW -> 0
RED -> 1
BLUE -> 2
BLACK -> 3
使用上没什么可说的,关键从源码讲一下 EnumMap
为什么在性能上会更好。
看一下 EnumMap
的结构定义
- keyType:记录枚举数据类型
- keyUniverse:存储所有的枚举实例,
- vals:存储值,与 keyUniverse 数组等长,存储的值与 keyUniverse 的索引对应
public class EnumMap<K extends Enum<K>, V>
extends AbstractMap<K, V> implements Serializable, Cloneable {
private final Class<K> keyType;
private transient K[] keyUniverse;
private transient Object[] vals;
private transient int size = 0;
}
EnumMap
在初始化时就会将枚举的所有实例存储到 keyUniverse
数组,vals
则初始化为与 keyUniverse
等长的数组,每个元素填充为 null
。
新增数据时,获取枚举实例的 ordinal
作为索引,然后直接赋值到 vals
相应的索引即可,时间复杂度为 O1
。
public V put(K var1, V var2) {
this.typeCheck(var1);
int var3 = var1.ordinal();
Object var4 = this.vals[var3];
this.vals[var3] = this.maskNull(var2);
if (var4 == null) {
++this.size;
}
return this.unmaskNull(var4);
}
获取数据时,获取枚举实例的 ordinal
作为索引,直接从 vals
数组获取相应索引位置的值即可,时间复杂度为 O1
。
public V get(Object var1) {
return this.isValidKey(var1) ? this.unmaskNull(this.vals[((Enum)var1).ordinal()]) : null;
}
EnumMap
之所以可以这么操作,是因为枚举的实例是有限的,而每个实例通过 ordinal()
方法可以确定其索引位置,这样 Map
的操作就转化成了对 vals
数组的操作,所以效率非常高。
EnumSet 的用法
创建空集合
EnumSet.noneOf(Color.class);
创建包含所有元素的集合
EnumSet.allOf(Color.class);
创建包含指定元素的集合
EnumSet.of(Color.YELLOW, Color.RED);
创建范围集合
第一个枚举值的索引位置必须大于第二个枚举值,不然会导致异常。
public static void main(String[] args) {
EnumSet<Color> rangeColorSet = EnumSet.range(Color.YELLOW, Color.BLUE);
// 输出 [YELLOW, RED, BLUE]
System.out.println(rangeColorSet);
}
补集
public static void main(String[] args) {
EnumSet<Color> partColorSet = EnumSet.of(Color.YELLOW, Color.RED);
EnumSet<Color> remainderColorSet = EnumSet.complementOf(partColorSet);
// 输出 [BLUE, BLACK]
System.out.println(remainderColorSet);
}
复制创建集合
public static void main(String[] args) {
List<Color> colorList = new ArrayList<>();
Collections.addAll(colorList, Color.YELLOW, Color.RED, Color.RED);
// 输出 [YELLOW, RED, RED]
System.out.println(colorList);
EnumSet<Color> colorSet = EnumSet.copyOf(colorList);
// 输出 [YELLOW, RED]
System.out.println(colorSet);
}