ArrayList、HashMap的动态扩容机制

ArrayList的动态扩容机制

ArrayList是采取懒加载的方式,ArrayList每次扩容都是通过Arrays.copyof(elementData,newCapacity)来实现的,即将当前数组元素拷贝到新数组中

  • 使用无参构造器创建的ArrayList初始容量为0,第一次调用add()/addAll()方法时才会初始化数组的容量,初始容量为10。
  • 对集合添加若干个元素时,如果当前集合的容量满足需求,不扩容;如果当前集合容量不满足需求,则扩大为原来的1.5倍;如果扩大1.5倍依然不满足需求,则扩大为满足需求的最小容量。
    举例: 当第一次添加元素时才会分配10个对象空间,当添加第11个元素的时候,会扩容1.5倍。如果一次添加多个元素,扩容后仍不能装下所有元素,则直接扩容至能装有所有元素的大小。
  • 推荐在new ArrayList()时指定大小,以节省扩容时损耗资源。初始化时自定义大小,其扩容机制也遵循1.5倍原则

ArrayList默认初始容量为10。当超过容量时,新容量扩容为原容量的1.5倍
举例:List list = new ArrayList(20)扩容了几次
答案:0次,当指定list容量时,直接创建相应大小的数组

HashMap的动态扩容机制

  • HashMap底层数据结构是 数组 + 链表 + 红黑树
  • HashMap何时扩容
    注意:阈值=map容量*负载因子
    (1)空参数的构造函数:实例化的HashMap默认内部数组是null,即没有实例化。第一次调用put方法时,则会开始第一次初始化扩容,长度为16。
    (2)有参构造函数:new HashMap(指定容量大小),会根据指定的正整数找到不小于指定容量的2的幂数,将这个数设置赋值给阈值(threshold)。第一次调用put方法时,会将阈值赋值给容量,然后让阈值=map容量与负载因子。
    (3)如果不是第一次扩容,则容量变为原来的2倍,阈值也变为原来的2倍。(容量和阈值都变为原来的2倍时,负载因子还是不变)
    (4)首次put时,先会触发扩容(算是初始化),然后存入数据,然后判断是否需要扩容;不是首次put,则不再初始化,直接存入数据,然后判断是否需要扩容;

HashMap的容量始终是2的指数
HashMap默认初始化大小为16,默认负载因子0.75,当元素个数超过阈值16*0.75=12时,进行扩容,每次扩容的容量都是之前容量的2倍,如果容量超出了Integer.MAX_VALUE,则容量设置为Integer.MAX_VALUE,且不再增长。当链表长度大于8(默认)时,就会把链表转换为红黑树6

举例:HashMap初始容量10000即new HashMap(10000),当往里put 10000个元素时,需要resize几次(初始化的那次不算)
答案:0次
解释:比10000大,且最接近的2的n次方数是16384,默认负载因子是0.75,16384*0.75 = 12288>10000,因而不需要扩容。

猜你喜欢

转载自blog.csdn.net/user2025/article/details/107896246