Java集合之List——LinkedList详解
简介
LinkedList
的底层实现是一个双向链表,它是接口List
和Deque
的一个实现类;LinkedList
是非同步的;LinkedList
的iterator
和listIterator
方法返回的迭代器是fail-fast的。
源码解读
继承关系
1 | public class LinkedList<E> |
结构图:
与ArrayList
相比而言多实现了Deque
接口,继承的抽象类变为了AbstractList
的子类AbstractSequentialList
,并且减少了RandomAccess
接口的实现。
成员变量
仅介绍部分。LinkedList
的底层由一个双向链表实现,其定义为:1
2
3
4
5private static class Node<E> {
E item; //节点存储的内容
Node<E> next; //对下个节点的引用
Node<E> prev; //对前个节点的引用
}
其余一些使用频率较高的成员变量:1
2
3transient int size = 0; //集合大小
transient Node<E> first;//指向头结点的引用
transient Node<E> last;//指向尾结点的引用
一下两张图片帮助理解,来源
构造方法
public LinkedList();
,无参构造方法;public LinkedList(Collection<? extends E> c);
,构造一个包含指定集合元素的列表,其顺序由集合的迭代器返回。
1 | public LinkedList() { |
辅助方法
接下来将介绍一些辅助方法,比较重要,LinkedList
中通过其完成大部分List
和Deque
操作,如Add、remove、offer
等方法。
1 | private void linkFirst(E e) { //头插元素 |
1 | private E unlinkFirst(Node<E> f) { //删除头结点 |
1 | Node<E> node(int index) { //用于定位要操作节点的位置 |
常用方法
与ArrayList
很接近(不考虑实现的话),具体可见博客
这里主要介绍一下与ArrayL
不同的,即Deque
接口的一些实现方法。
以下两组都可以将集合作为队列来操作,两组操作的区别:
- 前者属于
List
的实现,后者属于queue
的实现; - 后者
offer、poll、peek
相对比较友好,遇到队列为空等情况不会报错,而是有返回值,而前一组抛出错误; - 作为
List
使用时,一般采用add、get
方法,作为Queue
使用时,才会采用offer、poll、peek
等方法; - 作为链表对象时,offer等方法相对来说没有什么意义。
1 | boolean add(E e); //将元素插入队列 |
1 | boolean offer(E e);//将元素插入队列 |
其余操作,可相互组合,当做栈或队列使用。1
2
3
4
5
6
7
8
9
10
11
12
13
14public boolean offerFirst(E e); //存
public boolean offerLast(E e);
public E peekFirst(); //取
public E peekLast();
public E pollFirst(); //删
public E pollLast();
//还有一对操作push、pop,可直接当做栈来使用
public void push(E e) {
addFirst(e);
}
public E pop() {
return removeFirst();
}
效率分析
LinkedList
由于本质是链表,相对于ArrayList
而言,插入或删除元素时不再需要对元素进行挪动,所以它在数据的删改方面会很快(只指插入删除这一个动作),而在查询或修改元素过程时,不能像数组一下通过下标访问,每次需要遍历链表进行查找,这样就比ArrayList
慢很多。
综上LinkedList
,在增删(在List
前段位置)操作较多,查询、修改较少时比较合适。