ArrayList的扩容机制

一、初始化机制
  1. JDK 1.7
    1. 饿汉式初始化:使用无参构造方法 new ArrayList() 时,直接创建长度为 10 的 Object[] elementData 数组,无论是否立即添加元素
    2. 缺点:若未立即使用集合,会浪费内存空间。
  2. JDK 1.8
    1. 懒汉式初始化:无参构造方法 new ArrayList() 时,初始化一个空数组 {}DEFAULTCAPACITY_EMPTY_ELEMENTDATA),容量为 0。第一次调用 add() 方法时,才会创建长度为 10 的数组
    2. 优点:延迟数组创建,节省内存资源,尤其适用于未立即使用的集合场景
二、构造方法行为
  1. JDK 1.7
    1. 所有构造方法(包括无参构造)均直接初始化数组。例如,new ArrayList() 强制分配容量为 10,new ArrayList(0) 则创建空数组
  2. JDK 1.8
    1. 无参构造方法不再预分配空间,仅当显式指定初始容量(如 new ArrayList(10))时才会直接初始化数组
    2. 若传入集合参数(如 new ArrayList<>(existingList)),则直接复制集合元素的数组,避免冗余扩容
三、扩容机制
  1. 扩容规则
    1. 共同点:当数组容量不足时,JDK 1.7 和 1.8 均按 1.5 倍(即 oldCapacity + (oldCapacity >> 1))扩容,并将旧数组元素复制到新数组
    2. 触发条件:添加元素时,若当前容量不足(size + 1 > elementData.length),触发扩容
  2. 性能优化
    1. JDK 1.8 在首次调用 add() 时才会初始化数组,避免了无参构造场景下的无效内存占用
    2. 建议在已知数据规模时使用带参构造方法(如 new ArrayList(100)),减少扩容次数以提升性能
四、内存与性能对比

<!--br {mso-data-placement:same-cell;}--> td {white-space:nowrap;border:0.5pt solid #dee0e3;font-size:10pt;font-style:normal;font-weight:normal;vertical-align:middle;word-break:normal;word-wrap:normal;}

维度

JDK 1.7

JDK 1.8

初始化策略

预分配内存(可能浪费资源)

按需分配内存(节省内存)

扩容频率

可能因预分配容量较高而减少扩容次数

首次添加元素必扩容,后续扩容频率相同

适用场景

需立即添加大量元素的场景

内存敏感型场景或延迟初始化需求

五、总结与建议
  1. JDK 1.7:适用于需要快速响应添加操作的场景,但可能因预分配内存导致资源浪费。
  2. JDK 1.8:通过懒加载优化内存使用,适合不确定初始数据量的场景,但首次添加元素时会有轻微性能损耗
  3. 最佳实践
    1. 预分配容量:若已知数据规模,优先使用带参构造方法指定初始容量。
    2. 避免频繁扩容:批量添加数据时,提前调用 ensureCapacity() 预扩容