Java集合类

1.HashMap

 

 

源码分析:

put值操作: 
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
      //初始化定义Node[],Node,初始化Node[]大小。 Node<K,V>[] tab; Node<K,V> p; int n, i;
      //首次初始化,table=null if ((tab = table) == null || (n = tab.length) == 0)
      //调用resize()进行初始化扩容,默认大小为16 n = (tab = resize()).length;
       //判断上一步初始化所得Node(实质为数组)是否为空。首次创建为空,会执行此步骤,创建新的Node节点并保存数据<hash(key),key,value,next<指针>> if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null);
        //若不是首次创建,执行此步骤。 else { Node<K,V> e; K k;
        //hash(key),key 都相同且不为空,直接赋值 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p;
         //红黑树赋值 else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else {
        //遍历链表,获取next为空的Node并赋值 for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                  //此处并不一定会转化为红黑树 treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } }
        //如果e不为空,即找到了一个去存储Key-value的Node if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }
get值操作
final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) {
          //true,检测是否是TreeNode if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); do {
            //false,判断下一个节点是否是要查找的对象 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }

HashMap的扩容机制

 1 final Node<K,V>[] resize() {
 2         Node<K,V>[] oldTab = table;
 3         int oldCap = (oldTab == null) ? 0 : oldTab.length;
 4         int oldThr = threshold;
 5         int newCap, newThr = 0;
       //容量大于0,说明不是第一次初始化
6 if (oldCap > 0) {
          //超过最大容量:2^30
7 if (oldCap >= MAXIMUM_CAPACITY) {
           //临界值等于Integer类型的最大值 0x7fffffff=2^31-1
8 threshold = Integer.MAX_VALUE; 9 return oldTab; 10 }
          //当前容量在默认值和最大值的一半之间
11 else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && 12 oldCap >= DEFAULT_INITIAL_CAPACITY)
            //新临界值为当前临界值的两倍
13 newThr = oldThr << 1; // double threshold 14 }
       //当前容量为0,但是当前临界值不为0,让新的容量等于当前临界值
15 else if (oldThr > 0) // initial capacity was placed in threshold 16 newCap = oldThr;
      //当前容量和临界值都为0,让新的容量为默认值,临界值=初始容量*默认加载因子
17 else { // zero initial threshold signifies using defaults 18 newCap = DEFAULT_INITIAL_CAPACITY; 19 newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); 20 }
      //如果新的临界值为0
21 if (newThr == 0) { 22 float ft = (float)newCap * loadFactor; 23 newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? 24 (int)ft : Integer.MAX_VALUE); 25 }
      //临界值赋值
26 threshold = newThr; 27 @SuppressWarnings({"rawtypes","unchecked"})
          //扩容table
28 Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; 29 table = newTab; 30 if (oldTab != null) { 31 for (int j = 0; j < oldCap; ++j) { 32 Node<K,V> e; 33 if ((e = oldTab[j]) != null) { 34 oldTab[j] = null; 35 if (e.next == null) 36 newTab[e.hash & (newCap - 1)] = e;
              //节点为红黑树,进行切割操作
37 else if (e instanceof TreeNode) 38 ((TreeNode<K,V>)e).split(this, newTab, j, oldCap); 39 else {

               //链表的下一个节点还有值,但节点位置又没有超过 

              //就是扩容后仍然在原地的元素链表 

              //就是扩容后下标为 原位置+原容量 的元素链表,从而不需要重新计算hash。
40                         Node<K,V> loHead = null, loTail = null;
41                         Node<K,V> hiHead = null, hiTail = null;
42                         Node<K,V> next;
                //循环链表直到链表末再无节点
43 do { 44 next = e.next;
                  //e.hash&oldCap == 0 判断元素位置是否还在原位置
45 if ((e.hash & oldCap) == 0) { 46 if (loTail == null) 47 loHead = e; 48 else 49 loTail.next = e; 50 loTail = e; 51 } 52 else { 53 if (hiTail == null) 54 hiHead = e; 55 else 56 hiTail.next = e; 57 hiTail = e; 58 } 59 } while ((e = next) != null);
                //循环链表结束,通过判断loTail是否为空来拷贝整个链表到扩容后table
60 if (loTail != null) { 61 loTail.next = null; 62 newTab[j] = loHead; 63 } 64 if (hiTail != null) { 65 hiTail.next = null; 66 newTab[j + oldCap] = hiHead; 67 } 68 } 69 } 70 } 71 } 72 return newTab; 73 }

 

 

解决hash冲突的方法以及HashMap解决hash冲突的方法

 

posted @ 2019-08-21 21:53  落叶随风起  阅读(99)  评论(0编辑  收藏  举报