概览

LinkedList类扩展AbstractSeqentialList并执行List,queue接口。
基于双向链表实现,只能顺序访问,但是可以快速地在链表中间插入和删除元素。
LinkedList在随机访问方面相对比较慢,但它的特性集较ArrayList更大。LinkedList 还可以用作栈、队列和双向队列。

总结:

  • 对于链表头尾的操作,实现deque接口,效率都比较高,LinkedList 保存了头尾两个节点,以及节点数
  • 对于关于索引,会判断在前半部分还是后半部分,进行遍历
  • 关于元素,根据元素是否为空决定比较地址还是内容,根据是第一次出现还是最后一次出现决定遍历方向

LinkedList本身定义了一些主要用于操作和访问列表的方法:

  1. public void push(E e) // 等同于 addFirst
  2. public boolean offerFirst(E e) // 等同于 addFirst
  3. public void addFirst(E e) // 在列头加元素 == private void linkFirst(E e)
  4. public boolean offerLast(E e) // 等同于 addLast
  5. public void addLast(E e) // 在列尾加元素 == void linkLast(E e)
  6. public boolean add(E e) // 在列尾加元素 == void linkLast(E e)
  7. public void add(int index, E element) // linkLast(element) or linkBefore(element, node(index))
  8. public boolean addAll(Collection<? extends E> c)
  9. public E peekFirst()
  10. public E getFirst() // 获得第一个元素
  11. public E getLast() // 获得最后一个元素
  12. public E peekLast()
  13. public E pop() // 等同于removeFirst
  14. public E pollFirst() // 等同于removeFirst
  15. public E removeFirst() // 删除并获得第一个元素 -> private E unlinkFirst(Node<E> f)
  16. public E pollLast() // 等同于removeLast
  17. public E removeLast() // 删除并获得最后一个元素 -> private E unlinkLast(Node<E> l)
  18. public boolean remove(Object o) // 遍历查询指定元素删除
  19. public E pollLast() //

关键属性

  1. private static class Node<E> {
  2. E item;
  3. Node<E> next;
  4. Node<E> prev;
  5. Node(Node<E> prev, E element, Node<E> next) {
  6. this.item = element;
  7. this.next = next;
  8. this.prev = prev;
  9. }
  10. }
  1. transient int size = 0;
  2. transient Node<E> first;
  3. transient Node<E> last;

构造器

  1. LinkedList(); // 建立空的链接列表
  2. LinkedList(Collection c); // 建立由c初始化的链接列表

查找

查询会去遍历这个链表,有一个优化的机制,通过二分查询,index决定是从头开查询还是从尾开始查询

  1. public E get(int index) {
  2. checkElementIndex(index);
  3. return node(index).item;
  4. }
  5. Node<E> node(int index) {
  6. // assert isElementIndex(index);
  7. if (index < (size >> 1)) {
  8. Node<E> x = first;
  9. for (int i = 0; i < index; i++)
  10. x = x.next;
  11. return x;
  12. } else {
  13. Node<E> x = last;
  14. for (int i = size - 1; i > index; i--)
  15. x = x.prev;
  16. return x;
  17. }
  18. }

添加元素

  • 对链表头尾进行操作

    1. void linkLast(E e) {
    2. final Node<E> l = last;
    3. final Node<E> newNode = new Node<>(l, e, null);
    4. last = newNode;
    5. if (l == null)
    6. first = newNode;
    7. else
    8. l.next = newNode;
    9. size++;
    10. modCount++;
    11. }
    12. private void linkFirst(E e) {
    13. final Node<E> f = first;
    14. final Node<E> newNode = new Node<>(null, e, f);
    15. first = newNode;
    16. if (f == null)
    17. last = newNode;
    18. else
    19. f.prev = newNode;
    20. size++;
    21. modCount++;
    22. }
  • 对链表中间部分添加元素

    1. public void add(int index, E element) {
    2. checkPositionIndex(index);
    3. if (index == size)
    4. linkLast(element);
    5. else
    6. linkBefore(element, node(index));
    7. }
    8. void linkBefore(E e, Node<E> succ) {
    9. // assert succ != null;
    10. final Node<E> pred = succ.prev;
    11. final Node<E> newNode = new Node<>(pred, e, succ);
    12. succ.prev = newNode;
    13. if (pred == null)
    14. first = newNode;
    15. else
    16. pred.next = newNode;
    17. size++;
    18. modCount++;
    19. }
  • 调用addAll方法添加一组元素

    • 无论是addAll(Collection<? extends E> c),还是LinkedList(Collection c) 构造器
    • 本质是调用public boolean addAll(int index, Collection<? extends E> c)

      1. public boolean addAll(int index, Collection<? extends E> c) {
      2. checkPositionIndex(index);
      3. Object[] a = c.toArray();
      4. int numNew = a.length;
      5. if (numNew == 0)
      6. return false;
      7. Node<E> pred, succ;
      8. if (index == size) {
      9. succ = null;
      10. pred = last;
      11. } else {
      12. succ = node(index);
      13. pred = succ.prev;
      14. }
      15. for (Object o : a) {
      16. @SuppressWarnings("unchecked") E e = (E) o;
      17. Node<E> newNode = new Node<>(pred, e, null);
      18. if (pred == null)
      19. first = newNode;
      20. else
      21. pred.next = newNode;
      22. pred = newNode;
      23. }
      24. if (succ == null) {
      25. last = pred;
      26. } else {
      27. pred.next = succ;
      28. succ.prev = pred;
      29. }
      30. size += numNew;
      31. modCount++;
      32. return true;
      33. }

删除元素

  • 对链表头尾进行操作

    1. private E unlinkFirst(Node<E> f) {
    2. // assert f == first && f != null;
    3. final E element = f.item;
    4. final Node<E> next = f.next;
    5. f.item = null;
    6. f.next = null; // help GC
    7. first = next;
    8. if (next == null)
    9. last = null;
    10. else
    11. next.prev = null;
    12. size--;
    13. modCount++;
    14. return element;
    15. }
    16. private E unlinkLast(Node<E> l) {
    17. // assert l == last && l != null;
    18. final E element = l.item;
    19. final Node<E> prev = l.prev;
    20. l.item = null;
    21. l.prev = null; // help GC
    22. last = prev;
    23. if (prev == null)
    24. first = null;
    25. else
    26. prev.next = null;
    27. size--;
    28. modCount++;
    29. return element;
    30. }
  • 对链表中间部分进行操作

    • 判断需要删除元素是否为空,分开进行处理
    • 从头遍历到尾,直到找到第一个符合条件的指定元素,删除

      1. public boolean remove(Object o) {
      2. if (o == null) {
      3. for (Node<E> x = first; x != null; x = x.next) {
      4. if (x.item == null) {
      5. unlink(x);
      6. return true;
      7. }
      8. }
      9. } else {
      10. for (Node<E> x = first; x != null; x = x.next) {
      11. if (o.equals(x.item)) {
      12. unlink(x);
      13. return true;
      14. }
      15. }
      16. }
      17. return false;
      18. }
      19. E unlink(Node<E> x) {
      20. // assert x != null;
      21. final E element = x.item;
      22. final Node<E> next = x.next;
      23. final Node<E> prev = x.prev;
      24. if (prev == null) {
      25. first = next;
      26. } else {
      27. prev.next = next;
      28. x.prev = null;
      29. }
      30. if (next == null) {
      31. last = prev;
      32. } else {
      33. next.prev = prev;
      34. x.next = null;
      35. }
      36. x.item = null;
      37. size--;
      38. modCount++;
      39. return element;
      40. }

      迭代器

      1. public ListIterator<E> listIterator(int index) {
      2. checkPositionIndex(index);
      3. return new ListItr(index);
      4. }
      5. private class ListItr implements ListIterator<E> {
      6. private Node<E> lastReturned;
      7. private Node<E> next;
      8. private int nextIndex;
      9. private int expectedModCount = modCount;
      10. ListItr(int index) {
      11. // assert isPositionIndex(index);
      12. next = (index == size) ? null : node(index);
      13. nextIndex = index;
      14. }
      15. }

      拷贝

  • clone 是一个深拷贝

    1. public Object clone() {
    2. LinkedList<E> clone = superClone();
    3. // Put clone into "virgin" state
    4. clone.first = clone.last = null;
    5. clone.size = 0;
    6. clone.modCount = 0;
    7. // Initialize clone with our elements
    8. for (Node<E> x = first; x != null; x = x.next)
    9. clone.add(x.item);
    10. return clone;
    11. }
    12. private LinkedList<E> superClone() {
    13. try {
    14. return (LinkedList<E>) super.clone();
    15. } catch (CloneNotSupportedException e) {
    16. throw new InternalError(e);
    17. }
    18. }