Источник Java 8 HashMap.get()
:
1. public V get(Object key) {
2. Node<K,V> e;
3. return (e = getNode(hash(key), key)) == null ? null : e.value;
4. }
5.
6. /**
7. * Implements Map.get and related methods
8. *
9. * @param hash hash for key
10. * @param key the key
11. * @return the node, or null if none
12. */
13. final Node<K,V> getNode(int hash, Object key) {
14. Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
15. if ((tab = table) != null && (n = tab.length) > 0 &&
16. (first = tab[(n - 1) & hash]) != null) {
17. if (first.hash == hash && // always check first node
18. ((k = first.key) == key || (key != null && key.equals(k))))
19. return first;
20. if ((e = first.next) != null) {
21. if (first instanceof TreeNode)
22. return ((TreeNode<K,V>)first).getTreeNode(hash, key);
23. do {
24. if (e.hash == hash &&
25. ((k = e.key) == key || (key != null && key.equals(k))))
26. return e;
27. } while ((e = e.next) != null);
28. }
29. }
30. return null;
31. }
(a) Зачем всегда явно проверять первый узел в строке 17?
(b) Что делает tab[(n - 1) & hash]
в строке 16?
(c) Может мне понадобится понимание hash()
источник также:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
Java 8 HashMap.put()
источник :
1. public V put(K key, V value) {
2. return putVal(hash(key), key, value, false, true);
3. }
4.
5. final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
6. boolean evict) {
7. Node<K,V>[] tab; Node<K,V> p; int n, i;
8. if ((tab = table) == null || (n = tab.length) == 0)
9. n = (tab = resize()).length;
10. if ((p = tab[i = (n - 1) & hash]) == null)
11. tab[i] = newNode(hash, key, value, null);
12. else {
13. Node<K,V> e; K k;
14. if (p.hash == h ash &&
15. ((k = p.key) == key || (key != null && key.equals(k))))
16. e = p;
17. else if (p instanceof TreeNode)
18. e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
19. else {
20. for (int binCount = 0; ; ++binCount) {
21. if ((e = p.next) == null) {
22. p.next = newNode(hash, key, value, null);
23. if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
24. treeifyBin(tab, hash);
25. break;
26. }
27. if (e.hash == hash &&
28. ((k = e.key) == key || (key != null && key.equals(k))))
29. break;
30. p = e;
31. }
32. }
33. if (e != null) { // existing mapping for key
34. V oldValue = e.value;
35. if (!onlyIfAbsent || oldValue == null)
36. e.value = value;
37. afterNodeAccess(e);
38. return oldValue;
39. }
40. }
41. ++modCount;
42. if (++size > threshold)
43. resize();
44. afterNodeInsertion(evict);
45. return null;
46. }
(a) Я понимаю putTreeVal()
в строке 18 вставляет ключ- значение в сбалансированном дереве. Но я не нахожу logi c для помещения значения ключа в связанный список, как в строке 27 getNode()
, что включает в себя обход до конца связанного списка.
(b) Что делает if
в строках 10 и 14 делать?
(c) Я также не получаю полный лог c полностью ясно. Можете ли вы предоставить комментарии для каждой важной строки. На самом деле я хочу знать, есть ли какая-либо репозитория документации / исходного кода с комментариями к каждой важной строке, объясняющая, что он пытается понять, потому что в этом классе есть много сложных сложных методов, таких как resize()
, tableSizeFor(int)