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++;
    }
相关文章
|
21天前
|
XML Java 编译器
Java注解的底层源码剖析与技术认识
Java注解(Annotation)是Java 5引入的一种新特性,它提供了一种在代码中添加元数据(Metadata)的方式。注解本身并不是代码的一部分,它们不会直接影响代码的执行,但可以在编译、类加载和运行时被读取和处理。注解为开发者提供了一种以非侵入性的方式为代码提供额外信息的手段,这些信息可以用于生成文档、编译时检查、运行时处理等。
59 7
|
1月前
|
数据采集 人工智能 Java
Java产科专科电子病历系统源码
产科专科电子病历系统,全结构化设计,实现产科专科电子病历与院内HIS、LIS、PACS信息系统、区域妇幼信息平台的三级互联互通,系统由门诊系统、住院系统、数据统计模块三部分组成,它管理了孕妇从怀孕开始到生产结束42天一系列医院保健服务信息。
32 4
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
77 2
|
14天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
79 13
|
27天前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
54 12
|
22天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
1月前
|
人工智能 监控 数据可视化
Java智慧工地信息管理平台源码 智慧工地信息化解决方案SaaS源码 支持二次开发
智慧工地系统是依托物联网、互联网、AI、可视化建立的大数据管理平台,是一种全新的管理模式,能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。围绕施工现场管理的人、机、料、法、环五大维度,以及施工过程管理的进度、质量、安全三大体系为基础应用,实现全面高效的工程管理需求,满足工地多角色、多视角的有效监管,实现工程建设管理的降本增效,为监管平台提供数据支撑。
45 3
|
1月前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
23天前
|
人工智能 移动开发 安全
家政上门系统用户端、阿姨端源码,java家政管理平台源码
家政上门系统基于互联网技术,整合大数据分析、AI算法和现代通信技术,提供便捷高效的家政服务。涵盖保洁、月嫂、烹饪等多元化服务,支持多终端访问,具备智能匹配、在线支付、订单管理等功能,确保服务透明、安全,适用于家庭生活的各种需求场景,推动家政市场规范化发展。
|
1月前
|
运维 自然语言处理 供应链
Java云HIS医院管理系统源码 病案管理、医保业务、门诊、住院、电子病历编辑器
通过门诊的申请,或者直接住院登记,通过”护士工作站“分配患者,完成后,进入医生患者列表,医生对应开具”长期医嘱“和”临时医嘱“,并在电子病历中,记录病情。病人出院时,停止长期医嘱,开具出院医嘱。进入出院审核,审核医嘱与住院通过后,病人结清缴费,完成出院。
100 3