LinkedList详解

LinkedList 是 Java 集合框架中 List 接口和 Deque 接口的双向链表实现。与 ArrayList 基于数组的实现不同,LinkedList 使用链表数据结构存储元素。

基本特性

  1. 实现结构:双向链表(每个节点包含前驱和后继指针)

  2. 线程安全:非线程安全(需要外部同步)

  3. 允许元素:允许 null 元素

  4. 实现接口

    • List 接口

    • Deque 接口(双端队列操作)

    • Queue 接口(队列操作)

性能特点

操作时间复杂度说明
插入/删除头部O(1)直接修改头节点指针
插入/删除尾部O(1)直接修改尾节点指针
插入/删除中间O(n)需要遍历到指定位置
随机访问O(n)需要从头或尾遍历
搜索元素O(n)需要遍历整个链表

对比ArrayList

特性LinkedListArrayList
底层结构双向链表动态数组
随机访问慢(O(n))快(O(1))
头部插入/删除快(O(1))慢(O(n))
尾部插入/删除快(O(1))快(通常O(1))
中间插入/删除慢(O(n))慢(O(n))
内存占用较高(每个元素需要额外指针)较低(仅存储数据)
  1. 适合使用 LinkedList 的情况

    • 需要频繁在头部/尾部进行插入删除操作

    • 需要实现栈、队列或双端队列功能

    • 不确定数据量大小,需要动态增长

  2. 不适合使用 LinkedList 的情况

    • 需要频繁随机访问元素

    • 内存资源紧张

    • 需要线程安全集合(需外部同步或使用CopyOnWriteArrayList)

算法优化

1.获取元素

        先看一下 Node<E> node(int index) 方法,此处先有个印象,后面很多地方会用。由于随机检索是要遍历链表,此处有一个小优化点,判断要查找的索引在链表中的位置,如果在前半部分则从前向后遍历,否则从后向前。

// 获取指定位置的元素
public E get(int index) {
    checkElementIndex(index);
    return node(index).item;
}

// 内部方法:定位到指定位置的节点
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;
    }
}

2. 添加元素

                在链表尾部添加元素

// 在链表尾部添加元素
public boolean add(E e) {
    linkLast(e);
    return true;
}

// 在指定位置插入元素
public void add(int index, E element) {
    checkPositionIndex(index);
    if (index == size)
        linkLast(element);
    else
        linkBefore(element, node(index));
}

3. 删除元素

        是通过遍历链表查询元素,在进行删除,效率差。

// 删除指定位置的元素
public E remove(int index) {
    checkElementIndex(index);
    return unlink(node(index));
}

// 删除第一个出现的指定元素
public boolean remove(Object o) {
    if (o == null) {
        for (Node<E> x = first; x != null; x = x.next) {
            if (x.item == null) {
                unlink(x);
                return true;
            }
        }
    } else {
        for (Node<E> x = first; x != null; x = x.next) {
            if (o.equals(x.item)) {
                unlink(x);
                return true;
            }
        }
    }
    return false;
}

4. Deque 接口实现

        栈,后进先出
            包含下面方法
            push(E e) // 压入栈顶元素,相当于在链表最头添加元素。
            pop() // 弹出栈顶元素,相当于获取并移除头元素。

         队列, 先进先出
            boolean offer(E e) // 在链表尾添加元素。
            E poll() // 获取并删除头元素。
            E peek()  // 获取头元素

    // 作为栈使用(后进先出)
    public void push(E e) { addFirst(e); }
    public E pop() { return removeFirst(); }
    
    // 作为队列使用(先进先出)
    public boolean offer(E e) { return add(e); }
    public E poll() { return (size == 0) ? null : removeFirst(); }
    public E peek() { return (size == 0) ? null : getFirst(); }

       

      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

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

      抵扣说明:

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

      余额充值