-
This class is a member of the
-
Java Collections Framework.
-
@author Josh Bloch
-
@see List
-
@see ArrayList
-
@since 1.2
-
@param the type of elements held in this collection
*/
public class LinkedList
extends AbstractSequentialList
implements List, Deque, Cloneable, java.io.Serializable
{
…
}
1.2 翻译
双向链表是实现了List和Deque接口。实现了所有List的操作和允许值为Null。
所有的操作执行都与双向链表相似。操作索引将遍历整个链表,至于是从头开始遍历还是从尾部开始遍历取决于索引的下标距离哪个比较近。
需要注意的是这个方法不是同步的方法,需要同步的应用(ConcurrentLinkedDeque高效的队列),如果多个线程同时操作LinkedList实例和至少有一个线程修改list的结构,必须在外部加同步操作。关于结构性操作可以看前面的HashMap的介绍。这个同步操作通常是压缩在某些对象头上面。(synchronized就是存储在对象头上面。)
如果对象头不存在这样的对象,这个列表应该使用{@link Collections#synchronizedList Collections.synchronizedList}工具来封装,这个操作最好是在创建List之前完成,防止非同步的操作。List list = Collections.synchronizedList(new ArrayList(…));但是一般不用这个方法,而是用JUC包下的ConcurrentLinkedDeque更加高效,(因为这个底层采用的是CAS操作)
快速失败机制(…好像在集合容器下面都有这个机制来抛出异常…)
当一个list被多个线程成同时修改的时候会抛出异常。但是不能用来保证线程安全。
所以在多线程环境下,还是要自己加锁或者采用JUC包下面的方法来保证线程安全, 而不能依靠fail-fast机制抛出异常,这个方法只是用来检测bug。
整个说明文档其实是跟ArrayList差不多,只不过是他们的底层实现的数据结构不一样而已,可以参考对比ArrayList。【【手撕源码系列】ArrayList源码解读—Java8版本】
1.3 一语中的
1.4 LinkedList和ArrayList的区别
顺序插入的速度ArrayList会快些,LinkedList的速度会稍慢一些。因为ArrarList只是在指定的位置上赋值即可,而LinkedList则需要创建Node对象,并且需要建立前后关联,如果对象较大的话,速度会慢一些。
LinkedList的占用的内存空间要大一些。
数组遍历的方式ArrayList推荐使用for循环,而LinkedList则推荐使用foreach,如果使用for循环,效率将会很慢。
一般我们这样认为:ArrarList查询和获取快,修改和删除慢;LinkedList修改和删除快,查询和获取慢。其实这样说不准确的。
LinkedList做插入、删除的时候,慢在寻址,快在只需要改变前后Entry的引用地址;
ArrayList做插入、删除的时候,慢在数组元素的批量copy,快在寻址。
所以,如果待插入、删除的元素是在数据结构的前半段尤其是非常靠前的位置的时候,LinkedList的效率将大大快过ArrayList,因为ArrayList将批量copy大量的元素;越往后,对于LinkedList来说,因为它是双向链表,所以在第2个元素后面插入一个数据和在倒数第2个元素后面插入一个元素在效率上基本没有差别,但是ArrayList由于要批量copy的元素越来越少,操作速度必然追上乃至超过LinkedList。
1.5 如何选择?
1、如果你十分确定你插入、删除的元素是在前半段,使用LinkedList
2、如果你十分确定你删除、删除的元素后半段,使用ArrayList
3、如果你上面的两点不确定,建议你使用LinkedList
说明:
其一、LinkedList整体插入、删除的执行效率比较稳定,没有ArrayList这种越往后越快的情况;
其二、插入元素的时候,弄得不好ArrayList就要进行一次扩容,而ArrayList底层数组扩容是一个既消耗时间又消耗空间的操作,所以综合来看就知道选择哪个类型的list
我们先来看看LinkedList的定义:
public class LinkedList
extends AbstractSe