ArrayList的扩容
(1 )调用add方法为ArrayList添加一个元素,然后数组中的元素个数加一(size+1)。
(2) 调用方法需要得到最小扩容量,这个最小扩容量就是数组需要的最小的数组长度。如果ArrayList是使用无参构造的,没有确定长度。最小扩容量就是10和刚才元素个数中的最大值。如果是初始化过的,这个最小扩容量就是就是元素个数。
(3)得到最小扩容量后判断是否需要扩容,如果最小扩容量大于数组长度,就是说明数组长度是不够的,需要扩容。新容量为原来数组长度的1.5倍。然后新容量和最小扩容量比较,如果小于的话,最小容量就是扩容的数组的长度,将原来的数组复制到新的数组。
举个例子,现在数组是空数组,添加一个元素后,最小扩容量是10,然后数组长度是1,然后我们需要将数组扩容到10。然后后面再次添加元素,已经被初始化过了,最小扩容量就是size+1,然后这个会小于数组长度10,不会扩容。
如果数组已经被初始化过了,现在数组长度是1-9,然后这个扩容就是原来容量的1.5倍。
HashMap的扩容
插入:(1)首先桶数组为空,进行扩容。(2)不为空,判断桶数组有没有这个键值对的引用(hash&(n-1)),这个位置没有键值对的存放,直接将这个节点放入(3)桶数组这个位置有存放的键值对:如果是在链表节点中有这个键值对,直接进行替换。如果是树形节点的话,则在树中进行查找插入。如果链表中没有,则放在链表最后一个,然后比较链表大小与树化阈值(8),如果大于的话,进行树化(进行树化,首先要判断数组大小与64-MIN_TREEIFY_CAPACITY,如果数组大小小于64,在树化之前,先进行扩容。当桶数组容量比较小的时候,键值对hash的碰撞率较高,此时会导致链表长度较长。高碰撞率是由于桶数组容量较小导致的,所以优先扩容还可以避免一些不必要的树化)。最后要判断这个桶数组中所有个数,大于负载容量的话,进行扩容
扩容:确定新的容量和阀值(根据是否已经初始化和构造参数的不同,确定的也不同。a.已经初始化,已知旧的容量和阀值,扩为原来的2倍。b.根据有参构造函数,容量为传入的参数的最近的2幂次方。c.根据无参构造函数,容量为默认的容量16,阀值也为原来的)根据计算出的newCap创建新的桶数组,桶数组table也是在这里初始化的。将键值对节点重新映射到新的桶数组里。如果节点是TreeNode类型,则需要拆分红黑树。如果是普通节点,则节点按原顺序进行分组。