LinkedList源码解读—Java8版本(中)

简介: LinkedList源码解读—Java8版本(中)

四、域的解读


  // LinkedList节点个数
    transient int size = 0;
    /**
     * Pointer to first node. 指向头结点
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;
    /**
     * Pointer to last node.  指向尾节点
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;


LinkedList内部有两个引用,一个first,一个last,分别用于指向链表的头和尾,另外有一个size,用于标识这个链表的长度,而它的接的引用类型是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;
        }
    }


Node 类是LinkedList中的私有内部类,LinkedList中就是通过Node来存储集合中的元素。


E :节点的值。


Node next:当前节点的后一个节点的引用(可以理解为指向当前节点的后一个节点的指针)


Node prev:当前节点的前一个节点的引用(可以理解为指向当前节点的前一个节点的指针)


五、构造方法


LinkedList提供了两个构造器,ArrayList比它多提供了一个通过设置初始化容量来初始化类。


LinkedList不提供该方法的原因:因为LinkedList底层是通过链表实现的,每当有新元素添加进来的时候,都是通过链接新的节点实现的,也就是说它的容量是随着元素的个数的变化而动态变化的。而ArrayList底层是通过数组来存储新添加的元素的,所以我们可以为ArrayList设置初始容量(实际设置的数组的大小)。


相关阅读:【手撕源码系列】ArrayList源码解读—Java8版本


5.1 空参构造函数

/**
     * Constructs an empty list.
     */
    public LinkedList() {
    }


5.2 collection参数构造函数

  public LinkedList(Collection<? extends E> c) {
          this();
          // 将集合添加到链表中去
          addAll(c);
      }
  public boolean addAll(Collection<? extends E> c) {
      // 从链表尾巴开始集合中元素
          return addAll(size, c);
      }
   public boolean addAll(int index, Collection<? extends E> c) {
      // 1.添加位置的下标的合理性检查
        checkPositionIndex(index);
      // 2.将集合转换为Object[]数组对象
        Object[] a = c.toArray();
        int numNew = a.length;
        if (numNew == 0)
            return false;
    // 3.得到插入位置的前继节点和后继节点
        Node<E> pred, succ;
        if (index == size) {
          // 从尾部添加的情况:前继节点是原来的last节点;后继节点是null
            succ = null;
            pred = last;
        } else {
           // 从指定位置(非尾部)添加的情况:前继节点就是index位置的节点,后继节点是index位置的节点的前一个节点
            succ = node(index);
            pred = succ.prev;
        }
    // 4.遍历数据,将数据插入
        for (Object o : a) {
            @SuppressWarnings("unchecked") E e = (E) o;
            // 创建节点
            Node<E> newNode = new Node<>(pred, e, null);
            if (pred == null)
              // 空链表插入情况:
                first = newNode;
            else
              // 非空链表插入情况:
                pred.next = newNode;
            // 更新前置节点为最新插入的节点(的地址)
            pred = newNode;
        }
        if (succ == null) {
          // 如果是从尾部开始插入的,则把last置为最后一个插入的元素
            last = pred;
        } else {
          // 如果不是从尾部插入的,则把尾部的数据和之前的节点连起来
            pred.next = succ;
            succ.prev = pred;
        }
        size += numNew;  // 链表大小+num
        modCount++;  // 修改次数加1
        return true;
    }


六、核心方法


6.1 List接口

6.1.1 add(E e)方法

  // 作用:将元素添加到链表尾部
    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节点也为需要插入的节点。(也就是说:该节点既是头节点first也是尾节点last)
            first = newNode;
        else
          // 不是空链表的情况:将原来的尾部节点(现在是倒数第二个节点)的next指向需要插入的节点
            l.next = newNode;
        size++; // 更新链表大小和修改次数,插入完毕
        modCount++;
    }
相关文章
|
28天前
|
Kubernetes jenkins 持续交付
从代码到k8s部署应有尽有系列-java源码之String详解
本文详细介绍了一个基于 `gitlab + jenkins + harbor + k8s` 的自动化部署环境搭建流程。其中,`gitlab` 用于代码托管和 CI,`jenkins` 负责 CD 发布,`harbor` 作为镜像仓库,而 `k8s` 则用于运行服务。文章具体介绍了每项工具的部署步骤,并提供了详细的配置信息和示例代码。此外,还特别指出中间件(如 MySQL、Redis 等)应部署在 K8s 之外,以确保服务稳定性和独立性。通过本文,读者可以学习如何在本地环境中搭建一套完整的自动化部署系统。
56 0
|
1月前
|
Java 中间件 测试技术
java依赖冲突解决问题之jar包版本冲突无法通过升降级解决时如何解决
java依赖冲突解决问题之jar包版本冲突无法通过升降级解决时如何解决
|
1月前
|
Java 应用服务中间件 Windows
【应用服务 App Service】App Service 中部署Java项目,查看Tomcat配置及上传自定义版本
【应用服务 App Service】App Service 中部署Java项目,查看Tomcat配置及上传自定义版本
|
14天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
160 37
|
1天前
|
数据采集 运维 前端开发
【Java】全套云HIS源码包含EMR、LIS (医院信息化建设)
系统技术特点:采用前后端分离架构,前端由Angular、JavaScript开发;后端使用Java语言开发。
12 5
|
1天前
|
Java
|
9天前
|
机器学习/深度学习 数据采集 JavaScript
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
ADR药品不良反应监测系统是一款智能化工具,用于监测和分析药品不良反应。该系统通过收集和分析病历、处方及实验室数据,快速识别潜在不良反应,提升用药安全性。系统采用Java开发,基于SpringBoot框架,前端使用Vue,具备数据采集、清洗、分析等功能模块,并能生成监测报告辅助医务人员决策。通过集成多种数据源并运用机器学习算法,系统可自动预警药品不良反应,有效减少药害事故,保障公众健康。
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
|
23天前
|
Java API 开发工具
Java不同的版本
Java不同的版本Java不同的版本
33 4
|
23天前
|
Java API 开发工具
Java版本
Java版本
29 2
|
1月前
|
存储 消息中间件 Java
何时在 Java 中使用 ArrayList 和 LinkedList
【8月更文挑战第23天】
12 2