ArrayList和LinkedList有什么区别?
重要内容
| 对比维度 | ArrayList | LinkedList |
|---|---|---|
| 底层数据结构 | 动态数组(连续内存空间) | 双向链表(非连续内存,通过节点指针连接) |
| 内存占用 | 内存连续,空间浪费在预留容量 | 每个节点额外存储前后指针,总占用更高 |
| 扩容机制 | 动态扩容(默认扩至 1.5 倍),需复制数组 | 无需扩容,按需分配新节点 |
| 线程安全性 | 非线程安全 | 非线程安全 |
| 随机访问效率 | O(1),通过索引直接定位元素 | O(n),需要遍历链表节点 |
| 头部增删效率 | O(n),需移动后续所有元素 | O(1),直接修改头节点指针 |
| 尾部增删效率 | O(1)(不扩容时) | O(1),直接修改尾节点指针 |
| 中间增删效率 | O(n),需移动后续元素 | O(n)(查找位置)+ O(1)(插入/删除),整体为 O(n) |
| 适用场景 | 高频随机访问、尾部操作 | 高频头部/尾部增删、队列/栈操作 |
扩展知识
ArrayList 底层结构
顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现
transient Object[] elementData; // transient 表示该属性不会被序列化
LinkedList 底层结构
双向链表或者双端队列,也就是说它既可以看作一个顺序容器,又可以看作一个队列 Queue ,同时又可以看作一个栈 Stack
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}