LinkedList源码简单分析

本文深入分析了LinkedList的源码,探讨其作为双链表实现的List和Deque接口,重点介绍了其内部结构、构造方法及主要操作如添加、删除、获取元素的实现原理。

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

LinkedList源码简单分析

一. 简介

LinkedList是实现了List和Deque接口的双链表,它实现了List接口的所有可选的方法,允许添加所有的元素,包括null。LinkedList还实现了Cloneable和Serializable接口,所以它还具有可复制和序列化的能力。与ArrayList相比,LinkedList的底层是基于链表,所以在数据的插入和删除方面性能要优于ArrayList,但在随机访问方面ArrayList的性能更好。

二. 属性

2.1 LinkedList基本属性

2.1.1 first

/**
 * Pointer to first node.
 * Invariant: (first == null && last == null) ||
 *            (first.prev == null && first.item != null)
 */
 transient Node<E> first;
  • first链表的头指针,指向第一个结点

2.1.2 last

/**
 * Pointer to last node.
 * Invariant: (first == null && last == null) ||
 *            (last.next == null && last.item != null)
 */
 transient Node<E> last;
  • last链表的尾指针,指向最后一个结点

2.1.3 size

transient int size = 0;
  • 链表的长度

2.2 LinkedLink内部类Node属性

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;
    }
}

2.2.1 item

  • LinkedList中的数据是存储在节点上的,item就是存储数据的地方。(LinkedList本质跟链表一样)

2.2.2 next

  • next,储存下一个节点的指针(地址),如果是最后一个就设置为null。

2.2.3 prev

  • prev,存储上一个结点的指针,如果是头结点就置为null

三. 构造方法

3.1 无参构造

/**
 * Constructs an empty list.
 */
 public LinkedList() {}
  • 构建一个空列表
  • first和last都为null,size长度等于0

3.2 有参构造

在这里插入图片描述

  • 构建一个包含指定集合元素的链表,通过集合的迭代器将元素返回
  • 首先调用无参构造this()
  • 然后调用addAll©方法

四. 主要的操作方法

4.1 addAll©

在这里插入图片描述

  • 该方法默认将集合c中的元素追加到LinkedList链表的最后面

4.2 node(index)

在这里插入图片描述

  • 通过指定的元素下标,返回结点
  • index < (size >> 1),使用折半查找的算法查询结点,快速检索,提高性能。

addAll(index, c)

在这里插入图片描述

  • 调用checkPositionIndex方法,检查下标是否越界。

  • toArray,将集合转化为数组a。

  • numNew,数组a的长度,如果长度等于零,下面操作没有意义,直接返回false。

  • 接下来的if/else包含的代码块,主要作用就是判断数组a中的所有元素添加的位置。

    • index==size,数组中的元素追加到链表(LinkedList)的末端。

      • 尾指针赋值给pred,succ=null。
    • 0<=index<size,数组中的元素插入到链表的任意位置(除了末端)。

      • 通过node方法找到该索引所在的结点,返回值赋值给succ。

      • 将succ结点的prev指针域的值赋值给pred。
        在这里插入图片描述

        • 集合c中的所有元素将会在pred和succ中间插入
          在这里插入图片描述
  • for循环就是将数组a中的所有元素封装成Node结点,根据不同的情况,依次链接到链表上(linkedList)

  • 最后链表的长度加上数组a的大小numNew,操作数modCount加一

4.4 add(E e)

在这里插入图片描述

  • 调用add(E e)实际上是在调用linkLast(E e)
  • linkLast方法,默认将新添加的元素,放在最后面末端
  • l==null,意味着当前链表是空链表,新添加的结点是头结点,相反,将新结点指针连接到尾结点的next指针域。
  • 最后链表长度加一,操作数加一

4.5 add(index, element)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 调用add(index, element)方法,首先需要检查索引是否越界。
  • 如果index==size,元素添加到末端,直接调用linkLast方法。
  • 元素添加到其他地方,直接调用linkBefore方法
    • 首先通过Node方法,找到要被替换位置的结点。
    • 根据插入的位置(头部或中间部分)不同,插入结点的方式也不同。

4.6 remove(Object o

在这里插入图片描述

  • remove(Object o)删除节点的大致过程是:
    • 先遍历整个链表,根据条件找到要被删除的结点
    • 调用unlink方法
      在这里插入图片描述
      • 该方法根据被删除结点所处的位置(头结点,尾结点)不同,操作也不同
        • 处在头结点:先将头指针指向被删除结点的下一个结点,然后将该节点的prev指针域置为null
        • 处在尾结点:先将被删除结点的上一个结点的next的指针域置为null,被删除结点的prev指针域也置为null,最后让链表的尾指针指向被删除结点的前一个结点。
        • 将被删除结点的数据域item置为null
        • 链表大小减一,操作数加一
    • 因为LinkedList链表可以添加null,所以remove方法中有两种情况(o==null || o!=null)。

4.7 remove(index)

在这里插入图片描述

  • 根据下标删除结点很简单,直接调用unlink方法将结点移除,当然首先还是要检查下标是否越界

4.8 get(index)

在这里插入图片描述

  • get方法也很简单,直接调用node()方法通过下标找到结点,然后返回结点数据域的值。

五. 感谢

  • 本篇笔记是我看了微信公众号好好学java中的文章写出来的,内容的当然没有大佬写的那么详细和有条理,所以大家如果有兴趣可以去订阅一下。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值