标签:
hashMap底层有一个数组存放所有的数据:
Node<K,V>[] tab;//链表数组
hashMap最重要的两个方法:
put,根据hash值找到位置,如果没有发生冲突,键值对放入数组中,如果发生冲突,需要解决冲突,如果当前已经存在key的映射关系,新value会替换以前的,如果不存在,会把当前键值对放在找到的索引位置链表末端;
1 /** 2 * Implements Map.put and related methods 3 * 4 * @param hash 根据key计算出来的hash值 5 * @param key the key 6 * @param value the value to put 7 * @param onlyIfAbsent if true, 不改变已经存在的值 8 * @param evict if false,表处在创建模式 9 * @return 之前的值,如果不存在返回null 10 */ 11 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, 12 boolean evict) { 13 Node<K,V>[] tab; //存放底层数组 14 15 Node<K,V> p; //存放传进来的键值对 16 17 int n, i; 18 19 //如果数组为空,重新生成新的数组 20 if ((tab = table) == null || (n = tab.length) == 0) 21 n = (tab = resize()).length; 22 23 //如果当前key的hash值没有发生冲突,把它放在数组的最后一个,生成一个新的结点 24 if ((p = tab[i = (n - 1) & hash]) == null) 25 tab[i] = newNode(hash, key, value, null); 26 else { 27 Node<K,V> e; 28 29 K k; 30 31 //如果hash值相同并且key相同 32 if (p.hash == hash && 33 ((k = p.key) == key || (key != null && key.equals(k)))) 34 e = p; 35 else if (p instanceof TreeNode) 36 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); 37 else { 38 39 //hash值相同,key不同,不是TreeNode,需要解决冲突,找到一个位置放置,一般是放在当前结点的链表尾部 40 for (int binCount = 0; ; ++binCount) { 41 42 //当找到链表的尾部,生成新的结点存放键值对 43 if ((e = p.next) == null) { 44 p.next = newNode(hash, key, value, null); 45 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st 46 treeifyBin(tab, hash); 47 break; 48 } 49 50 //如果键和hash都相同,说明已经存在映射关系 51 if (e.hash == hash && 52 ((k = e.key) == key || (key != null && key.equals(k)))) 53 break; 54 p = e; 55 } 56 } 57 58 //已经存在当前key的映射,需要替换之前的值, 59 if (e != null) { // existing mapping for key 60 V oldValue = e.value; 61 if (!onlyIfAbsent || oldValue == null) 62 e.value = value; 63 afterNodeAccess(e); 64 return oldValue; 65 } 66 } 67 ++modCount; 68 if (++size > threshold) 69 resize(); 70 afterNodeInsertion(evict); 71 return null; 72 }
标签:
原文地址:http://www.cnblogs.com/zhhx/p/4933433.html