非线程安全:
- ArrayList: 基于动态数组实现,支持随机访问,即通过索引访问元素为 O (1)。在添加和删除元素时,如果操作位置不是列表末尾,需要移动大量元素(所有元素向后移一格),性能低。
- LikedList:基于双向链表实现,在插入和删除元素时,如果已经持有节点引用(迭代器遍历的i 值指向),只需修改链表的指针,不需要移动大量元素,时间复杂度为 O (1)。但随机访问元素时,需要从链表头或链表尾开始遍历,时间复杂度为 O (n)。适用于需要频繁进行插入和删除操作的场景。
线程安全:
- Vector: 基于数组实现。
Vector中的方法几乎都加了synchronized关键字,性能低。现在几乎不用。 - collection.synchronizedList:上了collection.synchronizedList包装的List,99%和Vector一样,但是没那么老旧,和Vector一样在迭代器中线程都不安全,因为他们的锁都是对象级的锁,防不了迭代器层级的并发,需要另外在迭代器中上锁.
CopyOnWriteArrayList: 在对列表进行修改时,会创建一个新的数组,将修改操作应用到新数组上,而读操作仍然在原数组上进行,这样可以保证读操作不会被写操作阻塞,实现了读写分离。适用于读操作远远多于写操作的并发场景。在迭代器中线程安全,因为读的是快照.[tips:快照只能读]
迭代器:
Iterator普通迭代器只能读和删,想进行其他操作需要用双向迭代器IteratorList
普通for循环的remove会到导致索引异常[删除元素→索引前移→i++导致跳过一个元素]
ArrayList:
线程不安全:
ArrayList内部维护了一个size,高并发下多个线程同时对一个size进行修改,可能会导致数据覆盖 [B线程覆盖了A线程,同时使size++,导致跳过一个索引,变为null] ,甚至数组越界 [两个线程看了size,都认为不需要扩容]
LinkedList:
在没有迭代器遍历来直接获得节点引用的情况下,各方面几乎被ArrayList完爆。
JVM内部不具有索引表,即便明确具体索引数字,也要遍历链表。而迭代器内部维护了节点引用,可以直接通过节点引用O(1)的访问、修改节点数据.
CopyOnWriteArrayList:
所有修改操作都是复制一份新数组,写入性能差,适合读多写少
线程安全:
方法级锁,保证修改时线程安全,操作时复制一份新数组,并重新指定数组地址。在重新指定新数组的地址前,都是读的旧数组快照。同时配合volatile关键字禁止CPU、JVM调优来保证其他线程可以立马感知新数组地址。读操作无锁,因为读的是快照



