博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EnumMap源码分析
阅读量:6579 次
发布时间:2019-06-24

本文共 4035 字,大约阅读时间需要 13 分钟。

        自Java8以来,HashMap是高效的。应用HashMap完成枚举类型到值的映射也是我们常用的方式,但是EnumMap将更加高效。
EnumMap顾名思义,是为枚举类服务的。
  • key必须为枚举类(Enum),且创建EnumMap时必须指定key的类型。
  • key不能为null,NullPointerException,但value允许null。
  • 底层结构均为数组,大小为Enum成员数量,创建EnumMap时会缓存所有枚举达到key数组。
  • 元素顺序为Enum的顺序,与put顺序无关。
  • 与HashMap类似,不保证线程安全。
注意:
  • 迭代时不会抛出ConcurrentModificationException。
  • NULL和null的区别。
1、重要属性
private 
final 
Class<K>
 keyType; 
// EnumMap的key的类型,在keyType中的enumConstants存放key的所有枚举值。
private transient K[] keyUniverse; //存放key的所有枚举值
private transient Object[] vals; // EnumMap的value值
private transient int size =0;
注意:key和value的底层机构均为数组
常用方法:
private Object maskNull(Object value) {
return (value == null ? NULL : value); //null变NULL,避免内部空指针异常 }
private V unmaskNull(Object value) {
return (V)(value == NULL ? null : value); }
 
private static final Object NULL = new Object() {
public int hashCode() {
return 0; } public String toString() {
return "java.util.EnumMap.NULL"; } };
2、put
public V put(K key, V value) {
typeCheck(key); // key必须是keyType类型或keyType子类型,否则ClassCastException异常 int index = key.ordinal(); // 以key的ordinal作为数组下标 Object oldValue = vals[index]; vals[index] = maskNull(value); //maskNull: value为空则返回自定义的空对象NULL if (oldValue == null) size++; return unmaskNull(oldValue); //返回oldValue或null
}
3、get
public V get(Object key) {
return (isValidKey(key) ? unmaskNull(vals[((Enum
)key).ordinal()]) : null); }
private boolean isValidKey(Object key) { // 检验key的有效性(不为null且类型合法)     if (key == null)         return false; // Cheaper than instanceof Enum followed by getDeclaringClass     Class
keyClass = key.getClass(); return keyClass == keyType || keyClass.getSuperclass() == keyType; }
get方法先检验key的有效性,有效则以ordinal为下标返回vals[ordinal],否则返回null,So,和HashMap一样,不可以用get来判断EnumMap是否包含某一元素,因为某元素的value可能本就为null。
4、contains相关
public boolean containsKey(Object key) {
return isValidKey(key) && vals[((Enum
)key).ordinal()] != null; }
注意containsKey和get的区别(仅仅未调用unmaskNull方法),以及EnumMap自定义的NULL和null的区别。
public boolean containsValue(Object value) {
value = maskNull(value); //null则返回NULL,否则返回value本身 for (Object val : vals) // 遍历vals if (value.equals(val)) return true; // 只要有一个相等即返回true return false; }
private boolean containsMapping(Object key, Object value) {
return isValidKey(key) && maskNull(value).equals(vals[((Enum
)key).ordinal()]); }
// containsMapping方法是私有的,仅供EntrySet的contains方法调用。
5、遍历相关

// 遍历KeySet

Set keySet = enumMap.keySet();

terator iteKey = keySet.iterator();

while(iteKey.hasNext()){

    Object object =(Object) iteKey.next();

    System.out.print(object +"="+ enumMap.get(object)+"; ");

}

------------------

// 遍历values

Collection<Object> vals = enumMap.values();

Iterator iteVal = vals.iterator();

while(iteVal.hasNext()){

    Object object =(Object) iteVal.next();

    System.out.print(object +"; ");

    // ((Iterator) object).remove();// ClassCastException: String cannot be cast to Iterator

}

--------------------

// 遍历Entry

Set<Entry<Season, Object>> entrySet = enumMap.entrySet();

Iterator iteEn = entrySet.iterator();

while(iteEn.hasNext()){

    Entry object =(Entry) iteEn.next();

    System.out.print(object.getKey()+"; ");

    iteEn.remove();

}

注意: 和HashMap不同的是,EnumMap迭代不会抛
ConcurrentModificationException异常。
for (Object entry : enumMap.entrySet()) {
            enumMap.remove(Season.summer); // 【--不抛--
ConcurrentModificationException
异常】
        }
        EnumMap中没有mouCount,相应Iterator中也没有expectedModCount,也就是说没有fast-fail机制。
相关分析参阅另一篇云笔记 《
HashMap迭代时不抛出ConcurrentModificationException的特例
》。
6、其他方法

public voidclear(){

    Arrays.fill(vals,null);

    size =0;

}

public static void fill(Object[] a, Object val){

    for(int i =0, len = a.length; i < len; i++)

        a[i]= val; // 逐个遍历,好在vals[]元素也不会有太多

}

 

public V remove(Object key){

    if(!isValidKey(key))

        return null;

    int index =((Enum<?>)key).ordinal();

    Object oldValue = vals[index];

    vals[index]=null// 直接置null

    if(oldValue !=null)

        size--;

    return unmaskNull(oldValue); // 返回oldValue(包含null

}

相关资料:

转载地址:http://fxbno.baihongyu.com/

你可能感兴趣的文章
JAVA简单选择排序算法原理及实现
查看>>
Spring MVC实现Junit Case
查看>>
HttpClient通过Post方式发送Json数据
查看>>
C# 枚举显示中文
查看>>
React是UI的未来吗?
查看>>
饿了么口碑实现超30亿美元独立融资 阿里软银领投
查看>>
火热的比特币创始人“中本聪”到底是谁?国外网友又有了新猜测!
查看>>
新西兰信报:移民规则变化 赴新中国学生人数减少
查看>>
中国人社部:2018年15个省(区、市)调整最低工资标准
查看>>
2019年春运启动 4683公里新线首次投入春运
查看>>
“小候鸟”返乡过年 无人陪伴儿童出行迎高峰
查看>>
2019年福彩新春贺词
查看>>
阿里云成中国唯一一家进入Forrester大数据服务榜单的科技公司
查看>>
深度预警:深入理解HBase的系统架构
查看>>
从 Java 到 Scala(一):面向对象谈起
查看>>
JSP第六篇【自定义标签之传统标签】
查看>>
Weex 事件传递的那些事儿
查看>>
Android性能优化:关于 内存泄露 的知识都在这里了!
查看>>
【备战春招/秋招系列】美团面经总结基础篇 (附详解答案)
查看>>
Rokid(全栈语音智能开发套件)开箱记
查看>>