- 底层数据结构是
双向链表
- 实现了
Deque
接口,Deque接口继承了Queue接口,所以说LinkedList可以被当作队列
,栈
来使用 - 成员变量
- size 链表的大小
- first 头节点
- last 尾节点
- 构造方法
- 空构造
- 集合构造
public LinkedList(Collection<? extends E> c) { this(); addAll(c); }
- 核心操作方法
- add方法
- 逻辑:向链表的尾部追加元素
- 源码
public boolean add(E e) { linkLast(e); return true; }
- linkLast方法
void linkLast(E e) { // l = 尾节点 final Node<E> l = last; // 临时Node 元素 -> e 前节点 等于 旧的last final Node<E> newNode = new Node<>(l, e, null); // 尾节点 -> e last = newNode; // 尾节点为空 -> 链表就为空 // 因为如果是一个元素的话,first=last if (l == null) // 让头 -> e first = newNode; else // last <=> l l.next = newNode; size++; modCount++; }
- remove方法
- 逻辑:迭代 ,equals判断,存在就删除,指针(Node)位置调整
- 源码
public boolean remove(Object o) { if (o == null) { // 判断链表里面的null元素,null可以被添加到集合里面的 for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); return true; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; }
- unlink方法
E unlink(Node<E> x) { // assert x != null; final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev; if (prev == null) { first = next; } else { prev.next = next; x.prev = null; } if (next == null) { last = prev; } else { next.prev = prev; x.next = null; } x.item = null; size--; modCount++; return element; }
- 图示
- get方法
- 逻辑
- 检查位置是否合法(
本质就是index与size作比较
) - 返回元素
- 源码
public E get(int index) { checkElementIndex(index); return node(index).item; }
- checkElementIndex(index)方法
private void checkElementIndex(int index) { // 做一个异常抛出 if (!isElementIndex(index)) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
- isElementIndex(index)方法
private boolean isElementIndex(int index) { // index 范围在 0~size之间就是合法的 return index >= 0 && index < size; }
node(index).item;
Node<E> node(int index) { // 断言 下标不超出限制 // assert isElementIndex(index); // 为了速度和性能的提升 // 判断 index 离哪段比较近,那么就从那端开始遍历 if (index < (size >> 1)) { // index < 大小的一半 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; } }
- set方法
- 逻辑
- 检查边界
- 调用node()查找Node
- Node的
item
域赋值为新值 - 返回老值
- 源码
public E set(int index, E element) { // 检查边界 checkElementIndex(index); // 调用node()查找Node Node<E> x = node(index); E oldVal = x.item; // Node的item域赋值为新值 x.item = element; // 返回老值 return oldVal; }