JDK 8 LinkedList 详解及详细源码展示

JDK 8 LinkedList 详解及详细源码展示

JDK 8 的 LinkedList 是 Java 集合框架中的核心实现,基于 双向链表 实现,支持高效的插入、删除操作,并提供了双向迭代器。本文结合源码剖析其设计哲学、核心实现及性能优化技术。

一、核心设计目标:双向链表与高效插入/删除
1.1 双向链表特性
  • 双向指针:每个节点包含前驱(prev)和后继(next)指针,支持双向遍历。
  • 动态增长:无需预先分配固定容量,内存按需分配。
1.2 高效操作
  • 插入/删除:时间复杂度为 O(1)(已知插入位置的前驱节点)。
  • 随机访问:时间复杂度为 O(n),需从头或尾遍历。
二、源码核心类结构
// java.util.LinkedList.java
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable {
    // 元素数量
    transient int size = 0;
    // 头节点
    transient Node<E> first;
    // 尾节点
    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;
        }
    }

    // 构造方法
    public LinkedList() {
    }

    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }
}
三、核心方法源码解析
3.1 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++;
    modCount++;
}
3.2 add 方法(指定位置插入)
public void add(int index, E element) {
    checkPositionIndex(index);
    if (index == size)
        linkLast(element);
    else
        linkBefore(element, node(index));
}

void linkBefore(E e, Node<E> succ) {
    final Node<E> pred = succ.prev;
    final Node<E> newNode = new Node<>(pred, e, succ);
    succ.prev = newNode;
    if (pred == null)
        first = newNode;
    else
        pred.next = newNode;
    size++;
    modCount++;
}

Node<E> node(int 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;
    }
}
3.3 remove 方法
public E remove(int index) {
    checkElementIndex(index);
    return unlink(node(index));
}

E unlink(Node<E> x) {
    final E element = x.item;
    final Node<E> next = x.next;
    final Node<E> prev = x.prev;

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

    if (next == null) {
        last = prev;
    } else {
        next.prev = prev;
        x.next = null;
    }

    x.item = null;
    size--;
    modCount++;
    return element;
}
3.4 get 方法
public E get(int index) {
    checkElementIndex(index);
    return node(index).item;
}
四、关键优化技术
4.1 双向遍历优化
  • 索引定位:在 node(int index) 方法中,根据索引位置选择从头或尾开始遍历,减少遍历时间。
  • 迭代器优化ListIterator 支持双向遍历,时间复杂度为 O(n/2)。
4.2 内存局部性
  • 节点紧凑:每个节点仅包含前驱、后继指针和元素,内存占用紧凑。
  • 缓存友好:通过 node(int index) 的双向遍历策略,提升缓存命中率。
4.3 快速失败机制
  • 修改计数器:通过 modCount 字段检测并发修改。
  • 迭代器检查:在迭代过程中,若 modCount 变化,抛出 ConcurrentModificationException
五、典型应用场景
5.1 基础操作
// 创建 LinkedList
List<String> list = new LinkedList<>();

// 尾部插入
list.add("A");
list.add("B");

// 头部插入
list.addFirst("C");

// 尾部删除
list.removeLast();
5.2 队列/栈实现
// 作为队列使用
Queue<String> queue = new LinkedList<>();
queue.offer("A");
String head = queue.poll();

// 作为栈使用
Deque<String> stack = new LinkedList<>();
stack.push("A");
String top = stack.pop();
5.3 双向遍历
// 正向遍历
ListIterator<String> iterator = list.listIterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

// 反向遍历
while (iterator.hasPrevious()) {
    System.out.println(iterator.previous());
}
六、总结

JDK 8 的 LinkedList 通过双向链表、双向遍历、动态增长等核心技术,实现了高效的插入和删除操作。其源码实现深刻体现了数据结构与算法的精髓:

  1. 双向链表:支持 O(1) 时间的插入和删除(已知前驱节点)。
  2. 内存局部性:通过双向遍历策略,减少遍历时间。
  3. 快速失败:通过 modCount 检测并发修改,保障迭代安全。

实际开发中,建议根据场景选择数据结构:

  • 频繁插入/删除:优先使用 LinkedList
  • 随机访问:优先使用 ArrayList
  • 多线程场景:使用 CopyOnWriteArrayList 或通过 Collections.synchronizedList 包装。

深入理解其源码,有助于设计高性能的 Java 应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值