欢迎访问宙启技术站
智能推送

JDK源码分析(4)之 LinkedList 相关

发布时间:2023-05-15 07:22:00

LinkedList 是继承于 AbstractSequentialList 的双向链表实现。它通过维护两个指针(head 和 tail)实现对链表的遍历。这个类的特点是可以在 O(1) 的时间内插入或删除元素,所以适合需要频繁操作的场景。

下面我们来分析一下 LinkedList 的源码实现。

# 内部实现

LinkedList 实现了 List、Deque 和 Queue 接口,拥有多种访问和操作元素的方法,如:add、offer、remove、peek 等等。下面是一些常用方法的源码实现:

## add

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;

    if (l == null)

        first = newNode;

    else

        l.next = newNode;

    size++;

}

## remove

public E remove() {

    return removeFirst();

}

// 删除链表 个元素

public E removeFirst() {

    final Node<E> f = first;

    if (f == null)

        throw new NoSuchElementException();

    return unlinkFirst(f);

}

// 解除链表中的头节点

private E unlinkFirst(Node<E> f) {

    final E element = f.item;

    final Node<E> next = f.next;

    f.item = null;

    f.next = null; // help GC

    first = next;

    if (next == null)

        last = null;

    else

        next.prev = null;

    size--;

    return element;

}

## peek

public E peek() {

    final Node<E> f = first;

    return (f == null) ? null : f.item;

}

通过这些方法的源码实现,我们可以看到 LinkedList 的设计理念是,尽量使操作时间复杂度为 O(1)。

# 应用场景

LinkedList 适用于在内存中频繁地开辟、释放空间的场景,如文件缓存、内存池等等。同时也适合在数据量较小的情况下进行操作。

然而,由于内部实现原因,LinkedList 并不适合在数据量较大的情况下进行操作,因为会产生大量 GC 垃圾回收。在这种情况下,建议使用 ArrayList 或者其他的数据结构。

# 总结

LinkedList 的设计思路是典型的时间换空间,通过维护头尾指针,实现操作的快速响应。它适合在数据量较小或在内存频繁开辟、释放空间的场景使用。但对于数据量较大的情况,需要注意会产生大量 GC 垃圾回收的问题。