源码解读—HashMap
更新:文章中“阀值”这个词是错误的,正确的是“阈值”,意思:阈值又叫临界值,是指一个效应能够产生的最低值或最高值。
*********************************************************************************
什么是HashMap ? hashMap是用什么基础数据结构实现的?HashMap是如何解决hashCode冲突的?
hashMap的基础容器是数组+链表(transient Entry[] table)。进行存储时:
程序根据key值去hashCode: int hash = hash(key.hashCode());
然后根据hashCode找到在table中的index: int i = indexFor(hash, table.length);
然后从table中取出链表(该链表是解决hash冲突的,详细了解可以看一下“链地址法”):Entry<K,V> e = table[i];
循环链表取值或者存储等
分析类先看父类和接口:由此可知道本类有什么特性和功能。
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
Map:他是一个Map,存储key-value类型的键值对数据
Cloneable:他可以被克隆
Serializable:他可以被序列化和反序列化
知道了特性就看一下怎么new HashMap对象的:
1、四个构造方法进行实例化。
aaarticlea/png;base64,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" alt="" />
第一个构造器: public HashMap() ;
/**
* 以容量16,系数为0.75构造一个空的HashMap
* Constructs an empty <tt>HashMap</tt> with the default initial capacity
* (16) and the default load factor (0.75).
*/
//DEFAULT_LOAD_FACTOR=0.75
//DEFAULT_INITIAL_CAPACITY= 16
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
// threshold:阈值,用于判断是否需要扩容,如果容量>threshold,则需要进行扩容操作
threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
//table为一个Entry数组 ,实例化table,初始容量16。
table = new Entry[DEFAULT_INITIAL_CAPACITY];
init();
}
此处调用了 void init() ;在hashMap中并未有特殊应用,只是为子类预留其他初始化操作
/**
* 该方法是为子类留用的,在hashMap初始化之后调用,在子类中覆写该方法进行一写子类的特殊操作
* 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() {
}
第二个构造器: public HashMap(int initialCapacity) ;
/**
* 用指定的初始化容量(initialCapacity)和默认的系数0.75来创建一个HashMap
* Constructs an empty <tt>HashMap</tt> with the specified initial
* capacity and the default load factor (0.75).
*
* @param initialCapacity the initial capacity.
* @throws IllegalArgumentException if the initial capacity is negative.
*/
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);//调用第三个构造器
}
第三个构造器: public HashMap(int initialCapacity, float loadFactor);
/**
* 用指定的容量和系数来创建HashMap
* Constructs an empty <tt>HashMap</tt> with the specified initial
* capacity and load factor.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public HashMap(int initialCapacity, float loadFactor) {
//容量小于0 抛出不合法参数异常
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +initialCapacity);
//如果初始化容量大于1<<30,则按照最大容量进行初始化 MAXIMUM_CAPACITY == 1 << 30 == 2^30
if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY;
//如果阀值系数<=0或者Not-a-Number 抛出不合法参数异常
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
// Find a power of 2 >= initialCapacity
int capacity = 1;
//初始化initialCapacity如果不是2^n,则取大于initialCapacity的最小2^n为初始化容量。为什么会这样????见:附录01
while (capacity < initialCapacity)
// <<= 还能这样玩,长见识了!!!
capacity <<= 1;
//这四行和HashMap()相同
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor);
table = new Entry[capacity];
init();
}
第四个构造器: public HashMap(Map<? extends K, ? extends V> m);
/**
*构造一个新的HashMap,数据内容和指定的Map相同
*该新的HashMap的load factor 依旧是hi0.75,容量和指定的Map相同
* Constructs a new <tt>HashMap</tt> with the same mappings as the
* specified <tt>Map</tt>. The <tt>HashMap</tt> is created with
* default load factor (0.75) and an initial capacity sufficient to
* hold the mappings in the specified <tt>Map</tt>.
*
* @param m the map whose mappings are to be placed in this map
* @throws NullPointerException if the specified map is 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);
putAllForCreate(m);
}
在这里程序调用了private void putAllForCreate(Map<? extends K, ? extends V> m);在这里暂时不解释,在下面会进行解释。
2、五个putXXX()方法的实现:
aaarticlea/png;base64,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" alt="" />
第一个put()方法: public V put(K key, V value) ;
/**
* 把给定的K-V键值对放入map,如果map已经有关于K的映射,则把value覆盖以前的旧值
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for the key, the old
* value is replaced.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>null</tt> return can also indicate that the map
* previously associated <tt>null</tt> with <tt>key</tt>.)
*/
public V put(K key, V value) {
//如果key为null,调用putForNullKey()进行存储,由此可见 HashMap的key允许为null
if (key == null)
return putForNullKey(value);
//根据hash算法计算hashCode
int hash = hash(key.hashCode());
//根据hashCode和table.length找到key所在table数组中的下标
int i = indexFor(hash, table.length);
//取出table[i]的链表头节点,循环链表判断是否有重复数据
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
//此处判重为什么不直接判断key值,而要同时判断hash是否相同?既然已经找到table[i],只需要在链表中判断key是否相同即可?? 标识:XX04
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;
}
这里调用了: private V putForNullKey(V value);
第二个put()方法: private V putForNullKey(V value);
/**
* Offloaded version :没有翻译出什么意思
* 把key为null的值放入map
* Offloaded version of put for null keys
*/
private V putForNullKey(V value) {
//HashMap是用数组+链表进行数据存储的,在这里,程序把所有key为null的value放在table[0]的链表中。
//但不等同于table[0]的链表中不会存储key!= null的数据,因为有些key值通过hashCode()计算出的数组下标有可能为0
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
//找到key== null的节点,跟新value值
if (e.key == null) {
V oldValue = e.value;
e.value = value;
//这个方法没看出来是干嘛的 标识:XX01
e.recordAccess(this);
return oldValue;
}
}
//如果HashMap中没找打key为null的值,则进行插入操作
//修改次数+1 标识:XX02
modCount++;
//把数据添加到table[0]位置上链表的第一个元素
addEntry(0, null, value, 0);
return null;
}
在private V putForNullKey(V value);中继续调用了void addEntry(int hash, K key, V value, int bucketIndex) ;
/**
* 把给定的key、value、和hashCode组成的entry放入容器,如果被appropriate则需要去修改table的size
* 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.
*子类可以通过覆写这个方法去修改put方法。
* Subclass overrides this to alter the behavior of put method.
*/
void addEntry(int hash, K key, V value, int bucketIndex) {
//取出table[bucketIndex]位置的链表节点e
Entry<K,V> e = table[bucketIndex];
// 创建新的entry放在table[bucketIndex]
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
//如果需要调整大小则进行resize()操作
if (size++ >= threshold)
//按照两倍进行扩容,依旧符合容量为偶数的标准
resize(2 * table.length);
}
在void addEntry(int hash, K key, V value, int bucketIndex) 中继续调用了 void resize(int newCapacity);
/**
* 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).
*/
void resize(int newCapacity) {
//先保存原数据
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
//如果table容量已经达到最大值,此时无法再继续扩容,只能提高阀值,把threshold设置为Integer.MAX_VALUE。
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
//新创建一个table size=newCapacity
Entry[] newTable = new Entry[newCapacity];
//把原数据复制进新table中
transfer(newTable);
//更新table
table = newTable;
//更新threshold
threshold = (int)(newCapacity * loadFactor);
}
在void resize(int newCapacity);中又继续调用了void transfer(Entry[] newTable);
/**
* 把entrys从当前的table转移到newTable
* Transfers all entries from current table to newTable.
*/
void transfer(Entry[] newTable) {
Entry[] src = table;
int newCapacity = newTable.length;
//循环复制table
for (int j = 0; j < src.length; j++) {
Entry<K,V> e = src[j];
if (e != null) {
//取消指向链表的引用,交由gc进行处理
src[j] = null;
//循环复制链表
do {
Entry<K,V> next = e.next;
//根据hashCode计算该该节点 在table中所处的位置
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];//注意此处返回的是链表的头节点,不是一个整链表,不要理解错误(弄明白什么是链表,什么事节点以及他们的关系)
newTable[i] = e;//把加入链表的节点加在table[i]中。
e = next;
} while (e != null);
}
}
}
这里的 static int indexFor(int h, int length) ;是计算该entry在table中的位置。
/**
* Returns index for hash code h.
*/
static int indexFor(int h, int length) {
//为什么这样计算呢? 标识:XX03
return h & (length-1);
}
------------------------------至此第一个put()方法结束,再看第二个put()方法------------------------------------------------------
第三个put()方法: public void putAll(Map<? extends K, ? extends V> m) ;
/**
* 把给定的map复制进this.map,如果给定的map中有与this.map重复的key,则this.map中的数值将会被覆盖掉
* Copies all of the mappings from the specified map to this map.
* These mappings will replace any mappings that this map had for
* any of the keys currently in the specified map.
*
* @param m mappings to be stored in this map
* @throws NullPointerException if the specified map is null
*/
public void putAll(Map<? extends K, ? extends V> m) {
int numKeysToBeAdded = m.size();
//如果m为空map则返回
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.
*/
//如果addedMap的容量大于this.map的阀值则进行扩容
if (numKeysToBeAdded > threshold) {
//因为 threshold = (int)(capacity * loadFactor);所以capacity= threshold/loadFactor,为什么后面需要+1? 标识:XX05
int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
//容量最大只能取MAXIMUM_CAPACITY
if (targetCapacity > MAXIMUM_CAPACITY)
targetCapacity = MAXIMUM_CAPACITY; int newCapacity = table.length;
//求出newCapacity
while (newCapacity < targetCapacity)
newCapacity <<= 1;
//进行扩容操作
if (newCapacity > table.length)
resize(newCapacity);
}
//通过迭代器进行table复制
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());
}
}
第四个put(): private void putForCreate(K key, V value) ;
/**
* 该方法将会被构造器调用而不是put()。不需要对容器进行大小判断和扩容操作
* 这是创建entry而不是添加entry
* 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); /**
* 通过key寻找以前存在的entry,在克隆和反序列化的时候不会发生,
* 当map是一个有序map且
* 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;
}
}
//创建一个新的entry
createEntry(hash, key, value, i);
}
此处调用: void createEntry(int hash, K key, V value, int bucketIndex) ;
/**
* 该方法除了在一些构造器中创建新的entry之外和addEntry一样。这个版本不需要担心调整容量的问题
* 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.
*
*子类通过重写该方法去修改HashMap(Map)的构造方法、clone和readObject。
*即:只有这三个方法才会调用该方法,而这三个方法是进行创建、克隆和反序列化,而不是添加新的entry,因此不必考虑容量的问题。
* 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++;
}
该方法的三个调用处:
aaarticlea/png;base64,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02HYRtVLksPToRMHC2KKWaRDc/2kQwBopE5Jh7fv3xwZuXH8+I3jgzeOD26OjKzcvi90FU8c8cwXezPT9GivaWa5mIhZepmwq4bF5Q6yNi24+BqgLcwkRou+dCg31/StR0qHARt1Cit7VR8TldeFeE6d3P6xq5YOtVlmV9Ataa6NjWeGL2fEW76ZZTv8mWeWF4qZemeWlYG0xVI6qYa8bD6XdVOXsZiYxlXuj6NUEpoO/VPAEdu2MVnQThAsV0+HznCjMlnsG0T0NNs9eVHfJ7sc6RBAS3RKOrxl743s11Urt+wNXcU3WGW4iME+v82yLKsnPiBDg5zK7E2M1nK/w/iAPtHpH0jzNEBd6BRzZkvd60KCurDTW09r9zsMHjv0b1SZ8FX3qtovZUZYNkYpUPexi5AOjdcsB6VDO+FduqAsqXZVyuqw+268OF/v2KFy2t/YRF4Zn9NCkrmYNxR6K5G3j6kvHQa0bXbCnQp2mlc1HZYXS2nZF/2sSl/9S4VsMjfhXuPSKdFwmXQIoEU6JR1++GN+Le9FdcaRqppWj/Sklp3ZehXNugdNg9vcxg+PqfmuMd2jc6aSPUiHAFqiQ9LhLjU92hvtQXyhNdR7f77tbz3U7kuHO/WslAaR96mBF+kQABqJdNgihpu2dNjWd186bF9r+Q6bMG000iEANBLpEADaFN+EAFqCdAgAbYpvQgAtQToEgDbFNyGAliAdAkCb4psQQEuQDgGgTfFNCKAlSIcA0Kb4JgTQEqRDAGhTfBMCaIl2T4cAgJZ/JwPoKqRDAGh3Lf9OBtBVSIcA0O5a/p0MoKu0aToEAABAS5AOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIJEOAQAAIP1/Qz3twRdnz4gAAAAASUVORK5CYII=" alt="" />
第五个put()方法: private void putAllForCreate(Map<? extends K, ? extends V> m) ;
//不再解释
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());
}
}
putXXX()说完再看三个getXXX();
3、getXXX(),的实现。
aaarticlea/png;base64,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" alt="" />
第一个get(); final Entry<K,V> getEntry(Object key);
/**
* 返回指定key在hashMap中关联的entry,如果没有包含该key则返回null
* Returns the entry associated with the specified key in the
* HashMap. Returns null if the HashMap contains no mapping
* for the key.
*/
//循环 判断 返回 不讲
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key.hashCode());
//注意此for循环的使用
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;
}
第二个get():private V getForNullKey() ;
/**
* 老版本中通过get()方法寻找key为null的值,key为null的值放在tableb[0]的位置
*
* 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;
}
第三个get():public V get(Object key) ;
/**
* 返回指定key在map中的value值,当map中没有该key时返回null值
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*
* <p>More formally, if this map contains a mapping from a key
* {@code k} to a value {@code v} such that {@code (key==null ? k==null :
* key.equals(k))}, then this method returns {@code v}; otherwise
* it returns {@code null}. (There can be at most one such mapping.)
*
* <p>A return value of {@code null} does not <i>necessarily</i>
* indicate that the map contains no mapping for the key; it's also
* possible that the map explicitly maps the key to {@code null}.
* The {@link #containsKey containsKey} operation may be used to
* distinguish these two cases.
*
* @see #put(Object, Object)
*/
//与上面类似
public V get(Object key) {
if (key == null)
//见上面的讲解
return getForNullKey();
int hash = 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.equals(k)))
return e.value;
}
return null;
}
4、其他重要方法实现
public boolean containsKey(Object key);
/**
* 如果map中有指定的key则返回true
* Returns <tt>true</tt> if this map contains a mapping for the
* specified key.
*
* @param key The key whose presence in this map is to be tested
* @return <tt>true</tt> if this map contains a mapping for the specified
* key.
*/
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
void resize(int newCapacity)
/**
* 把map中的内容改写到一个容量更大的map中去,当插入时key的数量达到阀值的时候回自动调用本方法
* 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).
*/
void resize(int newCapacity) {
//先保存原数据
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
//如果table容量已经达到最大值,此时无法再继续扩容,只能提高阀值,把threshold设置为Integer.MAX_VALUE。
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
//新创建一个table size=newCapacity
Entry[] newTable = new Entry[newCapacity];
//把原数据复制进新table中
transfer(newTable);
//更新table
table = newTable;
//更新threshold
threshold = (int)(newCapacity * loadFactor);
}
几个removeXXX()操作:
/**
* 如果存在则删除指定key的entry
* Removes the mapping for the specified key from this map if present.
*
* @param key key whose mapping is to be removed from the map
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>null</tt> return can also indicate that the map
* previously associated <tt>null</tt> with <tt>key</tt>.)
*/
public V remove(Object key) {
Entry<K,V> e = removeEntryForKey(key);
return (e == null ? null : e.value);
} /**
* 删除并返回改HashMap中指定的key所关联的entry,如果hashMap不包含该key则返回null
* 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());//如果key== null ,则返回0,因为key==0的数据在table[0]中存储。
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--;//HashMap.size--;
//删除
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
//返回
return e;
}
prev = e;
e = next;
} return e;
} /**
* 为EntrySet定制的方法
* Special version of remove for EntrySet.
*/
final Entry<K,V> removeMapping(Object o) {
//类型不对肯定不在map中就不用继续查找直接返回。
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; //循环链表,找到target进行删除
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;
}
public void clear();清空map数据
/**
* 从map中移除所有的数据
* 调用返回后map将被清空
* Removes all of the mappings from this map.
* The map will be empty after this call returns.
*/
public void clear() {
//这里也++啊!!!到底干嘛用的??????
modCount++;
Entry[] tab = table;
//清除引用
for (int i = 0; i < tab.length; i++)
tab[i] = null;
//size置0
size = 0;
}
public boolean containsValue(Object value);
/**
* 如果map中包含一个或者多个value则返回true
* Returns <tt>true</tt> if this map maps one or more keys to the
* specified value.
*
* @param value value whose presence in this map is to be tested
* @return <tt>true</tt> if this map maps one or more keys to the
* specified value
*/
public boolean containsValue(Object value) {
if (value == null)
return containsNullValue(); Entry[] tab = table;
//循环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;
}
private boolean containsNullValue();
/**
* 特例 判断是够包括 value == null的 value
* 为什么不重用 public boolean containsValue(Object value) 而不进行value== null判断呢??????
* Special-case code for containsValue with null argument
*/
//重复 不讲
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;
}
public Object clone();
/**
* shallow copy 克隆==浅拷贝??? 标识:XX06
* Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and
* values themselves are not cloned.
*
* @return a shallow copy of this map
*/
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;
}
这个方法比较特殊: void addEntry(int hash, K key, V value, int bucketIndex) ;
/**
* 把给定的key、value、和hashCode组成的entry放入容器,如果被appropriate则需要去修改table的size
* 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.
*子类可以通过覆写这个方法去修改put方法。
* Subclass overrides this to alter the behavior of put method.
*/
void addEntry(int hash, K key, V value, int bucketIndex) {
//取出table[bucketIndex]位置的链表节点e
Entry<K,V> e = table[bucketIndex];
// 创建新的entry放在table[bucketIndex]
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
//如果需要调整大小则进行resize()操作
if (size++ >= threshold)
//按照两倍进行扩容,依旧符合容量为偶数的标准
resize(2 * table.length);
}
迭代器的实现: private abstract class HashIterator<E> implements Iterator<E>
HashMap中有三个XXXset,所以有三个XXXiterator+HashIterator,
aaarticlea/png;base64,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" alt="" />
这里对其他三个不在讲解,实现方式一致,如果有兴趣可以去找一下java迭代器的使用。
//HashMap 通过Iterator 迭代器进行迭代输出,通过此对象进行实现迭代输出
private abstract class HashIterator<E> implements Iterator<E> {
Entry<K,V> next; // next entry to return 下一个将要输出的节点
int expectedModCount; // For fast-fail 用来表示map在进行迭代期间是否有其他线程对map进行操作
int index; // current slot 当前对象(entry)在table中的位置
Entry<K,V> current; // current entry 当前进行输出的节点 HashIterator() {
//初始化的时候设置此两值相同,在进行next的时候进行判断,如果相同则进行操作,不相同(说明同时有其他线程对map数据进行修改。不允许)则抛出异常。
expectedModCount = modCount;
if (size > 0) { // advance to first entry
Entry[] t = table;
//找到下一个不为null的链表的头结点
while (index < t.length && (next = t[index++]) == null)
;
}
} public final boolean hasNext() {
return next != null;
} //从table中找到下一个entry链表的头节点,此方法只是更新current和next
final Entry<K,V> nextEntry() {
//在迭代期间如果有其他线程对map进行数据操作操作则抛出异常。
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Entry<K,V> e = next;
if (e == null)
throw new NoSuchElementException(); //找到下一个不为null的节点
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;//entry 置空
//从Map中删除此节点
HashMap.this.removeEntryForKey(k);
//重新更新操作标识
expectedModCount = modCount;
} }
--------over------
源码解读—HashMap的更多相关文章
- jdk1.8.0_45源码解读——HashMap的实现
jdk1.8.0_45源码解读——HashMap的实现 一.HashMap概述 HashMap是基于哈希表的Map接口实现的,此实现提供所有可选的映射操作.存储的是<key,value>对 ...
- 源码解读—HashTable
在上一篇学习过HashMap(源码解读—HashMap)之后对hashTable也产生了兴趣,随即便把hashTable的源码看了一下.和hashMap类似,但是也有不同之处. public clas ...
- HashTable、HashMap与ConCurrentHashMap源码解读
HashMap 的数据结构 hashMap 初始的数据结构如下图所示,内部维护一个数组,然后数组上维护一个单链表,有个形象的比喻就是想挂钩一样,数组脚标一样的,一个一个的节点往下挂. 我们可以 ...
- 线程本地变量ThreadLocal源码解读
一.ThreadLocal基础知识 原始线程现状: 按照传统经验,如果某个对象是非线程安全的,在多线程环境下,对对象的访问必须采用synchronized进行线程同步.但是Spring中的各种模板 ...
- php-msf 源码解读【转】
php-msf: https://github.com/pinguo/php-msf 百度脑图 - php-msf 源码解读: http://naotu.baidu.com/file/cc7b5a49 ...
- ThreadLocal源码解读
1. 背景 ThreadLocal源码解读,网上面早已经泛滥了,大多比较浅,甚至有的连基本原理都说的很有问题,包括百度搜索出来的第一篇高访问量博文,说ThreadLocal内部有个map,键为线程对象 ...
- Spring源码-循环依赖源码解读
Spring源码-循环依赖源码解读 笔者最近无论是看书还是从网上找资料,都没发现对Spring源码是怎么解决循环依赖这一问题的详解,大家都是解释了Spring解决循环依赖的想法(有的解释也不准确,在& ...
- jdk1.8.0_45源码解读——HashSet的实现
jdk1.8.0_45源码解读——HashSet的实现 一.HashSet概述 HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持.主要具有以下的特点: 不保证set的迭代顺 ...
- jdk1.8.0_45源码解读——Set接口和AbstractSet抽象类的实现
jdk1.8.0_45源码解读——Set接口和AbstractSet抽象类的实现 一. Set架构 如上图: (01) Set 是继承于Collection的接口.它是一个不允许有重复元素的集合.(0 ...
随机推荐
- maven学习笔记(定制普通Java一个项目)
创建一个新项目: mvn archetype:generate -DgroupId=cn.net.comsys.ut4.simpleweather -DartifactId=simple-weathe ...
- Presto集群安装配置
Presto是一个运行在多台服务器上的分布式系统. 完整安装包括一个coordinator(调度节点)和多个worker. 由客户端提交查询,从Presto命令行CLI提交到coordinator. ...
- Hive(四):c#通过odbc访问hive
hive odbc 驱动配置成功后,通过c#访问就变得比较简单了,分为查询与更新操作,直接附上测试代码.在此过程中需要注意c#工程编译的目标平台 读写访问代码示例: public class Hive ...
- oc-数据模型的建立
@{@"name":@"David Beckham",@"age":@38,@"gender":@"男&quo ...
- js中的script标签
在页面中用script标签引入javascript文件(<script type="text/javascript" src="js文件地址">&l ...
- (转)textarea去掉右侧滚动条,去掉右下角拖拽
本文转载自:http://blog.csdn.net/cctv_end/article/details/7946188 代码: <TEXTAREA style= "overflo ...
- php 自带函数
memory_get_usage()://查看当前内存使用情况单位 bytes str_repeat("liuhui", 2);//字符串重复指定次数,liuhui重复2次
- PHP替换,只替换匹配到的第一个
function str_replace_limit($search, $replace, $subject, $limit=-1) { if (is_array($search)) { foreac ...
- Django数据库操作
刚学到Django的数据库操作,把它记录下来,方便以后查看: 在Django中定义数据库表,并使用Django提供的方法来对数据库进行操作(增.删.改.查) 1.定义3个数据库表: class Gro ...
- 删除SQL server 实例
在网上找到下面几种方法,本人使用的是第一种,很实用. 1.删除 SQL Server 的特定实例若要删除 SQL Server 的某个特定实例,请按照以下步骤操作: 找到并删除%drive%:\\Pr ...