hashmap:
 当HashMap中的元素越来越多的时候,碰撞的几率也就越来越高(因为数组的长度是固定的),所以为了提高查询的效率,就要对HashMap的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,所以这是一个通用的操作,很多人对它的性能表示过怀疑,不过想想我们的“均摊”原理,就释然了,而在hashmap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize。
  那么HashMap什么时候进行扩容呢?当hashmap中的元素个数超过数组大小*loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,也就是说,默认情况下,数组大小为16,那么当hashmap中元素个数超过16*0.75=12的时候,就把数组的大小扩展为2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知hashmap中元素的个数,那么预设元素的个数能够有效的提高hashmap的性能。比如说,我们有1000个元素new HashMap(1000), 但是理论上来讲new HashMap(1024)更合适,不过上面annegu已经说过,即使是1000,hashmap也自动会将其设置为1024。 但是new HashMap(1024)还不是更合适的,因为0.75*1000 < 1000, 也就是说为了让0.75 * size > 1000, 我们必须这样new HashMap(2048)才最合适,既考虑了&的问题,也避免了resize的问题。
        hashmap数组和链表的结合体
        1.8 第一次插入 先扩容后插入  后面 先插入后扩容
        扩容原理
final Node<K,V>[] resize() {
         Node<K,V>[] oldTab = table;  //原数组
         int oldCap = (oldTab == null) ? 0 : oldTab.length;  //非空判断/oldcap原容量大小
         int oldThr = threshold;    //扩容阈值  16*0.75
         int newCap, newThr = 0;    //定义新haspmap初始值
         if (oldCap > 0) {         //>0
             if (oldCap >= MAXIMUM_CAPACITY) {   //大于i nt MAXIMUM_CAPACITY = 1 << 30;
                 threshold = Integer.MAX_VALUE;  // MAX_VALUE = 0x7fffffff  ==2147483647;
                 return oldTab;
             }
             else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                      oldCap >= DEFAULT_INITIAL_CAPACITY)   //正常扩容条件:1.新cap=oldcap2倍,并且小于1 << 30
                 newThr = oldThr << 1; // double threshold   //新数组阈值扩大二倍
         }
         else if (oldThr > 0) // initial capacity was placed in threshold  //    初始容量设置为阈值
             newCap = oldThr;
         else {               // zero initial threshold signifies using defaults  // 零初始阈值表示使用默认值
             newCap = DEFAULT_INITIAL_CAPACITY;
             newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
         }
         if (newThr == 0) {    //==0情况 计算
             float ft = (float)newCap * loadFactor;
             newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                       (int)ft : Integer.MAX_VALUE);
         }
         threshold = newThr;
         @SuppressWarnings({"rawtypes","unchecked"})
             Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];       //定义新数组大小
         table = newTab;
         if (oldTab != null) {
             for (int j = 0; j < oldCap; ++j) {
                 Node<K,V> e;
                 if ((e = oldTab[j]) != null) {
                     oldTab[j] = null;
                     if (e.next == null)
                         newTab[e.hash & (newCap - 1)] = e; //(e.hash & newCap-1)取模取余 赋值
                     else if (e instanceof TreeNode)//红黑树操作
                         ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                     else { // preserve order //链表赋值复制
                         Node<K,V> loHead = null, loTail = null; //如果hash值经过((e.hash & oldCap) == 0))计算符合放入一个链表
                         Node<K,V> hiHead = null, hiTail = null;//如果hash计算经过((e.hash & oldCap) == 0))不符合一个新的链表
                         Node<K,V> next;
                         do {                    //遍历原来链表
                             next = e.next;    //记录下一节点信息 备用
                             if ((e.hash & oldCap) == 0) {  //e.hash & oldCap 与计算如( oldCap=8,hash是3,11,19,27时,(e.hash & oldCap)的结果是0,8,0,8,
                                                                 这样3,19组成新的链表
                                                               ,index为3;而11,27组成新的链表,新分配的index为3+8;)
                                 if (loTail == null)        //loTail为空,即新链表为空  即插入第一个节点
                                     loHead = e;            //取原链表第一个节点
                                 else                         向下插入
                                     loTail.next = e;        新链表尾部指向原连表e节点
                                 loTail = e;                 //尾结点重新赋值
                             }
                             else {                           //另一个链表,操作同上
                                 if (hiTail == null)
                                     hiHead = e;
                                 else
                                     hiTail.next = e;
                                 hiTail = e;
                             }
                         } while ((e = next) != null);
                         if (loTail != null) {  //存入新数组
                             loTail.next = null; //尾结点指向空,用于后续插入时候判断该节点是否为尾结点
                             newTab[j] = loHead;//原来数组下标一致
                         }
                         if (hiTail != null) {//存入新数组
                             hiTail.next = null;
                             newTab[j + oldCap] = hiHead;//原数组下标+原数组容量大小
                         }
                     }
                 }
             }
         }
         return newTab;
     }