返回

揭秘LinkedList源码,探索其精妙设计与ArrayList异同

Android

剖析LinkedList 源码,探究其奥妙与ArrayList的异同#



在上一篇文章中,我们深入剖析了 ArrayList 的源码,领略了其巧妙的实现。今天,让我们将目光投向 LinkedList,探寻其独具特色的数据结构和与 ArrayList 的异同。从图中可以看出,LinkedList 和 ArrayList 都继承自 java.util.AbstractCollection 抽象类,共享许多基础方法,但 LinkedList 还实现了 java.util.List 接口,使其拥有更丰富的功能。


揭开 LinkedList 的神秘面纱

LinkedList 采用链表数据结构,是一种动态的数据结构,它由一组节点组成,每个节点包含一个数据项和指向下一个节点的指针。与 ArrayList 不同,LinkedList 在内存中不是连续存储的,而是通过指针将各个节点连接起来。这种结构使得 LinkedList 具有很强的灵活性,可以方便地进行插入和删除操作,但同时也带来了查找效率较低的问题。


窥探 LinkedList 的实现细节

LinkedList 的核心实现类为 java.util.LinkedList,它提供了许多重要的方法,如 add、remove、get、set 等。这些方法的实现都依赖于 LinkedList 的底层数据结构——节点。每个节点都包含一个数据项和指向下一个节点的指针,如下图所示:

class Node<E> {
    E item;
    Node<E> next;
}

LinkedList 类使用一个头节点和一个尾节点来标识链表的开始和结束,如下图所示:

class LinkedList<E> {
    Node<E> first;
    Node<E> last;
}

当在 LinkedList 中添加元素时,新元素将被添加到链表的末尾,如下所示:

public void addLast(E e) {
    Node<E> l = last;
    Node<E> newNode = new Node<>(e);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
}

当从 LinkedList 中删除元素时,将从链表中移除该元素并返回该元素,如下所示:

public E removeFirst() {
    Node<E> f = first;
    if (f == null)
        return null;
    else {
        E element = f.item;
        Node<E> next = f.next;
        f.next = null; // help GC
        first = next;
        if (next == null)
            last = null;
        return element;
    }
}

当在 LinkedList 中获取元素时,将遍历链表并返回指定索引处的元素,如下所示:

public E get(int index) {
    Node<E> x = first;
    for (int i = 0; i < index; i++) {
        x = x.next;
        if (x == null)
            throw new IndexOutOfBoundsException();
    }
    return x.item;
}

LinkedList 与 ArrayList 的异同对比

LinkedList 和 ArrayList 都是 Java 中常用的数据结构,但它们在实现、性能和适用场景上存在一些差异。

特性 LinkedList ArrayList
数据结构 链表 数组
插入和删除
查找
内存使用 不连续 连续
适用场景 需要频繁插入和删除操作 需要频繁查找操作

性能差异剖析

LinkedList 在插入和删除操作上具有优势,因为链表的结构使得它可以很方便地找到要插入或删除的元素,而 ArrayList 则需要移动大量元素来腾出或填补空间。然而,LinkedList 在查找操作上却不如 ArrayList,因为链表需要遍历链表才能找到要查找的元素,而 ArrayList 可以直接通过索引访问元素。


内存使用差异

LinkedList 在内存使用上也不同于 ArrayList。LinkedList 中的元素不是连续存储的,而是通过指针连接起来的,这使得 LinkedList 可以更加灵活地调整大小,但同时也带来了内存开销,因为每个节点都需要存储指向下一个节点的指针。ArrayList 中的元素则是连续存储的,这使得 ArrayList 能够更有效地利用内存,但同时也限制了 ArrayList 的灵活性。


适用场景差异

LinkedList 和 ArrayList 都有其独特的适用场景。LinkedList 适用于需要频繁插入和删除操作的情况,例如缓存、队列等。ArrayList 适用于需要频繁查找操作的情况,例如集合、数组等。


结语

LinkedList 和 ArrayList 都是 Java 中常用的数据结构,它们各有优缺点,适用于不同的场景。通过对 LinkedList 源码的分析,我们进一步了解了 LinkedList 的实现原理和与 ArrayList 的异同。希望这些知识能够帮助您在实际开发中更加熟练地使用 LinkedList。