热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

EnumMap类源码解析

EnumMap内部通过数组存在元素key:表示的是枚举类型,这个类型要一样用value存储枚举具体的存储值通过ordinal方法,使得有序存储packagejava.util

EnumMap
内部通过数组存在元素
key:表示的是枚举类型,这个类型要一样
用value存储枚举具体的存储值
通过ordinal方法,使得有序存储


package java.util;

import java.util.Map.Entry;
import sun.misc.SharedSecrets;

/**
* @author Josh Bloch
* @see EnumSet
* @since 1.5
*/

public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
implements java.io.Serializable, Cloneable
{
/**
* 类型
*
* @serial
*/

private final Class keyType;

/**
* key要是枚举类型
*/

private transient K[] keyUniverse;

/**
*内部数组存储values
*/

private transient Object[] vals;

/**
*map的大小
*/

private transient int size = 0;

/**
* 空时候
*/

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);
}
// 0 个元素的 Enum
private static final Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0];

/**
* 指定key类型的构造函数
*
* @param keyType the class object of the key type for this enum map
* @throws NullPointerException if keyType is null
*/

public EnumMap(Class keyType) {
this.keyType = keyType;
keyUniverse = getKeyUniverse(keyType);
vals = new Object[keyUniverse.length];
}

/**
* 创建一个enum map 和指定Enummap有相同的key类型,并用该map进行初始化
*
* @param m the enum map from which to initialize this enum map
* @throws NullPointerException if m is null
*/

public EnumMap(EnumMapextends V> m) {
keyType = m.keyType;
keyUniverse = m.keyUniverse;
vals = m.vals.clone();
size = m.size;
}

/**
* 利用指定map 创建一个enum map
*
* @param m the map from which to initialize this enum map
* @throws IllegalArgumentException if m is not an
* EnumMap instance and contains no mappings
* @throws NullPointerException if m is null
*/

public EnumMap(Mapextends V> m) {
if (m instanceof EnumMap) {
EnumMapextends V> em = (EnumMapextends 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);
}
}

// Query Operations

/**
* 元素个数
*
* @return the number of key-value mappings in this map
*/

public int size() {
return size;
}

/**
* 是否包含value的元素 先验证是否是有效的value,在遍历
* @param value the value whose presence in this map is to be tested
* @return true if this map maps one or more keys to this value
*/

public boolean containsValue(Object value) {
value = maskNull(value);

for (Object val : vals)
if (value.equals(val))
return true;

return false;
}

/**
*是否包含key 的元素,先验证是否是有效的key,再遍历
* @param key the key whose presence in this map is to be tested
* @return true if this map contains a mapping for the specified
* key
*/

public boolean containsKey(Object key) {
return isValidKey(key) && vals[((Enum)key).ordinal()] != null;
}
// 是否包含该元素
private boolean containsMapping(Object key, Object value) {
return isValidKey(key) &&
maskNull(value).equals(vals[((Enum)key).ordinal()]);
}

/**
* 获取key对应value
*/

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

// Modification Operations

/**
* 加入元素
* @throws NullPointerException if the specified key is null
*/

public V put(K key, V value) {
typeCheck(key);

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

/**
* 删除元素
*/

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);
}

private boolean removeMapping(Object key, Object value) {
if (!isValidKey(key))
return false;
int index = ((Enum)key).ordinal();
if (maskNull(value).equals(vals[index])) {
vals[index] = null;
size--;
return true;
}
return false;
}

/**
*是否有效的key
*/

private boolean isValidKey(Object key) {
if (key == null)
return false;

// Cheaper than instanceof Enum followed by getDeclaringClass
Class keyClass = key.getClass();
return keyClass == keyType || keyClass.getSuperclass() == keyType;
}

// Bulk Operations

/**
* map中元素加入到EnumMap
* @param m the mappings to be stored in this map
* @throws NullPointerException the specified map is null, or if
* one or more keys in the specified map are null
*/

public void putAll(Mapextends K, ? extends V> m) {
if (m instanceof EnumMap) {
EnumMapextends K, ? extends V> em =
(EnumMapextends K, ? extends V>)m;
if (em.keyType != keyType) {
if (em.isEmpty())
return;
throw new ClassCastException(em.keyType + " != " + keyType);
}

for (int i = 0; i Object emValue = em.vals[i];
if (emValue != null) {
if (vals[i] == null)
size++;
vals[i] = emValue;
}
}
} else {
super.putAll(m);
}
}

/**
* 清空
*/

public void clear() {
Arrays.fill(vals, null);
size = 0;
}

// Views


private transient Set> entrySet = null;

/**
* @return a set view of the keys contained in this enum map
*/

public Set keySet() {
Set ks = keySet;
if (ks != null)
return ks;
else
return keySet = new KeySet();
}

private class KeySet extends AbstractSet<K> {
public Iterator iterator() {
return new KeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
int oldSize = size;
EnumMap.this.remove(o);
return size != oldSize;
}
public void clear() {
EnumMap.this.clear();
}
}

/**
* @return a collection view of the values contained in this map
*/

public Collection values() {
Collection vs = values;
if (vs != null)
return vs;
else
return values = new Values();
}

private class Values extends AbstractCollection<V> {
public Iterator iterator() {
return new ValueIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsValue(o);
}
public boolean remove(Object o) {
o = maskNull(o);

for (int i = 0; i if (o.equals(vals[i])) {
vals[i] = null;
size--;
return true;
}
}
return false;
}
public void clear() {
EnumMap.this.clear();
}
}

/**
* @return a set view of the mappings contained in this enum map
*/

public Set> entrySet() {
Set> es = entrySet;
if (es != null)
return es;
else
return entrySet = new EntrySet();
}

private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public Iterator> iterator() {
return new EntryIterator();
}

public boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry entry = (Map.Entry)o;
return containsMapping(entry.getKey(), entry.getValue());
}
public boolean remove(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry entry = (Map.Entry)o;
return removeMapping(entry.getKey(), entry.getValue());
}
public int size() {
return size;
}
public void clear() {
EnumMap.this.clear();
}
public Object[] toArray() {
return fillEntryArray(new Object[size]);
}
@SuppressWarnings("unchecked")
public T[] toArray(T[] a) {
int size = size();
if (a.length a = (T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
if (a.length > size)
a[size] = null;
return (T[]) fillEntryArray(a);
}
private Object[] fillEntryArray(Object[] a) {
int j = 0;
for (int i = 0; i if (vals[i] != null)
a[j++] = new AbstractMap.SimpleEntry<>(
keyUniverse[i], unmaskNull(vals[i]));
return a;
}
}

private abstract class EnumMapIterator<T> implements Iterator<T> {
// Lower bound on index of next element to return
int index = 0;

// Index of last returned element, or -1 if none
int lastReturnedIndex = -1;

public boolean hasNext() {
while (index null)
index++;
return index != vals.length;
}

public void remove() {
checkLastReturnedIndex();

if (vals[lastReturnedIndex] != null) {
vals[lastReturnedIndex] = null;
size--;
}
lastReturnedIndex = -1;
}

private void checkLastReturnedIndex() {
if (lastReturnedIndex <0)
throw new IllegalStateException();
}
}

private class KeyIterator extends EnumMapIterator<K> {
public K next() {
if (!hasNext())
throw new NoSuchElementException();
lastReturnedIndex = index++;
return keyUniverse[lastReturnedIndex];
}
}

private class ValueIterator extends EnumMapIterator<V> {
public V next() {
if (!hasNext())
throw new NoSuchElementException();
lastReturnedIndex = index++;
return unmaskNull(vals[lastReturnedIndex]);
}
}

private class EntryIterator extends EnumMapIterator<Map.Entry<K,V>> {
private Entry lastReturnedEntry = null;

public Map.Entry next() {
if (!hasNext())
throw new NoSuchElementException();
lastReturnedEntry = new Entry(index++);
return lastReturnedEntry;
}

public void remove() {
lastReturnedIndex =
((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
super.remove();
lastReturnedEntry.index = lastReturnedIndex;
lastReturnedEntry = null;
}

private class Entry implements Map.Entry<K,V> {
private int index;

private Entry(int index) {
this.index = index;
}

public K getKey() {
checkIndexForEntryUse();
return keyUniverse[index];
}

public V getValue() {
checkIndexForEntryUse();
return unmaskNull(vals[index]);
}

public V setValue(V value) {
checkIndexForEntryUse();
V oldValue = unmaskNull(vals[index]);
vals[index] = maskNull(value);
return oldValue;
}

public boolean equals(Object o) {
if (index <0)
return o == this;

if (!(o instanceof Map.Entry))
return false;

Map.Entry e = (Map.Entry)o;
V ourValue = unmaskNull(vals[index]);
Object hisValue = e.getValue();
return (e.getKey() == keyUniverse[index] &&
(ourValue == hisValue ||
(ourValue != null && ourValue.equals(hisValue))));
}

public int hashCode() {
if (index <0)
return super.hashCode();

return entryHashCode(index);
}

public String toString() {
if (index <0)
return super.toString();

return keyUniverse[index] + "="
+ unmaskNull(vals[index]);
}

private void checkIndexForEntryUse() {
if (index <0)
throw new IllegalStateException("Entry was removed");
}
}
}

// Comparison and hashing

/**
* equals
*/

public boolean equals(Object o) {
if (this == o)
return true;
if (o instanceof EnumMap)
return equals((EnumMap)o);
if (!(o instanceof Map))
return false;

Map m = (Map)o;
if (size != m.size())
return false;

for (int i = 0; i if (null != vals[i]) {
K key = keyUniverse[i];
V value = unmaskNull(vals[i]);
if (null == value) {
if (!((null == m.get(key)) && m.containsKey(key)))
return false;
} else {
if (!value.equals(m.get(key)))
return false;
}
}
}

return true;
}

private boolean equals(EnumMap em) {
if (em.keyType != keyType)
return size == 0 && em.size == 0;

// Key types match, compare each value
for (int i = 0; i Object ourValue = vals[i];
Object hisValue = em.vals[i];
if (hisValue != ourValue &&
(hisValue == null || !hisValue.equals(ourValue)))
return false;
}
return true;
}

/**
* hashCode
*/

public int hashCode() {
int h = 0;

for (int i = 0; i if (null != vals[i]) {
h += entryHashCode(i);
}
}

return h;
}

private int entryHashCode(int index) {
return (keyUniverse[index].hashCode() ^ vals[index].hashCode());
}

/**
* clone
*/

public EnumMap clone() {
EnumMap result = null;
try {
result = (EnumMap) super.clone();
} catch(CloneNotSupportedException e) {
throw new AssertionError();
}
result.vals = result.vals.clone();
result.entrySet = null;
return result;
}

/**
* Throws an exception if e is not of the correct type for this enum set.
*/

private void typeCheck(K key) {
Class keyClass = key.getClass();
if (keyClass != keyType && keyClass.getSuperclass() != keyType)
throw new ClassCastException(keyClass + " != " + keyType);
}

/**
* Returns all of the values comprising K.
* The result is uncloned, cached, and shared by all callers.
*/

private static extends Enum> K[] getKeyUniverse(Class keyType) {
return SharedSecrets.getJavaLangAccess()
.getEnumConstantsShared(keyType);
}

private static final long serialVersiOnUID= 458661240069192865L;

/**
* Save the state of the EnumMap instance to a stream (i.e.,
* serialize it).
*
* @serialData The size of the enum map (the number of key-value
* mappings) is emitted (int), followed by the key (Object)
* and value (Object) for each key-value mapping represented
* by the enum map.
*/

private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException
{
// Write out the key type and any hidden stuff
s.defaultWriteObject();

// Write out size (number of Mappings)
s.writeInt(size);

// Write out keys and values (alternating)
int entriesToBeWritten = size;
for (int i = 0; entriesToBeWritten > 0; i++) {
if (null != vals[i]) {
s.writeObject(keyUniverse[i]);
s.writeObject(unmaskNull(vals[i]));
entriesToBeWritten--;
}
}
}

/**
* Reconstitute the EnumMap instance from a stream (i.e.,
* deserialize it).
*/

private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException
{
// Read in the key type and any hidden stuff
s.defaultReadObject();

keyUniverse = getKeyUniverse(keyType);
vals = new Object[keyUniverse.length];

// Read in size (number of Mappings)
int size = s.readInt();

// Read the keys and values, and put the mappings in the HashMap
for (int i = 0; i K key = (K) s.readObject();
V value = (V) s.readObject();
put(key, value);
}
}
}

推荐阅读
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
author-avatar
李2502933835
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有