ArrayList简要
ArrayList
是实现了List
、RandomAccess
的顺序表,当容量不足时会自动扩容
特点:访问元素效率较高,操作元素效率低(每次add
remove
都会对整个表进行操作)
初始化
1 | // 可自定义初始化储存数据的数组长度 |
扩容机制
- 首次未设置数组长度时: 当执行
add*
添加数据会创建一个10
个长度的数组 - 再次扩容:当执行
add*
时会检查是否有足够空间,没有的话则增加当前长度的一半n/2
- 减容:当执行
remove*
时,先获取数组当前位置的数据,整个数组从当前位置向前移动补位,
置空数组后面的数据。(这里有个问题:减少容量时ArrayList里的数组长度没有减少,意味着数据长度只增不减)1
2
3
4
5
6
7
8
9
10
11
12// 每次执行 add* 时会进行数组长度校验,如果数组长度不够则会添加原长度的 n/2
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
线程安全问题
- 使用
CopyOnWriteArrayList
加锁的顺序列表 - 使用
Collections#synchronizedList
LinkedList简要
LinkedList
是实现了List``Deque
的队列双向链表,每个节点包含了数据,上一节点和下一节点的信息,容量是动态非连续的
特点:插入、删除较快,不需要移动数据,只移动节点信息就可以了
初始化 LinkedList()
扩容机制 动态随数据长度
Vector简要
与ArrayList相似,区别:线程安全,可自定义每次扩容大小
Stack简要
继承Vector,线程安全,实现栈的功能
常用线程安全的 List,Set
- CopyOnWriteArraySet 获取的
iterator()
不支持remove
set
add
操作 - CopyOnWriteArrayList 获取的
iterator()
不支持remove
set
add
操作 - SynchronizedRandomAccessList 通过
Collections#synchronizedList
获取 - SynchronizedList 通过
Collections#synchronizedList
获取
综合对比
- ArrayList的操作数据都是通过普通的数组实现,随机访问和修改元素比较快,但插入/删除等操作需要移动较多数据,比较适合在访问数据比较频繁的场景使用
- LinkedList是双向链表,在随机访问和修改都需要先去查找节点,但是在插入/删除数据时不需要移动数据,比较适合用在插入/删除频繁的场景中。
- LinkedList还实现了队列接口,通过头或尾进行顺序访问的同时可以删除节点,充分发挥了链表的优势。
- Vector与Stack实现的线程安全,但也降低的效率