1、EnuMap介绍
键的值为枚举类型
主要因为枚举类型有两个特征:一个是他的值是有限的且预先定义的;而是枚举值都有一个顺序,这两个特征使得可以更高效的实现Map接口
内部基于数组实现
2、实现原理
内部有以下实例变量:
//表示类型信息
private final Class<K> keyType;
//表示键,是所有可能的枚举值
private transient K[] keyUniverse;
//表示对应的值,对应Enum的顺序所对应的值
private transient Object[] vals;
//表示键值对的个数
private transient int size = 0;
//EnumMap中可以存放NUll值
private static final Object NULL = new Object() {
public int hashCode() {
return 0;
}
public String toString() {
return "java.util.EnumMap.NULL";
}
};
3、构造方法
public EnumMap(Class<K> keyType) {
this.keyType = keyType;
//以初始化键数组
//原理是最终调用枚举类型的values方法,
// 返回所有可能的枚举值
keyUniverse = getKeyUniverse(keyType);
//vals为键对应的值存储的数组;根据键的个数确定其所对应数组的大小
vals = new Object[keyUniverse.length];
}
4、put方法
public V put(K key, V value) {
//检查键的类型
typeCheck(key);
//如果类型正确,调用ordinal获取索引index
int index = key.ordinal();
//并将值value放入数组vals[index]中
Object oldValue = vals[index];
//EnuMap允许值为null,为了区别null值与没有null值,
//EnuMap将null值包装成一个特殊的对象
//有两个辅助放大用于null的打包和解包
vals[index] = maskNull(value);
if (oldValue == null)
size++;
return unmaskNull(oldValue);
}
//如果键类型不对,则会抛出异常
private void typeCheck(K key) {
Class<?> keyClass = key.getClass();
if (keyClass != keyType && keyClass.getSuperclass() != keyType)
throw new ClassCastException(keyClass + " != " + keyType);
}
/* @return the ordinal of this enumeration constant
返回键在枚举类中的顺序
*/
public final int ordinal() {
return ordinal;
}
5、get方法
public V get(Object key) {
//如果键有效,通过ordinal方法获取索引
//然后直接在值数组vals里找
return (isValidKey(key) ?
unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
}
6、containsValue
public boolean containsValue(Object value) {
//打包
value = maskNull(value);
//遍历数组进行比较
for (Object val : vals)
if (value.equals(val))
return true;
return false;
}
7、remove方法
public V remove(Object key) {
//对键进行检查:类型检查
if (!isValidKey(key))
return null;
//获取待删除键的索引
int index = ((Enum<?>)key).ordinal();
Object oldValue = vals[index];
vals[index] = null;
if (oldValue != null)
size--;
return unmaskNull(oldValue);
}