分析HashMap 的 JDK 原始碼
阿新 • • 發佈:2020-10-13
緣由:今天好友拿著下面的程式碼,問我為什麼 Map.Entry 這個介面沒有實現 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 實現的 entrySet() 方法,然後我們可以檢視 HashMap 裡 entrySet() 的原始碼
從原始碼可以看出,這裡的返回了一個 EntrySet
物件,但是需要注意的是這個 EntrySet
是 HashMap
裡的一個內部類,原始碼如下:
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<?,?>) 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,-1,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.現在我們來說說這個 Node 物件,Node 物件也是 HashMap 裡的一個內部類,原始碼如下:
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<?,?>)o; if (Objects.equals(key,e.getKey()) && Objects.equals(value,e.getValue())) return true; } return false; } }
可以看出來,這個 Node
物件是 Map.Entry<K,V>
的實現類,我們可以看到這個 Node
物件實現了 getKey()
和 getValue()
的方法,所以後面呼叫的 entry.getKey()
以及 entry.getValue()
方法其實都是呼叫的 Node 物件裡的getKey()
和 getValue()
方法,這裡就是 Java 的多型的一種表現。
3.至此,打完收槍!
以上就是分析HashMap 的 JDK 原始碼的詳細內容,更多關於HashMap 的 JDK 原始碼的資料請關注我們其它相關文章!