容器--EnumMap

一、概述

     EnumMap是一类特殊的Map, 其特殊之处在于KEY需要是枚举类型,由于枚举类型的特点是值的个数是固定的,所以,对于EnumMap来说,其所能存储的个数也就是固定的了。这种类型的Map相对来说是比较简单的。

 

二、主要实现介绍

  1. 初始化

  由于EnumMap的enum特点,决定了其容器的容量是不变的,所以,在创建一个EnumMap的时候,我们就需要指定其大小,目前创建一个EnumMap主要有以下几种方式:

     public EnumMap(Class<K> keyType) : 根据键的class类型,通过反射的方式得到该枚举的所有可能值,进而生成一个键数组及值数组。

     public EnumMap(EnumMap<K, ? extends V> m) :从另一个EnumMap去初始化,本质上是生成一个副本。

     public EnumMap(Map<K, ? extends V> m):根据另一个Map初始化,和第二个方法相比,多了个对Map的转化的过程 

 

     以上三种初始化方式之后,在内部都会创建一个key数组和value数组,它们的大小是相同的。特别的,由于对同一类enum来说,其key是固定的,所以key数组是可以复用的。

 

     2. 存储

     我们来看一下对于put操作的实现     

public V put(K key, V value) {
        typeCheck(key);//类型检查

        int index = key.ordinal();
        Object oldValue = vals[index];
        vals[index] = maskNull(value);//null值处理
        if (oldValue == null)
            size++;
        return unmaskNull(oldValue);
    }

      可以看到整个实现非常简单,key对应的value被存储在vals数组中,key的ordinal对应的下标的位置。

      需要注意的是,在存储时,系统对于值进行了maskNull的处理,在返回时做了unmaskNull处理,我们接着看下相关的代码:

    private static final Object NULL = new Object() {
        public int hashCode() {
            return 0;
        }

        public String toString() {
            return "java.util.EnumMap.NULL";
        }
    };

    private Object maskNull(Object value) {
        return (value == null ? NULL : value);
    }

    private V unmaskNull(Object value) {
        return (V) (value == NULL ? null : value);
    }

 

       可以看到这个方法的作用是,如果目标value为null,则用NULL对象来替换,那么为什么要这样做呢?

       这是因为,vals数组中,默认是没有值的,而这个用null来表示。那么,EnumMap本身是支持值为null的,如果不做任何处理将vals设置为null,则无法和没有值的情况进行区分,所以借助于这种方式来实现对于null值的表示。

 

      3. 取值

      和存值一样,取值也是比较简单的,如下:

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

      可见相比较于HashMap,这个取值操作是直接定位的,非常快速。

 

      4. key存在判断

  前面说到,初始化时实际上就已经确定了key的数组,那么,是否表示所有的key都存在呢?参见实现:

public boolean containsKey(Object key) {
        return isValidKey(key) && vals[((Enum)key).ordinal()] != null;
    }

      可见,如果某个key对应的下标没有设置值,系统认为这个key是未被包含的。

 

三、总结

 

     从前面的分析我们可以看到,EnumMap的实现非常简单,而且存取都非常高效,如果我们的业务场景是可以设置几个固定的key的值的话,那么用这类key将是非常高效的。

       

    

 

     

 

posted @ 2016-08-31 22:56  海上劳工  阅读(362)  评论(1编辑  收藏  举报