揭秘LinkedList源码,探索其精妙设计与ArrayList异同
2023-11-26 13:26:30
剖析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。