这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
List 是 Java 中常用集合之一,其重点实现类包括 ArrayList、LinkedList 和 Vector。
ArrayList
ArrayList 是通过数组实现的,可以认为它是一个可改变容量的数组。其扩容增量为 0.5 倍。
- 为什么说 ArrayList 的底层是数组?
由其构造方法可以发现,当我们创建一个 ArrayList 对象时,其实就是创建了一个 Object 类型的数组。
public ArrayList() {
// DEFAULTCAPACITY_EMPTY_ELEMENTDATA 为 Object 类型的空数组
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
- 为什么 ArrayList 的容量可变,扩容增量又是多少呢?
由其扩容方法我们可以发现,ArrayList 每次扩容都为原数组容量的 1 / 2,然后将原数组的数据拷贝到新数组。因此,当我们创建数据时,尽量指定 ArrayList 的初始容量大小,以减少数组拷贝次数,提升数组创建效率。
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
// 扩容增量为原来的 1 / 2
int newCapacity = oldCapacity + (oldCapacity >> 1);
...
elementData = Arrays.copyOf(elementData, newCapacity);
}
LinkedList
LinkedList 是通过双向链表实现的,因此也就没有扩容的概念。
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
...
}
Vector
Vector 也是通过数组实现的,不过它的很多方法都用了 synchronized 修饰,因此是线程安全的。Vector 缺省情况下的增量为原数组容量的 1 倍。
当然 Vector 因为性能问题,已不再建议使用,为了保证线程安全,可以使用 synchronizedList。
ArrayList 和 LinkedList 的区别
ArrayList 与 LinkedList 之间的区别,其实也就是数组与链表之间的区别。
数组查询和赋值比较快,因为可以通过数组下标访问指定位置的数据。
链表增加和删除比较快,因为可以通过修改链表的指针进行数据的增加和删除。
ArrayList 和 Vector 的区别
ArrayList 与 Vector 之间的区别,主要是 ArrayList 是线程不安全的,而 Vector 是线程安全的。
总结
| 扩容增量 | 线程安全 | 应用场景 | |
|---|---|---|---|
| ArrayList | 0.5 倍 | 否 | 查找数据时间多 |
| LinkedList | - | 否 | 增删数据时间多 |
| Vector | 1 倍 | 是 | 多线程 |