读书人

JDK源码解析 java.util.HashMap种 jdk

发布时间: 2012-12-24 10:43:13 作者: rapoo

JDK源码解析 java.util.HashMap类 jdk1.6

?

/*

?* ?@(#)HashMap.java 1.73 07/03/13

?*

?* Copyright 2006 Sun Microsystems, Inc. All rights reserved.

?* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.

?*/

?

package java.util;

?

import java.io.*;

?

/**

基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。?

?

此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(get 和 put)提供稳定的性能。迭代 collection 视图所需的时间与 HashMap 实例的“容量”(桶的数量)及其大小(键-值映射关系数)成比例。所以,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。?

?

HashMap 的实例有两个参数影响其性能:初始容量 和加载因子。容量 是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。?

?

通常,默认加载因子 (.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。?

?

如果很多映射关系要存储在 HashMap 实例中,则相对于按需执行自动的 rehash 操作以增大表的容量来说,使用足够大的初始容量创建它将使得映射关系能更有效地存储。?

?

注意,此实现不是同步的。如果多个线程同时访问一个哈希映射,而其中至少一个线程从结构上修改了该映射,则它必须 保持外部同步。(结构上的修改是指添加或删除一个或多个映射关系的任何操作;仅改变与实例已经包含的键关联的值不是结构上的修改。)这一般通过对自然封装该映射的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedMap 方法来“包装”该映射。最好在创建时完成这一操作,以防止对映射进行意外的非同步访问,如下所示:

?

? Map m = Collections.synchronizedMap(new HashMap(...));由所有此类的“collection 视图方法”所返回的迭代器都是快速失败 的:在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器本身的 remove 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不冒在将来不确定的时间发生任意不确定行为的风险。?

?

注意,迭代器的快速失败行为不能得到保证,一般来说,存在非同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的做法是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。?

?

此类是 Java Collections Framework 的成员。?

?

?

?

从以下版本开始:?

1.2?

另请参见:

Object.hashCode(), Collection, Map, TreeMap, Hashtable, 序列化表格

?

?*/

?

public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>,

Cloneable, Serializable {

?

/**

* The default initial capacity - MUST be a power of two.

* 默认的初始容量——必须是2的幂。

*/

static final int DEFAULT_INITIAL_CAPACITY = 16; //默认的初始化容量

?

/**

* The maximum capacity, used if a higher value is implicitly specified by

* either of the constructors with arguments. MUST be a power of two <=

* 1<<30.

* 最大容量,如果有一个更大的值在带有参数构造方法中隐式的指定则会使用

*/

static final int MAXIMUM_CAPACITY = 1 << 30;

?

/**

* The load factor used when none specified in constructor.

* 当在构造方法中没有特别指定时会用默认的负载因子,默认为0.75f

*/

static final float DEFAULT_LOAD_FACTOR = 0.75f;

?

/**

* The table, resized as necessary. Length MUST Always be a power of two.

* Entry数组,必要时可以调整,长度也必须是2的幂

*/

transient Entry[] table;

?

/**

* The number of key-value mappings contained in this map.

* 在这个Map中键值对的数量

*/

transient int size;

?

/**

* The next size value at which to resize (capacity * load factor).

* 重构因子,下一个Map尺寸值,由(容量*负载因子)调整

* @serial

*/

int threshold;

?

/**

* The load factor for the hash table.

* Hash表的加载因子

* @serial

*/

final float loadFactor;

?

/**

* The number of times this HashMap has been structurally modified

* Structural modifications are those that change the number of mappings in

* the HashMap or otherwise modify its internal structure (e.g., rehash).

* This field is used to make iterators on Collection-views of the HashMap

* fail-fast. (See ConcurrentModificationException).

*/

transient volatile int modCount;

?

/**

构造一个带指定初始容量和加载因子的空 HashMap。?

?

参数:

initialCapacity - 初始容量

loadFactor - 加载因子?

抛出:?

IllegalArgumentException - 如果初始容量为负或者加载因子为非正

?

*/

public HashMap(int initialCapacity, float loadFactor) {

if (initialCapacity < 0) //初始化容量小于1,非法

throw new IllegalArgumentException("Illegal initial capacity: "

+ initialCapacity);

if (initialCapacity > MAXIMUM_CAPACITY) //初始化容量大于默认最大容量,则容量为默认最大容量

initialCapacity = MAXIMUM_CAPACITY;

if (loadFactor <= 0 || Float.isNaN(loadFactor)) //加载因子不大于0或不是数字,非法

throw new IllegalArgumentException("Illegal load factor: "

+ loadFactor);

?

// Find a power of 2 >= initialCapacity

int capacity = 1;

while (capacity < initialCapacity)

capacity <<= 1; ?// 2,4,8,16,....取最接近传入的初始化容量的最大的2的幂

?

this.loadFactor = loadFactor;

threshold = (int) (capacity * loadFactor); //容量

table = new Entry[capacity]; //实例化Entry数组

init();

}

?

/**

构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。?

?

参数:

initialCapacity - 初始容量。?

抛出:?

IllegalArgumentException - 如果初始容量为负。

?

*/

public HashMap(int initialCapacity) {

this(initialCapacity, DEFAULT_LOAD_FACTOR); //使用DEFAULT_LOAD_FACTOR,即0.75

}

?

/**

构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。?

*/

public HashMap() {

this.loadFactor = DEFAULT_LOAD_FACTOR; //DEFAULT_LOAD_FACTOR = 0.75

threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); //DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR = 16*0.75=12

table = new Entry[DEFAULT_INITIAL_CAPACITY]; //DEFAULT_INITIAL_CAPACITY = 16

init();

}

?

/**

构造一个映射关系与指定 Map 相同的新 HashMap。所创建的 HashMap 具有默认加载因子 (0.75) 和足以容纳指定 Map 中映射关系的初始容量。?

?

参数:

m - 映射,其映射关系将存放在此映射中?

抛出:?

NullPointerException - 如果指定的映射为 null

?

*/

public HashMap(Map<? extends K, ? extends V> m) {

this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,

DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); //初始化容量取传入的map和默认初始化容量中的大的值

putAllForCreate(m);

}

?

// internal utilities

?

/**

* Initialization hook for subclasses. This method is called in all

* constructors and pseudo-constructors (clone, readObject) after HashMap

* has been initialized but before any entries have been inserted. (In the

* absence of this method, readObject would require explicit knowledge of

* subclasses.)

*/

void init() { //初始化方法,未实现

}

?

/**

* Applies a supplemental hash function to a given hashCode, which defends

* against poor quality hash functions. This is critical because HashMap

* uses power-of-two length hash tables, that otherwise encounter collisions

* for hashCodes that do not differ in lower bits. Note: Null keys always

* map to hash 0, thus index 0.

* hash算法

*/

static int hash(int h) { //Hash算法

// This function ensures that hashCodes that differ only by

// constant multiples at each bit position have a bounded

// number of collisions (approximately 8 at default load factor).

h ^= (h >>> 20) ^ (h >>> 12);

return h ^ (h >>> 7) ^ (h >>> 4);

}

?

/**

* Returns index for hash code h.

*/

static int indexFor(int h, int length) {

return h & (length - 1);

}

?

/**

返回此映射中的键-值映射关系数。?

?

指定者:

接口 Map<K,V> 中的 size

覆盖:

类 AbstractMap<K,V> 中的 size

返回:

此映射中的键-值映射关系数

?

*/

public int size() {

return size;

}

?

/**

如果此映射不包含键-值映射关系,则返回 true。?

?

指定者:

接口 Map<K,V> 中的 isEmpty

覆盖:

类 AbstractMap<K,V> 中的 isEmpty

返回:

如果此映射不包含键-值映射关系,则返回 true

?

*/

public boolean isEmpty() {

return size == 0; //判断为空,即map的size为0

}

?

/**

返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。?

更确切地讲,如果此映射包含一个满足 (key==null ? k==null : key.equals(k)) 的从 k 键到 v 值的映射关系,则此方法返回 v;否则返回 null。(最多只能有一个这样的映射关系。)?

?

返回 null 值并不一定 表明该映射不包含该键的映射关系;也可能该映射将该键显示地映射为 null。可使用 containsKey 操作来区分这两种情况。?

?

?

指定者:

接口 Map<K,V> 中的 get

覆盖:

类 AbstractMap<K,V> 中的 get

参数:

key - 要返回其关联值的键?

返回:

指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null

另请参见:

put(Object, Object)

?

*/

public V get(Object key) {

if (key == null) //如果key等于null,则遍历key为null对应的value。

return getForNullKey();

int hash = hash(key.hashCode()); //遍历Entry数组,查找key对应的value。使用到了hash码。

for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {

Object k;

if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

return e.value;

}

return null;

}

?

/**

* Offloaded version of get() to look up null keys. Null keys map to index

* 0. This null case is split out into separate methods for the sake of

* performance in the two most commonly used operations (get and put), but

* incorporated with conditionals in others.

* 如果key为null,要取得value的值就调用该方法。

*/

private V getForNullKey() {

for (Entry<K, V> e = table[0]; e != null; e = e.next) {

if (e.key == null)

return e.value;

}

return null;

}

?

/**

如果此映射包含对于指定键的映射关系,则返回 true。?

?

指定者:

接口 Map<K,V> 中的 containsKey

覆盖:

类 AbstractMap<K,V> 中的 containsKey

参数:

key - 要测试其是否在此映射中存在的键?

返回:

如果此映射包含对于指定键的映射关系,则返回 true。

?

*/

public boolean containsKey(Object key) {

return getEntry(key) != null;

}

?

/**

* Returns the entry associated with the specified key in the HashMap.

* Returns null if the HashMap contains no mapping for the key.

* 使用hash码,遍历并返回对应key的整个Entry数组

*/

final Entry<K, V> getEntry(Object key) {

int hash = (key == null) ? 0 : hash(key.hashCode());

for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {

Object k;

if (e.hash == hash

&& ((k = e.key) == key || (key != null && key.equals(k))))

return e;

}

return null;

}

?

/**

在此映射中关联指定值与指定键。如果该映射以前包含了一个该键的映射关系,则旧值被替换。?

?

指定者:

接口 Map<K,V> 中的 put

覆盖:

类 AbstractMap<K,V> 中的 put

参数:

key - 指定值将要关联的键

value - 指定键将要关联的值?

返回:

与 key 关联的旧值;如果 key 没有任何映射关系,则返回 null。(返回 null 还可能表示该映射之前将 null 与 key 关联。)

?

*/

public V put(K key, V value) {

if (key == null)

return putForNullKey(value);

int hash = hash(key.hashCode());

int i = indexFor(hash, table.length);

for (Entry<K, V> e = table[i]; e != null; e = e.next) {

Object k;

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

V oldValue = e.value;

e.value = value;

e.recordAccess(this);

return oldValue;

}

}

?

modCount++;

addEntry(hash, key, value, i);

return null;

}

?

/**

* Offloaded version of put for null keys

*/

private V putForNullKey(V value) {

for (Entry<K, V> e = table[0]; e != null; e = e.next) {

if (e.key == null) {

V oldValue = e.value;

e.value = value;

e.recordAccess(this);

return oldValue;

}

}

modCount++;

addEntry(0, null, value, 0);

return null;

}

?

/**

* This method is used instead of put by constructors and pseudoconstructors

* (clone, readObject). It does not resize the table, check for

* comodification, etc. It calls createEntry rather than addEntry.

*/

private void putForCreate(K key, V value) {

int hash = (key == null) ? 0 : hash(key.hashCode());

int i = indexFor(hash, table.length);

?

/**

* Look for preexisting entry for key. This will never happen for clone

* or deserialize. It will only happen for construction if the input Map

* is a sorted map whose ordering is inconsistent w/ equals.

*/

for (Entry<K, V> e = table[i]; e != null; e = e.next) {

Object k;

if (e.hash == hash

&& ((k = e.key) == key || (key != null && key.equals(k)))) {

e.value = value;

return;

}

}

?

createEntry(hash, key, value, i);

}

?

private void putAllForCreate(Map<? extends K, ? extends V> m) {

for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m

.entrySet().iterator(); i.hasNext();) {

Map.Entry<? extends K, ? extends V> e = i.next();

putForCreate(e.getKey(), e.getValue());

}

}

?

/**

* Rehashes the contents of this map into a new array with a larger

* capacity. This method is called automatically when the number of keys in

* this map reaches its threshold.

*?

* If current capacity is MAXIMUM_CAPACITY, this method does not resize the

* map, but sets threshold to Integer.MAX_VALUE. This has the effect of

* preventing future calls.

*?

* @param newCapacity

* ? ? ? ? ? ?the new capacity, MUST be a power of two; must be greater than

* ? ? ? ? ? ?current capacity unless current capacity is MAXIMUM_CAPACITY

* ? ? ? ? ? ?(in which case value is irrelevant).

* 根据传入的数值重新调整Entry数组的大小。

*/

void resize(int newCapacity) {

Entry[] oldTable = table;

int oldCapacity = oldTable.length;

if (oldCapacity == MAXIMUM_CAPACITY) {

threshold = Integer.MAX_VALUE;

return;

}

?

Entry[] newTable = new Entry[newCapacity];

transfer(newTable);

table = newTable;

threshold = (int) (newCapacity * loadFactor);

}

?

/**

* Transfers all entries from current table to newTable.

* 转换

*/

void transfer(Entry[] newTable) {

Entry[] src = table;

int newCapacity = newTable.length;

for (int j = 0; j < src.length; j++) {

Entry<K, V> e = src[j];

if (e != null) {

src[j] = null;

do {

Entry<K, V> next = e.next;

int i = indexFor(e.hash, newCapacity);

e.next = newTable[i];

newTable[i] = e;

e = next;

} while (e != null);

}

}

}

?

/**

将指定映射的所有映射关系复制到此映射中,这些映射关系将替换此映射目前针对指定映射中所有键的所有映射关系。?

?

指定者:

接口 Map<K,V> 中的 putAll

覆盖:

类 AbstractMap<K,V> 中的 putAll

参数:

m - 要在此映射中存储的映射关系?

抛出:?

NullPointerException - 如果指定的映射为 null

?

*/

public void putAll(Map<? extends K, ? extends V> m) {

int numKeysToBeAdded = m.size();

if (numKeysToBeAdded == 0)

return;

?

/*

* Expand the map if the map if the number of mappings to be added is

* greater than or equal to threshold. This is conservative; the obvious

* condition is (m.size() + size) >= threshold, but this condition could

* result in a map with twice the appropriate capacity, if the keys to

* be added overlap with the keys already in this map. By using the

* conservative calculation, we subject ourself to at most one extra

* resize.

*/

if (numKeysToBeAdded > threshold) {

int targetCapacity = (int) (numKeysToBeAdded / loadFactor + 1);

if (targetCapacity > MAXIMUM_CAPACITY)

targetCapacity = MAXIMUM_CAPACITY;

int newCapacity = table.length;

while (newCapacity < targetCapacity)

newCapacity <<= 1;

if (newCapacity > table.length)

resize(newCapacity);

}

?

for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m

.entrySet().iterator(); i.hasNext();) {

Map.Entry<? extends K, ? extends V> e = i.next();

put(e.getKey(), e.getValue());

}

}

?

/**

从此映射中移除指定键的映射关系(如果存在)。?

?

指定者:

接口 Map<K,V> 中的 remove

覆盖:

类 AbstractMap<K,V> 中的 remove

参数:

key - 其映射关系要从映射中移除的键?

返回:

与 key 关联的旧值;如果 key 没有任何映射关系,则返回 null。(返回 null 还可能表示该映射之前将 null 与 key 关联。)

?

*/

public V remove(Object key) {

Entry<K, V> e = removeEntryForKey(key);

return (e == null ? null : e.value);

}

?

/**

* Removes and returns the entry associated with the specified key in the

* HashMap. Returns null if the HashMap contains no mapping for this key.

*/

final Entry<K, V> removeEntryForKey(Object key) {

int hash = (key == null) ? 0 : hash(key.hashCode());

int i = indexFor(hash, table.length);

Entry<K, V> prev = table[i];

Entry<K, V> e = prev;

?

while (e != null) {

Entry<K, V> next = e.next;

Object k;

if (e.hash == hash

&& ((k = e.key) == key || (key != null && key.equals(k)))) {

modCount++;

size--;

if (prev == e)

table[i] = next;

else

prev.next = next;

e.recordRemoval(this);

return e;

}

prev = e;

e = next;

}

?

return e;

}

?

/**

* Special version of remove for EntrySet.

* 移除映射关系

*/

final Entry<K, V> removeMapping(Object o) {

if (!(o instanceof Map.Entry))

return null;

?

Map.Entry<K, V> entry = (Map.Entry<K, V>) o;

Object key = entry.getKey();

int hash = (key == null) ? 0 : hash(key.hashCode());

int i = indexFor(hash, table.length);

Entry<K, V> prev = table[i];

Entry<K, V> e = prev;

?

while (e != null) {

Entry<K, V> next = e.next;

if (e.hash == hash && e.equals(entry)) {

modCount++;

size--;

if (prev == e)

table[i] = next;

else

prev.next = next;

e.recordRemoval(this);

return e;

}

prev = e;

e = next;

}

?

return e;

}

?

/**

从此映射中移除所有映射关系。此调用返回后,映射将为空。?

?

指定者:

接口 Map<K,V> 中的 clear

覆盖:

类 AbstractMap<K,V> 中的 clear

?

*/

public void clear() {

modCount++;

Entry[] tab = table;

for (int i = 0; i < tab.length; i++)

tab[i] = null;

size = 0;

}

?

/**

如果此映射将一个或多个键映射到指定值,则返回 true。?

?

指定者:

接口 Map<K,V> 中的 containsValue

覆盖:

类 AbstractMap<K,V> 中的 containsValue

参数:

value - 要测试其是否在此映射中存在的值?

返回:

如果此映射将一个或多个键映射到指定值,则返回 true

?

*/

public boolean containsValue(Object value) {

if (value == null)

return containsNullValue();

?

Entry[] tab = table;

for (int i = 0; i < tab.length; i++)

for (Entry e = tab[i]; e != null; e = e.next)

if (value.equals(e.value))

return true;

return false;

}

?

/**

* Special-case code for containsValue with null argument

* 判断是否包含null值

*/

private boolean containsNullValue() {

Entry[] tab = table;

for (int i = 0; i < tab.length; i++)

for (Entry e = tab[i]; e != null; e = e.next)

if (e.value == null)

return true;

return false;

}

?

/**

返回此 HashMap 实例的浅表副本:并不复制键和值本身。?

?

覆盖:

类 AbstractMap<K,V> 中的 clone

返回:

此映射的浅表副本

另请参见:

Cloneable

?

*/

public Object clone() {

HashMap<K, V> result = null;

try {

result = (HashMap<K, V>) super.clone();

} catch (CloneNotSupportedException e) {

// assert false;

}

result.table = new Entry[table.length];

result.entrySet = null;

result.modCount = 0;

result.size = 0;

result.init();

result.putAllForCreate(this);

?

return result;

}

?

//静态内部类 Entry,该类是HashMap实现的一个实体对象,实现了Map.Entry接口

static class Entry<K, V> implements Map.Entry<K, V> {

final K key;

V value;

Entry<K, V> next;

final int hash;

?

/**

* Creates new entry.

*/

Entry(int h, K k, V v, Entry<K, V> n) {

value = v;

next = n;

key = k;

hash = h;

}

?

public final K getKey() {

return key;

}

?

public final V getValue() {

return value;

}

?

public final V setValue(V newValue) {

V oldValue = value;

value = newValue;

return oldValue;

}

?

public final boolean equals(Object o) {

if (!(o instanceof Map.Entry))

return false;

Map.Entry e = (Map.Entry) o;

Object k1 = getKey();

Object k2 = e.getKey();

if (k1 == k2 || (k1 != null && k1.equals(k2))) {

Object v1 = getValue();

Object v2 = e.getValue();

if (v1 == v2 || (v1 != null && v1.equals(v2)))

return true;

}

return false;

}

?

public final int hashCode() {

return (key == null ? 0 : key.hashCode())

^ (value == null ? 0 : value.hashCode());

}

?

public final String toString() {

return getKey() + "=" + getValue();

}

?

/**

* This method is invoked whenever the value in an entry is overwritten

* by an invocation of put(k,v) for a key k that's already in the

* HashMap.

*/

void recordAccess(HashMap<K, V> m) {

}

?

/**

* This method is invoked whenever the entry is removed from the table.

*/

void recordRemoval(HashMap<K, V> m) {

}

}

?

/**

* Adds a new entry with the specified key, value and hash code to the

* specified bucket. It is the responsibility of this method to resize the

* table if appropriate.

*?

* Subclass overrides this to alter the behavior of put method.

*/

void addEntry(int hash, K key, V value, int bucketIndex) {

Entry<K, V> e = table[bucketIndex];

table[bucketIndex] = new Entry<K, V>(hash, key, value, e);

if (size++ >= threshold)

resize(2 * table.length);

}

?

/**

* Like addEntry except that this version is used when creating entries as

* part of Map construction or "pseudo-construction" (cloning,

* deserialization). This version needn't worry about resizing the table.

*?

* Subclass overrides this to alter the behavior of HashMap(Map), clone, and

* readObject.

*/

void createEntry(int hash, K key, V value, int bucketIndex) {

Entry<K, V> e = table[bucketIndex];

table[bucketIndex] = new Entry<K, V>(hash, key, value, e);

size++;

}

?

private abstract class HashIterator<E> implements Iterator<E> {

Entry<K, V> next; // next entry to return

int expectedModCount; // For fast-fail

int index; // current slot

Entry<K, V> current; // current entry

?

HashIterator() {

expectedModCount = modCount;

if (size > 0) { // advance to first entry

Entry[] t = table;

while (index < t.length && (next = t[index++]) == null)

;

}

}

?

public final boolean hasNext() {

return next != null;

}

?

final Entry<K, V> nextEntry() {

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

Entry<K, V> e = next;

if (e == null)

throw new NoSuchElementException();

?

if ((next = e.next) == null) {

Entry[] t = table;

while (index < t.length && (next = t[index++]) == null)

;

}

current = e;

return e;

}

?

public void remove() {

if (current == null)

throw new IllegalStateException();

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

Object k = current.key;

current = null;

HashMap.this.removeEntryForKey(k);

expectedModCount = modCount;

}

?

}

?

//私有的final内部类,提供对键值对中值的迭代的方法。

private final class ValueIterator extends HashIterator<V> {

public V next() {

return nextEntry().value;

}

}

?

//私有的final的内部类,提供对键值对中键的迭代的方法。

private final class KeyIterator extends HashIterator<K> {

public K next() {

return nextEntry().getKey();

}

}

?

//私有final的内部类,提供对键值对的映射关系的迭代的方法。

private final class EntryIterator extends HashIterator<Map.Entry<K, V>> {

public Map.Entry<K, V> next() {

return nextEntry();

}

}

?

// Subclass overrides these to alter behavior of views' iterator() method

//返回键迭代器对象

Iterator<K> newKeyIterator() {

return new KeyIterator();

}

//返回值迭代器对象

Iterator<V> newValueIterator() {

return new ValueIterator();

}

//返回键值对映射的迭代器对象。

Iterator<Map.Entry<K, V>> newEntryIterator() {

return new EntryIterator();

}

?

// Views

?

private transient Set<Map.Entry<K, V>> entrySet = null;

?

/**

返回此映射中所包含的键的 Set 视图。该 set 受映射的支持,所以对映射的更改将反映在该 set 中,反之亦然。如果在对 set 进行迭代的同时修改了映射(通过迭代器自己的 remove 操作除外),则迭代结果是不确定的。该 set 支持元素的移除,通过 Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作可从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。?

?

指定者:

接口 Map<K,V> 中的 keySet

覆盖:

类 AbstractMap<K,V> 中的 keySet

返回:

此映射中包含的键的 set 视图

?

*/

public Set<K> keySet() {

Set<K> ks = keySet;

return (ks != null ? ks : (keySet = new KeySet()));

}

?

//私有的final的内部类,是一个键值对中键的集合。

private final class KeySet extends AbstractSet<K> {

public Iterator<K> iterator() {

return newKeyIterator();

}

?

public int size() {

return size;

}

?

public boolean contains(Object o) {

return containsKey(o);

}

?

public boolean remove(Object o) {

return HashMap.this.removeEntryForKey(o) != null;

}

?

public void clear() {

HashMap.this.clear();

}

}

?

/**

返回此映射所包含的值的 Collection 视图。该 collection 受映射的支持,所以对映射的更改将反映在该 collection 中,反之亦然。如果在对 collection 进行迭代的同时修改了映射(通过迭代器自己的 remove 操作除外),则迭代结果是不确定的。该 collection 支持元素的移除,通过 Iterator.remove、Collection.remove、removeAll、retainAll 和 clear 操作可从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。?

?

指定者:

接口 Map<K,V> 中的 values

覆盖:

类 AbstractMap<K,V> 中的 values

?

*/

public Collection<V> values() {

Collection<V> vs = values;

return (vs != null ? vs : (values = new Values()));

}

?

//私有final的内部类,是一个键值对中值的对象的集合。

private final class Values extends AbstractCollection<V> {

public Iterator<V> iterator() {

return newValueIterator();

}

?

public int size() {

return size;

}

?

public boolean contains(Object o) {

return containsValue(o);

}

?

public void clear() {

HashMap.this.clear();

}

}

?

/**

返回此映射所包含的映射关系的 Set 视图。 该 set 受映射支持,所以对映射的更改将反映在此 set 中,反之亦然。如果在对 set 进行迭代的同时修改了映射(通过迭代器自己的 remove 操作,或者通过在该迭代器返回的映射项上执行 setValue 操作除外),则迭代结果是不确定的。该 set 支持元素的移除,通过 Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作可从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。?

?

指定者:

接口 Map<K,V> 中的 entrySet

指定者:

类 AbstractMap<K,V> 中的 entrySet

返回:

此映射所包含的映射关系的 set 视图。

?

*/

public Set<Map.Entry<K, V>> entrySet() {

return entrySet0();

}

?

//entrySet的具体实现

private Set<Map.Entry<K, V>> entrySet0() {

Set<Map.Entry<K, V>> es = entrySet; //声明一个Set指向entrySet,如果该set为null则实例化一个新的EntrySet对象。

return es != null ? es : (entrySet = new EntrySet());

}

?

private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {

public Iterator<Map.Entry<K, V>> iterator() {

return newEntryIterator();

}

?

public boolean contains(Object o) {

if (!(o instanceof Map.Entry))

return false;

Map.Entry<K, V> e = (Map.Entry<K, V>) o;

Entry<K, V> candidate = getEntry(e.getKey());

return candidate != null && candidate.equals(e);

}

?

public boolean remove(Object o) {

return removeMapping(o) != null;

}

?

public int size() {

return size;

}

?

public void clear() {

HashMap.this.clear();

}

}

?

/**

* Save the state of the <tt>HashMap</tt> instance to a stream (i.e.,

* serialize it).

*?

* @serialData The <i>capacity</i> of the HashMap (the length of the bucket

* ? ? ? ? ? ? array) is emitted (int), followed by the <i>size</i> (an int,

* ? ? ? ? ? ? the number of key-value mappings), followed by the key

* ? ? ? ? ? ? (Object) and value (Object) for each key-value mapping. The

* ? ? ? ? ? ? key-value mappings are emitted in no particular order.

* ?写入对象

*/

private void writeObject(java.io.ObjectOutputStream s) throws IOException {

Iterator<Map.Entry<K, V>> i = (size > 0) ? entrySet0().iterator()

: null;

?

// Write out the threshold, loadfactor, and any hidden stuff

s.defaultWriteObject();

?

// Write out number of buckets

s.writeInt(table.length);

?

// Write out size (number of Mappings)

s.writeInt(size);

?

// Write out keys and values (alternating)

if (i != null) {

while (i.hasNext()) {

Map.Entry<K, V> e = i.next();

s.writeObject(e.getKey());

s.writeObject(e.getValue());

}

}

}

?

private static final long serialVersionUID = 362498820763181265L;

?

/**

* Reconstitute the <tt>HashMap</tt> instance from a stream (i.e.,

* deserialize it).

* 读取对象

*/

private void readObject(java.io.ObjectInputStream s) throws IOException,

ClassNotFoundException {

// Read in the threshold, loadfactor, and any hidden stuff

s.defaultReadObject();

?

// Read in number of buckets and allocate the bucket array;

int numBuckets = s.readInt();

table = new Entry[numBuckets];

?

init(); // Give subclass a chance to do its thing.

?

// 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 < size; i++) {

K key = (K) s.readObject();

V value = (V) s.readObject();

putForCreate(key, value);

}

}

?

// These methods are used when serializing HashSets

//返回容量,在序列化HashSet时使用

int capacity() {

return table.length;

}

//返回加载因子

float loadFactor() {

return loadFactor;

}

}


读书人网 >编程

热点推荐