ArrayList与Vector
ArrayList
ArrayList 是 Java 集合框架中最常用的类之一,它实现了 List 接口,基于动态数组的数据结构。ArrayList 提供了快速的随机访问能力,并且支持动态扩容,适合存储和操作大量数据
特点
- 基于动态数组
- ArrayList 内部使用数组来存储元素。
- 数组的大小可以动态调整,当元素数量超过当前数组容量时,会自动扩容
- 有序且允许重复
- 元素按照插入顺序存储。
- 允许存储重复的元素
- 允许 null 元素
- ArrayList 可以存储 null 值,且可以存储多个 null
- 非线程安全,ArrayList 不是线程安全的。
常用方法
ArrayList 实现了 List 接口,因此支持 List 的所有方法。
ArrayList底层实现
-
transient Object[] elementData
- 这是一个 Object 类型的数组,用于存储 ArrayList 中的元素
- 数组的长度(elementData.length)表示当前 ArrayList 的容量(Capacity),即最多可以存储多少个元素。
- 数组的实际使用长度(即 ArrayList 中存储的元素数量)由 size 字段表示
- 在 ArrayList 中,存储数据的数组 elementData 被声明为 transient,但这并不意味着数据完全不参与序列化。相反,ArrayList 通过自定义序列化逻辑优化了存储效率
- 反序列化时,ArrayList 会根据写入的实际元素数量重新分配一个容量精确匹配的数组,避免冗余空间占用
-
int size
- 表示 ArrayList 中实际存储的元素数量。
- size 的值总是小于或等于 elementData.length
构造方法
-
无参构造方法
-
默认构造方法会将 elementData 初始化为一个空数组 DEFAULTCAPACITY_EMPTY_ELEMENTDATA。
-
在第一次添加元素时,elementData 会扩容到默认容量(10)
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {} public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
-
-
指定初始容量的构造方法
-
如果指定了初始容量(initialCapacity),elementData 会被初始化为一个指定长度的数组。
-
如果初始容量为 0,elementData 会被初始化为一个空数组 EMPTY_ELEMENTDATA
private static final Object[] EMPTY_ELEMENTDATA = {} public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); } }
-
-
基于集合的构造方法
-
该构造方法会将指定集合 c 中的元素复制到 elementData 数组中。
-
如果集合 c 为空,elementData 会被初始化为一个空数组 EMPTY_ELEMENTDATA
public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { this.elementData = EMPTY_ELEMENTDATA; } }
-
ArrayList的扩容机制
- ArrayList 的容量是动态调整的。当元素数量超过当前数组容量时,ArrayList 会自动扩容
- 新容量通常是旧容量的 1.5 倍
- 如果所需容量超过 MAX_ARRAY_SIZE,则返回 Integer.MAX_VALUE
- 扩容需要创建新数组并复制数据,可以通过指定初始容量来减少扩容次数,避免不必要的扩容操作
-
扩容的触发条件
- 扩容通常在添加元素时触发,例如在 add() 方法中
- ensureCapacityInternal(size + 1) 会检查当前容量是否足够,如果不足则调用 grow() 方法扩容。
- 当添加元素时,如果当前容量不足(即 size + 1 > elementData.length),ArrayList 会自动扩容
public boolean add(E e) { ensureCapacityInternal(size + 1); // 确保容量足够 elementData[size++] = e; return true; } -
扩容逻辑主要集中在 grow() 方法中
- grow(int minCapacity) 方法
private void grow(int minCapacity) { //minCapacity:所需的最小容量(通常是 size + 1) int oldCapacity = elementData.length; // 当前容量 int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量为旧容量的 1.5 倍 if (newCapacity - minCapacity < 0) // 如果新容量仍然不足 newCapacity = minCapacity; // 直接使用所需的最小容量 if (newCapacity - MAX_ARRAY_SIZE > 0) // 如果新容量超过最大限制 newCapacity = hugeCapacity(minCapacity); // 处理超大容量 elementData = Arrays.copyOf(elementData, newCapacity); // 创建新数组并复制数据 }- hugeCapacity(int minCapacity) 方法
private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // 如果所需容量溢出(超过 Integer.MAX_VALUE) throw new OutOfMemoryError(); // 抛出内存溢出异常 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } //如果所需容量超过了 MAX_ARRAY_SIZE,则返回 Integer.MAX_VALUE。 //如果所需容量溢出(即 minCapacity < 0),则抛出 OutOfMemoryError
Vector
- Vector 与 ArrayList 类似,但它是 线程安全 的
- Vector 实现了 List 接口,因此支持 List 的所有方法。
- 默认10,Vector 默认扩容为 2 倍

浙公网安备 33010602011771号