zoukankan      html  css  js  c++  java
  • EnumMap的用法和源码解析

    EnumMap的用法

       EnumMap顾名思义是保存枚举类型的Map.它要求map的key是枚举类型。这点在类定义的时候就已经声明好了EnumMap<K extends Enum<K>, V>,如何不是枚举类型编译会出错。

     eg:定义了一个Enum类 JdbcType。

       public enum JdbcType {
            INT,NUMBER,VARCHAR,VARCHAR2,LONG,BLOB,CHAR;
       }

    --------------------------------------------EnumMap的一个简单应用-----------------------------------------------

    public class EnumMapTest {

    public static void main(String[] args) {
         EnumMap<JdbcType, String> enumMap=new EnumMap<JdbcType, String>(JdbcType.class);
         enumMap.put(JdbcType.INT, "INT TYPE");
         enumMap.put(JdbcType.NUMBER, "NUMBER TYPE");
         enumMap.put(null,"NULL ");
         System.out.println(enumMap.get(JdbcType.INT));
    }
    }

        EnumMap的有什么优点,为什么我们要用EnumMap。

              .1 相比HashMap,EnumMap的性能和速度要快的多。EnumMap里面的数据结构是数组,获取的数据的时候特别快。而且添加的数据的时候(一般用put(K,V)),这里面的并不像一般数组一样,当插入到中间的位置时候,要数组整体移动(一般实现依次向后移动)。EnumMap实现不需要,因为数组在EnumMap实例化的时候就已经初始化好了,要做的就是对原来的oldValue进行覆盖,这样无论获取数据还是添加和删除数据都要快的多。这里特别提示一下,为什么EnumMap能够用数组,这得益于EnumMap的key是枚举类型,枚举类类型中每一种类型,在声明的时候都有确定的位置,可以通过对应的位置确定的枚举类型。通过该方法获得位置key.ordinal();

              2.枚举类型的相应的类型更加明确,key对应的范围更加明确。列如的key是string,那么你的键范围无法确定。所以能够用EnumMap,尽量用EnumMap这也是一种代码优化方案’

         EnumMap的大量用到各种框架中,在Mabatis的TypeHandlerRegistry中就用到了EnumMap:
      

         public final class TypeHandlerRegistry {

         private final Map<JdbcType, TypeHandler<?>> JDBC_TYPE_HANDLER_MAP = new EnumMap<JdbcType, TypeHandler<?>>(JdbcType.class);

         有兴趣的同学可以去看看TypeHandlerRegistry源码,会对EnumMap理解更加透彻。

      下面对EnumMap源码进行解析:

                                             

                  public EnumMap(Class<K> keyType) {   //EnumMap的构造器  keyType是key的类型,只能是枚举类型,否则不能编译过去
                     this.keyType = keyType; 
                     keyUniverse = getKeyUniverse(keyType);//getKeyUniverse方面获得该枚举中所有类型,返回一个数组该枚举类型中所有实例

                     vals = new Object[keyUniverse.length];//初始化该数组,该数组大小不会改变,因为枚举类型确定了,相同的键会进行值的覆盖,该数组也是map底层的数据结构

                 }


            新增方法:

    public V put(K key, V value) {
    typeCheck(key); //类型检查,只有该enum类型才能,进行数据录入。实际开发中null值可以编译通过,但是到这步检查会报空指针。

    int index = key.ordinal();//获取改值在enum中的声明的位置,通过该位置定位该值
    Object oldValue = vals[index];
    vals[index] = maskNull(value);
    if (oldValue == null) //oldNull为null为新增,oldNull有值进行覆盖
    size++;
    return unmaskNull(oldValue);
    }

    该方法 的用法API说的很清楚了:

       Associates the specified value with the specified key in this map.

       If the map previously contained a mapping for this key, the old
       value is replaced.


                删除方法:

                          public V remove(Object key) {

    if (!isValidKey(key)) // 如何该key是null,或者不是初始化时enum类型,直接返回null,不进行删除操作
    return null;
    int index = ((Enum<?>)key).ordinal(); //获取该值的位置,也是在数组中位置
    Object oldValue = vals[index]; //定位该值
    vals[index] = null; //对该值赋值null,也就是常见的逻辑删除,故删除速度也很快,不进行数组移动,定位之后,进行赋值操作
    if (oldValue != null) //原来有值对数组大小进行-1操作,否则不操作。
    size--;
    return unmaskNull(oldValue);
    }


                   get值方法:该方法很简单不做解释:

    public V get(Object key) {
    return (isValidKey(key) ?
    unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
    }

     

     EnumMap源码就解析到这里了,感兴趣的同学可以自己看看。

  • 相关阅读:
    如何将本地代码上传到GitHub
    《剑指offer》JavaScript版19-21题
    《剑指offer》JavaScript版16-18题
    《剑指offer》JavaScript版13-15题
    蘑菇街(前端1面)
    《二十二》观后感
    前端面试题(2)
    《深入理解ES6》之Promise
    HDU 4939 Stupid Tower Defense (2014 Multi-University Training Contest 7)
    HDU 4940 Destroy Transportation system(2014 Multi-University Training Contest 7)
  • 原文地址:https://www.cnblogs.com/caibixiang123/p/9214086.html
Copyright © 2011-2022 走看看