大家好,我是伍六七。
今天,阿七继续带大家来看一道经典面试题。对比 Vector、ArrayList、LinkedList 有何区别?你应该使用什么线程安全的集合框架?
让我们开始正文。
一、3 个角度对比 Vector、ArrayList、LinkedList
3.1 使用场景的区分:
- Vector:线程安全,适用于多线程环境下的数据操作。
- ArrayList:非线程安全,适用于单线程环境下的数据操作。
- LinkedList:适用于频繁插入、删除操作的场景。
3.2 扩容操作和细节的区分:
- Vector 和 ArrayList:在添加元素时,如果当前容量不足,会进行扩容操作。Vector 每次扩容会将容量翻倍,而 ArrayList 每次扩容会增加 50%的容量。扩容操作会导致数组重新分配内存,因此会影响性能。
- LinkedList:在添加元素时,不需要进行扩容操作,因为它底层是链表结构,每个节点只需要记录前驱和后继节点的地址即可。
3.3 底层数据结构的区分:
- Vector 和 ArrayList:底层数据结构都是数组,因此支持随机访问,时间复杂度为 O(1)。但是在插入和删除元素时,需要移动其他元素,时间复杂度为 O(n)。
- LinkedList:底层数据结构是双向链表,因此不支持随机访问,只能通过遍历来访问元素。但是在插入和删除元素时,只需要修改前驱和后继节点的地址,时间复杂度为 O(1)。
总之,Vector、ArrayList、LinkedList 都是 Java 集合框架中常用的 List 实现类,它们各有优缺点,应根据具体场景选择合适的实现类。
如果需要高效的随机访问,可以选择 ArrayList;如果需要频繁的插入和删除操作,可以选择 LinkedList;如果需要线程安全,可以使用 Vector 嘛?
二、线程安全场景下,使用什么集合框架?
Vector 通过在方法上添加 synchronized 关键字来实现线程安全。
在 Vector 的方法中,使用了 synchronized 关键字来保证同一时间只有一个线程可以访问 Vector 的方法,从而避免了多线程并发访问时的数据竞争和不一致性。
尽管 Vector 可以提供线程安全的操作,但 Java 官方并不推荐使用 Vector,主要原因是使用 synchronized 锁住整个数组,会有很大的性能问题。
由于 Vector 的方法都是使用 synchronized 关键字修饰的,这会导致在多线程环境下性能较差。
因为每个线程在访问 Vector 的方法时都需要获得锁,这会导致其他线程阻塞等待,从而降低了并发性能。
如果不使用 Vector,可以使用以下方式来保证线程安全:
2.1 synchronizedList
使用 Collections 工具类的 synchronizedList 方法,将 ArrayList 转换为线程安全的 List:
ini
List<String> list = Collections.synchronizedList(new ArrayList<>());
2.2 CopyOnWriteArrayList
使用 CopyOnWriteArrayList 类,它是 Java 并发包(java.util.concurrent)中提供的线程安全的 List 实现类:
ini
List<String> list = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList 在写操作时会创建一个新的数组,并将原数组的数据复制到新数组中,从而实现线程安全。由于读操作不需要加锁,因此读操作的性能较高,适用于读多写少的场景。
总之,尽管 Vector 可以提供线程安全的操作,但由于性能问题,Java 官方不推荐使用。可以使用 Collections 工具类的 synchronizedList 方法或者 CopyOnWriteArrayList 类来保证线程安全。具体选择哪种方式,应根据具体场景和需求来决定。
你学会了嘛?学会了点个赞再走~
关注我,送你全套我整理的 Java 岗位面试资料。这是我自己之前整理的面试题,靠着这份面试题,我从 30 人的小公司,进了 2000 人+的央企子公司,之后又进了互联网大厂。