重识java-EnumMap
2016-03-10 22:54
531 查看
EnumMap是一种键为枚举类型的特殊的Map实现。所有的Key也必须是一种枚举类型,EnumMap是使用数组来实现的。
可以看出,key的类型继承自
第一个构造函数,指定key的类型,构造默认大小的
第二个构造函数使用已存在的EnumMap的初始化现在的EnumMap;
第三个构造函数,从Map的所有子类中,探测key的类型,转为EnumMap,如果一般的Map的key不是enum类型的,则会报错。
get
判断key的类型,并且key不能为
remove
先判断key的类型,然后判断当前是否有 该key对应的value,成功删除键值对后,size减小。
EnumMapIterator的迭代
全部的键值必须来自一个单一的enum类型。
集合视图返回的迭代器是弱一致的:遍历时候不会抛出
key不能为
Thanks for reading! want more
源码解读
类声明public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements java.io.Serializable, Cloneable
可以看出,key的类型继承自
Enum,说明key必须是枚举类型。
变量
//Key的类型,自定义类型使用类名.class表示 private final Class<K> keyType; //保存枚举类的成员 private transient K[] keyUniverse; //enum数据结构 private transient Object[] vals; // 键值对数量 private transient int size = 0;
构造函数
public EnumMap(Class<K> keyType) { this.keyType = keyType; keyUniverse = getKeyUniverse(keyType); vals = new Object[keyUniverse.length]; } public EnumMap(EnumMap<K, ? extends V> m) { keyType = m.keyType; keyUniverse = m.keyUniverse; vals = m.vals.clone(); size = m.size; } public EnumMap(Map<K, ? extends V> m) { if (m instanceof EnumMap) { EnumMap<K, ? extends V> em = (EnumMap<K, ? extends V>) m; keyType = em.keyType; keyUniverse = em.keyUniverse; vals = em.vals.clone(); size = em.size; } else { if (m.isEmpty()) throw new IllegalArgumentException("Specified map is empty"); keyType = m.keySet().iterator().next().getDeclaringClass(); keyUniverse = getKeyUniverse(keyType); vals = new Object[keyUniverse.length]; putAll(m); } }
第一个构造函数,指定key的类型,构造默认大小的
EnumMap。其中调用
getKeyUniverse来获取枚举类型的所有成员。
private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) { //sun.misc.SharedSecrets类 return SharedSecrets.getJavaLangAccess().getEnumConstantsShared(keyType); }
第二个构造函数使用已存在的EnumMap的初始化现在的EnumMap;
第三个构造函数,从Map的所有子类中,探测key的类型,转为EnumMap,如果一般的Map的key不是enum类型的,则会报错。
核心方法
putpublic V put(K key, V value) { //检查key的类型是不是声明EnumMap时指明的key类型或是其子类 typeCheck(key); int index = key.ordinal(); Object oldValue = vals[index]; vals[index] = maskNull(value); if (oldValue == null)//是新插入的值,键值对大小增加 size++; return unmaskNull(oldValue); }
get
public V get(Object key) { return (isValidKey(key) ? unmaskNull(vals[((Enum<?>)key).ordinal()]) : null); }
判断key的类型,并且key不能为
null。
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); }
先判断key的类型,然后判断当前是否有 该key对应的value,成功删除键值对后,size减小。
EnumMapIterator的迭代
public boolean hasNext() { while (index < vals.length && vals[index] == null) index++; return index != vals.length; }
hasNext自动跳过
value为
null的节点,保证了
key的自然顺序。
总结
EnumMap维持键值的自然顺序(即枚举类型常量声明的顺序)。
全部的键值必须来自一个单一的enum类型。
EnumMap内部用数组表示效率更高。
集合视图返回的迭代器是弱一致的:遍历时候不会抛出
ConcurrentModificationException。遍历过程中若对容器进行改动。改动产生的影响遍历过程可能可见也可能不可见。
key不能为
null,插入空值将会抛出
NullPointerException;值可以为null。
EnumMap不保证线程安全
Thanks for reading! want more
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树