分析HashMap 的 JDK 源碼
緣由:今天好友拿著下面的代碼,問(wèn)我為什么 Map.Entry 這個(gè)接口沒(méi)有實(shí)現(xiàn) getKey() 和 getValue() 方法,卻可以使用,由此,開(kāi)啟了一番查閱 JDK 源碼的旅途….
Map map = new HashMap(); map.put(1, "張三"); map.put(2, "李四"); map.put(3, "王五"); map.put(4, "趙六"); map.put(5, "錢(qián)七"); Set set = map.entrySet(); for (Object object : set) { Map.Entry entry = (Map.Entry) object; System.out.println(entry.getKey() + "-->" + entry.getValue()); }
1.首先,我們看 map 對(duì)象,這個(gè) map 對(duì)象是 HashMap 的一個(gè)實(shí)例,然后下面的 Set set = map.entrySet(); 可以知道這其實(shí)用的 HashMap 實(shí)現(xiàn)的 entrySet() 方法,然后我們可以查看 HashMap 里 entrySet() 的源碼
從源碼可以看出,這里的返回了一個(gè) EntrySet
對(duì)象,但是需要注意的是這個(gè) EntrySet
是 HashMap
里的一個(gè)內(nèi)部類(lè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(); } } }
從這里我們是可以看出,這個(gè) EntrySet
其實(shí)是封裝的一個(gè) Node
類(lèi)的實(shí)體。也就是說(shuō)我們的 set
其實(shí)就是這個(gè) Node
對(duì)象。
2.現(xiàn)在我們來(lái)說(shuō)說(shuō)這個(gè) Node 對(duì)象,Node 對(duì)象也是 HashMap 里的一個(gè)內(nèi)部類(lè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; } }
可以看出來(lái),這個(gè) Node
對(duì)象是 Map.Entry<K,V>
的實(shí)現(xiàn)類(lèi),我們可以看到這個(gè) Node
對(duì)象實(shí)現(xiàn)了 getKey()
和 getValue()
的方法,所以后面調(diào)用的 entry.getKey()
以及 entry.getValue()
方法其實(shí)都是調(diào)用的 Node 對(duì)象里的getKey()
和 getValue()
方法,這里就是 Java 的多態(tài)的一種表現(xiàn)。
3.至此,打完收槍?zhuān)?/strong>
以上就是分析HashMap 的 JDK 源碼的詳細(xì)內(nèi)容,更多關(guān)于HashMap 的 JDK 源碼的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java 詳細(xì)講解分治算法如何實(shí)現(xiàn)歸并排序
分治算法的基本思想是將一個(gè)規(guī)模為N的問(wèn)題分解為K個(gè)規(guī)模較小的子問(wèn)題,這些子問(wèn)題相互獨(dú)立且與原問(wèn)題性質(zhì)相同。求出子問(wèn)題的解,就可得到原問(wèn)題的解,本篇文章我們就用分治算法來(lái)實(shí)現(xiàn)歸并排序2022-04-04ReentrantReadWriteLock不能鎖升級(jí)的原因總結(jié)
今天給大家?guī)?lái)的是關(guān)于Java并發(fā)的相關(guān)知識(shí),文章圍繞著為什么ReentrantReadWriteLock不能鎖升級(jí)展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06RxJava2 Scheduler使用實(shí)例深入解析
這篇文章主要為大家介紹了RxJava2 Scheduler使用實(shí)例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Java數(shù)據(jù)結(jié)構(gòu)與算法之棧(Stack)實(shí)現(xiàn)詳解
這篇文章主要為大家詳細(xì)介紹了Java數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)筆記第二篇,Java數(shù)據(jù)結(jié)構(gòu)與算法之棧Stack實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09Mybatis-plus:${ew.sqlselect}用法說(shuō)明
這篇文章主要介紹了Mybatis-plus:${ew.sqlselect}用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06MyBatis-Plus 如何實(shí)現(xiàn)連表查詢(xún)的示例代碼
這篇文章主要介紹了MyBatis-Plus 如何實(shí)現(xiàn)連表查詢(xún)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08