LinkedList 源码分析-初始化&节点查询

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

LinkedList 源码分析-初始化

LinkedList 底层是链表结构,适用于集合元素先入先出和先入后出的场景。

初始化

LinkedList 底层数据结构是一个双向链表,双向链表的特点:

  1. 链表每个节点我们叫做 Node
  2. Node 有 前节点(prev),代表前一个节点的位置
  3. Node 有 后节点(next),代表后一个节点的位置
  4. first 是双向链表的头节点,它的前一个节点指向 null
  5. last 是双向链表的尾节点,它的后一个节点指向 null
  6. 当链表中没有数据时,first 和 last 是同一个节点,前后都指向 null
  7. 链表中的每个节点都可以向前或者向后查询
  8. 双向链表按理说是没有内存大小限制的,当然也限于机器的配置

Node的组成部分,源码:

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    transient int size = 0;

    /**
     * Pointer to first node.
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;

    /**
     * Pointer to last node.
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    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;
        }
    }    
    
    ......
}
复制代码
  1. E item;表示节点值
  2. Node<E> next;表示下一个节点
  3. Node<E> prev表示前一个节点
  4. Node(Node<E> prev, E element, Node<E> next) 初始化参数:前一个节点、本身节点值、后一个节点

查询

链表查询是比较慢的,需要一个一个循环遍历查找,源码:

    Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            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;
        }
    }
复制代码
  1. if (index < (size >> 1))如果 index 处于队列的前半部分,从头开始找
  2. for (int i = 0; i < index; i++)直到 for 循环到 index 的前一个 node 停止
  3. for (int i = size - 1; i > index; i--)如果 index 处于队列的后半部分,从尾开始找,直到 for 循环到 index 的后一个 node 停止

LinkedList 的查询采取了简单二分法,先看 index 是在链表的前半部分,还是后半部分。如果是前半部分,就从头开始寻找,如果在后半部分,则从后开始查找。此举可以将查询的平均次数减半。

猜你喜欢

转载自juejin.im/post/7085605852006055973