容器--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将是非常高效的。

时间: 2024-08-26 01:26:54

容器--EnumMap的相关文章

Java 容器 & 泛型:一、认识容器

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 容器是Java语言学习中重要的一部分.泥瓦匠我的感觉是刚开始挺难学的,但等你熟悉它,接触多了,也就"顺理成章"地知道了.Java的容器类主要由两个接口派生而出:Collection和Map. 一.Collection vs Collections 首先,Collection 和 Collections 是两个不同的概念.之所以放在一起,是为了更好的比较.Collection是容器层次结构中

EnumMap源代码阅读器

EnumMap是一个用于存放键值为enum类型的map.全部的键值必须来自一个单一的enum类型.EnumMap内部用数组表示效率更高. EnumMap维持键值的自然顺序(即枚举类型常量声明的顺序),能够通过keySet()和entrySet()方法的集合视图来体现其顺序. 集合视图返回的迭代器是弱一致的:遍历时候不会抛出ConcurrentModificationException.遍历过程中若对容器进行改动.改动产生的影响遍历过程可能可见也可能不可见. 不同意null键值插入,插入空值将会抛

Java容器-引用分类与部分Map用法

一.目录 1.引用分类 2.了解WeakHashMap.IdentityHashMap.EnumMap 3.同步控制与只读设置 二.代码实现 1.引用分类(面试) 强引用(StrongReference):引用指向对象,gc运行时,不回收. 弱引用(SoftReference):gc运行时可能回收(当jvm内存不足时). 软引用(WeakReference):当gc运行时,对象回收. 虚引用(phantomReference):类似于无银用,主要跟踪对象被回收的对象,不能单独使用,要与Refer

java并发容器(Map、List、BlockingQueue)

转发: 大海巨浪 Java库本身就有多种线程安全的容器和同步工具,其中同步容器包括两部分:一个是Vector和Hashtable.另外还有JDK1.2中加入的同步包装类,这些类都是由Collections.synchronizedXXX工厂方法.同步容器都是线程安全的,但是对于复合操作,缺有些缺点: ① 迭代:在查觉到容器在迭代开始以后被修改,会抛出一个未检查异常ConcurrentModificationException,为了避免这个异常,需要在迭代期间,持有一个容器锁.但是锁的缺点也很明显

EnumMap源码阅读

EnumMap是一个用于存放键值为enum类型的map,所有的键值必须来自一个单一的enum类型.EnumMap内部用数组表示效率更高. EnumMap维持键值的自然顺序(即枚举类型常量声明的顺序),可以通过keySet()和entrySet()方法的集合视图来提现顺序. 集合视图返回的迭代器是弱一致的:遍历时候不会抛出ConcurrentModificationException,遍历过程中若对容器进行修改,修改产生的影响遍历过程可能可见也可能不可见. 不允许null键值插入,插入空值将会抛出

java并发容器(Map、List、BlockingQueue)具体解释

Java库本身就有多种线程安全的容器和同步工具,当中同步容器包含两部分:一个是Vector和Hashtable.另外还有JDK1.2中增加的同步包装类.这些类都是由Collections.synchronizedXXX工厂方法. 同步容器都是线程安全的,可是对于复合操作.缺有些缺点: ① 迭代:在查觉到容器在迭代開始以后被改动,会抛出一个未检查异常ConcurrentModificationException,为了避免这个异常,须要在迭代期间,持有一个容器锁.可是锁的缺点也非常明显.就是对性能的

Java集合容器简介

Java集合容器主要有以下几类: 1,内置容器:数组 2,list容器:Vetor,Stack,ArrayList,LinkedList, CopyOnWriteArrayList(1.5),AttributeList(1.5),RoleList(1.5),RoleUnresolvedList(1.5), ConcurrentLinkedQueue(1.5),ArrayBlockingQueue(1.5),LinkedBlockingQueue(1.5), PriorityQueue(1.5),

Java集合容器总结

一.按数据结构主要有以下几类:内置.list.set.map: 1.内置容器:数组 2.list容器: Vetor,Stack,ArrayList,LinkedList,CopyOnWriteArrayList(1.5),AttributeList(1.5),RoleList(1.5),RoleUnresolvedList(1.5),ConcurrentLinkedQueue(1.5),ArrayBlockingQueue(1.5),LinkedBlockingQueue(1.5),Priori

C++ Map 容器

1.Map是c++的一个标准容器,它提供了很好一对一的关系. Map是一种关联是容器,在map中增加和删除元素非常容易.可以修改一个特定的节点而不对其他节点不产生影响,由于map是一种关联式容器,Key--value结构我们必须明确,在map中我们可以根据key的值修改其对应的value的值,而不能修改key的值,其最大的特点是key和value的值可以是任意类型(内部类型你或用户自己定义的类型). 2. Map的特点: (1)快速建立key--value的索引.key和value可以是任意类型