LinkedList
类继承
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
...
}
- 同 ArrayList 一样实现了 Serializable(支持序列化)、Cloneable(支持克隆)、List(列表基本操作)
- Deque:双端队列接口,意味着 LinkedList 既可以作为栈使用也可以作为队列来使用
- Queue 接口定义了普通队列的操作方法(先进先出)
- Deque 继承了 Queue ,自己有的方法结合 Queue 的方法,使得 Deque 既可以先进先出,也可以后进先出
- AbstractSequentialList:提供标准迭代器;同时继承自 AbstractList 类,为链表这种数据结构提供索引的操作方法
链表本身不支持索引,但是 LinkedList 是可以根据索引操作元素的原因就是实现了 List 等接口
类成员
类属性
transient int size = 0; // 元素个数
transient Node<E> first; // 第一个元素
transient Node<E> last; // 最后一个元素
内部类
// 节点类
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
// 还有个标准的迭代器(继承自 AbstractSequentialList),正向,支持 remove
// 增强的迭代器,双向,支持 remove、add、set
private class ListItr implements ListIterator<E> {}
// 反向迭代器,反向,支持 remove
private class DescendingIterator implements Iterator<E> {}
// 类似 ArrayList 的 ArrayListSpliterator(并行流高效操作元素)
static final class LLSpliterator<E> implements Spliterator<E> {}
构造方法
// 无参构造
public LinkedList() {
}
// 有参构造,参数是一个 Collection
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
添加元素
public boolean add(E e) {
linkLast(e); // 尾部添加
return true;
}
void linkLast(E e) {
final Node<E> l = last; // 尾节点
final Node<E> newNode = new Node<>(l, e, null); // 当前数据封装成节点,并链接
last = newNode; // 新的节点作为尾节点(维护last属性)
if (l == null) // 如果原来的尾节点为空,说明链表是空。链表是空:维护头结点(新节点作为头结点);说明链表不为空:不用维护头结点
first = newNode;
else
l.next = newNode; // 原来的尾节点下一个元素是新节点(新节点作为尾节点,维护链表)
size++;
modCount++;
}
获取元素
-
获取首尾节点
直接获取 first 和 last 属性就行了
public E getFirst() { final Node<E> f = first; // 链表首节点 if (f == null) throw new NoSuchElementException(); return f.item; // 首节点的数据 } public E getLast() { final Node<E> l = last; // 链表尾节点 if (l == null) throw new NoSuchElementException(); return l.item; // 尾节点的数据 } -
通过索引获取
LinkedList 是链表本身是不具备索引操作的能力,所以要专门提供方法
public E get(int index) { checkElementIndex(index); // 检查索引下标是否合法 return node(index).item; // node(index) 根据下标获取节点,然后返回 node.item(节点的数据) } Node<E> node(int index) { // 因为是双向链表,所以可以正向遍历,也可以反向遍历,根据这个特性查找元素时不用遍历整个链表,比较 size 和 index 决定正向还是反向遍历 if (index < (size >> 1)) { // size >> 1:右移运算,就是 size 的一半 // 正向遍历 Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { // 反向遍历 Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
总结
- 基于双向链表实现,元素由节点构成(每个节点包含
item、prev、next) - 元素有序(添加顺序)、允许元素重复、允许元素为null、线程不安全
- 极具有队列的特性,也具有栈的特性
- 不支持随机访问,没有实现 RandomAccess 接口(但是也能根据下标操作元素,这是JDK额外提供的)
- 随机访问元素(通过下标)时间复杂度 O(n)(准确的说是 O(n/2),因为是双向链表)
- 头尾部插入、删除元素时间复杂度 O(1),中间插入、删除元素时间复杂度 O(n)
- 三种迭代器
Iterator标准迭代器。通过iterator()获取,继承自AbstractSequentialList;单向,支持removeListIterator增强迭代器。通过listIterator()获取;双向,支持add/set/removeDescendingIterator反向迭代器。通过descendingIterator()获取;反向,支持remove

浙公网安备 33010602011771号