分析HashMap 的 JDK 源碼
緣由:今天好友拿著下面的代碼,問我為什么 Map.Entry 這個接口沒有實現(xiàn) getKey() 和 getValue() 方法,卻可以使用,由此,開啟了一番查閱 JDK 源碼的旅途….
Map map = new HashMap();
map.put(1, "張三");
map.put(2, "李四");
map.put(3, "王五");
map.put(4, "趙六");
map.put(5, "錢七");
Set set = map.entrySet();
for (Object object : set) {
Map.Entry entry = (Map.Entry) object;
System.out.println(entry.getKey() + "-->" + entry.getValue());
}
1.首先,我們看 map 對象,這個 map 對象是 HashMap 的一個實例,然后下面的 Set set = map.entrySet(); 可以知道這其實用的 HashMap 實現(xiàn)的 entrySet() 方法,然后我們可以查看 HashMap 里 entrySet() 的源碼

從源碼可以看出,這里的返回了一個 EntrySet 對象,但是需要注意的是這個 EntrySet 是 HashMap 里的一個內(nèi)部類,源碼如下:
final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public final int size() {
return size;
}
public final void clear() {
HashMap.this.clear();
}
public final Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator();
}
public final boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Node<K,V> candidate = getNode(hash(key), key);
return candidate != null && candidate.equals(e);
}
public final boolean remove(Object o) {
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Object value = e.getValue();
return removeNode(hash(key), key, value, true, true) != null;
}
return false;
}
public final Spliterator<Map.Entry<K,V>> spliterator() {
return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);
}
public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next)
action.accept(e);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
}
從這里我們是可以看出,這個 EntrySet 其實是封裝的一個 Node 類的實體。也就是說我們的 set 其實就是這個 Node 對象。
2.現(xiàn)在我們來說說這個 Node 對象,Node 對象也是 HashMap 里的一個內(nèi)部類,源碼如下:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() {
return key;
}
public final V getValue() {
return value;
}
public final String toString() {
return key + "=" + value;
}
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
可以看出來,這個 Node 對象是 Map.Entry<K,V> 的實現(xiàn)類,我們可以看到這個 Node 對象實現(xiàn)了 getKey() 和 getValue() 的方法,所以后面調(diào)用的 entry.getKey() 以及 entry.getValue() 方法其實都是調(diào)用的 Node 對象里的getKey() 和 getValue() 方法,這里就是 Java 的多態(tài)的一種表現(xiàn)。
3.至此,打完收槍!
以上就是分析HashMap 的 JDK 源碼的詳細(xì)內(nèi)容,更多關(guān)于HashMap 的 JDK 源碼的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java 詳細(xì)講解分治算法如何實現(xiàn)歸并排序
分治算法的基本思想是將一個規(guī)模為N的問題分解為K個規(guī)模較小的子問題,這些子問題相互獨(dú)立且與原問題性質(zhì)相同。求出子問題的解,就可得到原問題的解,本篇文章我們就用分治算法來實現(xiàn)歸并排序2022-04-04
ReentrantReadWriteLock不能鎖升級的原因總結(jié)
今天給大家?guī)淼氖顷P(guān)于Java并發(fā)的相關(guān)知識,文章圍繞著為什么ReentrantReadWriteLock不能鎖升級展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06
Java數(shù)據(jù)結(jié)構(gòu)與算法之棧(Stack)實現(xiàn)詳解
這篇文章主要為大家詳細(xì)介紹了Java數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)筆記第二篇,Java數(shù)據(jù)結(jié)構(gòu)與算法之棧Stack實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09
Mybatis-plus:${ew.sqlselect}用法說明
這篇文章主要介紹了Mybatis-plus:${ew.sqlselect}用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
MyBatis-Plus 如何實現(xiàn)連表查詢的示例代碼
這篇文章主要介紹了MyBatis-Plus 如何實現(xiàn)連表查詢的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08

