LinkedList的深入理解(学习)

本文详细剖析了Java集合框架中的LinkedList源码,包括其原理、核心方法和迭代器实现,对比了与ArrayList的不同之处,提供了对LinkedList底层实现的全面理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先申明一下,此篇文章仅仅是我个人学习ArrayList源码后的学习总结,如果有错误,可以提出来探讨。

1.1    原理

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
  //核心节点,
    private transient Entry<E> header = new Entry<E>(null, null, null);
    private transient int size = 0;

   //节点实体
    private static class Entry<E> {
E element;
Entry<E> next;
Entry<E> previous;


Entry(E element, Entry<E> next, Entry<E> previous) {
   this.element = element;
   this.next = next;
   this.previous = previous;
}
    }

从结构上讲,是通过双向链表的形式实现。其实最关键的是那个heade对象。它才是整个LinkedList的核心。它是连接链表的开始和结束的关键节点。通过它可以向前,向后操作。

1.2    核心方法(都是私有)

1.2.1  AddBefore()

这个方法是所有的插入方法的核心,包括所以的add方法(除了addAll()),所有offer方法

源码:

private Entry<E> addBefore(E e, Entry<E> entry) {

//创建链路的节点,除了自己本身,还包括前置节点,后置节点。

    Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);

    //修改前一个节点的的后置节点指向它

    newEntry.previous.next = newEntry;

     //修改后一个节点的的前置节点指向它

    newEntry.next.previous = newEntry;

    size++;

    modCount++;//用于线程安全。

    return newEntry;

}

1.2.2  Entry(int index)

    private Entry<E> entry(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException("Index: "+index+
                                                ", Size: "+size);
        Entry<E> e = header;
        if (index < (size >> 1)) {
            for (int i = 0; i <= index; i++)
                e = e.next;
        } else {
            for (int i = size; i > index; i--)
                e = e.previous;
        }
        return e;
    }

此方法可以通过index获得对应的节点。主要用于方法参数中有index的方法,如get,remove;

从代码上看,通过index获得对应的节点,有两个方式,如果index在整条链路的前半截,那么是从前向后遍历,反之,从后往前遍历。

 

1.2.3  remove(Entry<e> entry)

    private E remove(Entry<E> e) {
if (e == header)
   throw new NoSuchElementException();


        E result = e.element;
e.previous.next = e.next;
e.next.previous = e.previous;
        e.next = e.previous = null;
        e.element = null;
size--;
modCount++;
        return result;
    }

此方法是删除操作的核心方法。主要用于删除方法,如:remove(int),remove(Object),

removeFirst(),removeLast();

 


 

1.3    迭代器

只提供一种迭代器(ListItr,不同于ArrayList的ListItr)

在ArrayList的Itr迭代器中,采用的维护cursor指向来遍历数组,而LinkedList是通过维护nextIndex和节点next来遍历链表。

 

通过参数index可以自定义遍历的开始位置(任意位置),

 

这个构造方法通过传入的index维护nextIndex指针和next节点,

public boolean hasNext() {

        returnnextIndex != size;

    }

 

    public E next() {

       checkForComodification();

        if (nextIndex ==size)

       throw new NoSuchElementException();

 

        lastReturned = next;

        next = next.next;

        nextIndex++;

        returnlastReturned.element;

    }

 

    public boolean hasPrevious() {

        returnnextIndex != 0;

    }

 

    public E previous() {

        if (nextIndex == 0)

       throw new NoSuchElementException();

 

        lastReturned = next = next.previous;

        nextIndex--;

       checkForComodification();

        returnlastReturned.element;

    }

 

    public int nextIndex() {

        returnnextIndex;

    }

 

    public int previousIndex() {

        returnnextIndex-1;

    }

 

    public void remove() {

            checkForComodification();

            Entry<E> lastNext = lastReturned.next;

            try {

                LinkedList.this.remove(lastReturned);

            } catch (NoSuchElementException e) {

                throw new IllegalStateException();

            }

        if (next==lastReturned)

                next = lastNext;

            else

       nextIndex--;

        lastReturned = header;

        expectedModCount++;

    }

 

    public void set(E e) {

        if (lastReturned ==header)

       throw new IllegalStateException();

       checkForComodification();

        lastReturned.element = e;

    }

 

    public void add(E e) {

        checkForComodification();

        lastReturned = header;

        addBefore(e, next);

        nextIndex++;

        expectedModCount++;

    }

 

    final void checkForComodification() {

        if (modCount !=expectedModCount)

       throw new ConcurrentModificationException();

    }

 

从源码上看,跟ArrayList的ListItr迭代器很类似,只是具体的实现有点差异。

2        ArrayList和LinkedList的总结

查询操作:ArrayList可以通过下标找到对应位置的值,效率高;而LinkedList需要向前或向后遍历才能找到对应的值,效率低。

插入和删除操作:ArrayList需要数据的迁移所以效率低。LinkedList需要查询到对应的节点,才能直接操作(不需要数据的迁移),相对来说,效率高。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值