返回

你不知道的LinkedList(一):基于jdk1.8的LinkdeList源码分析

后端

在Java中,LinkedList是一个非常重要的数据结构,它继承了AbstractSequentialList,实现了List、Deque、Cloneable和java.io.Serializable。与ArrayList不同,LinkedList是一个双向链表,支持快速插入和删除操作,非常适合于频繁增删的场景。

LinkedList的整体结构

LinkedList是一个双向链表,由一组节点组成,每个节点包含了数据和指向下一个节点的指针。链表的首节点和尾节点分别由first和last两个引用指向,如下图所示:

+--------------+       +--------------+
| first        |------>| last         |
+--------------+       +--------------+
| data: null   |       | data: null   |
| next: node 1 |       | next: null    |
+--------------+       +--------------+

节点的实现

LinkedList中的节点由Node类表示,其定义如下:

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(E item) {
        this.item = item;
    }
}

Node类包含三个属性:item、next和prev。item属性存储节点的数据,next属性指向下一个节点,prev属性指向前一个节点。

插入操作

LinkedList的插入操作非常高效,只需要在指定位置创建一个新的节点,然后将该节点插入到链表中即可。插入操作的代码如下:

public void add(int index, E element) {
    checkPositionIndex(index);

    Node<E> newNode = new Node<>(element);

    if (index == 0) {
        first = newNode;
    } else {
        Node<E> prev = node(index - 1);
        newNode.next = prev.next;
        prev.next = newNode;
    }

    size++;
    modCount++;
}

删除操作

LinkedList的删除操作也非常高效,只需要找到要删除的节点,然后将其从链表中删除即可。删除操作的代码如下:

public E remove(int index) {
    checkElementIndex(index);

    Node<E> node = node(index);
    Node<E> prev = node.prev;
    E element = node.item;

    if (prev == null) {
        first = node.next;
    } else {
        prev.next = node.next;
    }

    size--;
    modCount++;

    return element;
}

性能分析

LinkedList的性能与ArrayList相比,在插入和删除操作上具有明显的优势。这是因为LinkedList不需要像ArrayList那样移动元素来腾出空间,因此插入和删除操作的复杂度为O(1)。但是在随机访问和查找操作上,LinkedList的性能不如ArrayList,这是因为LinkedList需要遍历链表才能找到指定位置的元素,因此随机访问和查找操作的复杂度为O(n)。

总结

LinkedList是一个非常重要的数据结构,它具有插入和删除操作高效、内存占用小等优点。但是,LinkedList在随机访问和查找操作上的性能不如ArrayList。因此,在选择使用LinkedList还是ArrayList时,需要根据具体的应用场景进行权衡。