对比Vector、ArrayList、LinkedList有何区别?
Java的集合框架
Java 提供的主要容器类型分别是集合框架与 Map ,集合通常是指 Collection 接口下的 List 、 Set 、 Queue 三类集合。一般认为 Collection 接口是 Java 集合框架的根,其子集构成了集合框架。 Map 并不属于 Collection 接口的子集,但是在概念是也当做集合来使用,但是它本身并不是真正的集合。注意,所有集合中都不能存放基础数据类型,只能存放对象的引用。
![Java Collection](https://raw.githubusercontent.com/wqdchn/blog-image/master/java-vector-arraylist-linkedlist/Java Collection.png)
List集合
Vector 、 ArrayList 、 LinkedList 是 List 的实现,都是有序集合。它们都提供了诸如随机访问、添加、删除等常用操作,以及迭代器遍历、排序等方法,在功能上较为相近。但是其具体的设计存在一定区别,因此在性能、线程安全等方面有所不同。
常用方法:
- size() 集合元素个数
- add()/addAll() 添加元素
- remove()/removeAll() 删除元素
- get() 获取元素
- set() 修改元素
- sort() 集合元素排序
- toArray() 转换
- clear() 清空集合
Vector
Vector 是 Java 早期提供的线程安全的动态数组,内部使用对象数组类保存数据,其线程安全通过 synchronized 实现。
public synchronized boolean add(E e) { |
Vector 默认创建一个大小为 10 的 Object 数组,并将动态扩展大小 capacityIncrement 设置为 0 。 Vector 能够根据需要进行自动扩容,当数组已满时,会创建新的数组,并拷贝原有数据。在初始化时若指定了容量的动态扩展大小 capacityIncrement > 0 则依据指定的大小进行扩容,否则默认扩展一倍的容量。
private void grow(int minCapacity) { |
ArrayList
ArrayList 是应用最多的动态数组,由于它没有了同步开销,因此性能更加良好。相应的,它不是线程安全的。 ArrayList 也支持动态扩容,但是与 Vector 默认扩容一倍不同, ArrayList 扩容时是增加当前容量的 50% ,其默认容量是 10 。
|
ArrayList 在执行插入操作时,若元素个数超过当前数组预定义容量的最大值,数组需要扩容,扩容过程需要调用底层 System.arraycopy() 方法进行大量的数组复制操作。它在删除元素时并不会减少数组的容量,但是如果需要缩小数组容量,可以调用 trimToSize() 方法。在查找元素时要遍历数组,对于非 null 的元素采取 equals 的方式寻找。
LinkedList
LinkedList 是双向链表,它不需要进行调整容量,它也不是线程安全的。 LinkedList 在插入元素时,须创建一个新的 Entry 对象,并更新相应元素的前后元素的引用;在查找元素时,需遍历链表;在删除元素时,要遍历链表,找到要删除的元素,然后从链表上将此元素删除即可。
排序操作
Vector 、 ArrayList 、 LinkedList 内部都实现了排序操作,允许进行自定义排序。
public class Test { |
总结
Vector 、 ArrayList 、 LinkedList 是 List 的实现,都是有序集合。 Vector 、 ArrayList 使用数组实现,有需要时可以进行动态扩容, LinkedList 使用双向链表实现,不需要动态扩容。 Vector 是线程安全的,而 ArrayList 、 LinkedList 是线程不安全的。在分析以上三类集合的读写效率时,还应注意的一点是是否需要考尾部的情况。
以上内容都基于 jdk1.8.0_161 。
JDK源码是四个空格缩进,而我用的是Google Style两个空格缩进,有点不协调orz。