Java LinkedList【笔记】

LinkedList

LinkedList 适用于要求有顺序,并且会按照顺序进行迭代的场景,依赖于底层的链表结构

LinkedList基本结构

LinkedList 底层数据结构是一个双向链表

链表每个节点叫做 Node,Node 有 prev 属性,代表前一个节点的位置,next 属性,代表后一个节点的位置

双向链表的头节点(first)的前一个节点是 null

双向链表的尾节点(last)的后一个节点是 null

当链表中没有数据时,first 和 last 是同一个节点,前后指向都是 null

因为是个双向链表,只要机器内存足够强大,是没有大小限制的

链表中的元素叫做 Node,初始化参数的顺序为前一个节点,本身节点值,后一个节点

LinkedList追加节点(新增节点)

在LinkedList追加节点的时候,可以选择追加到链表头部,也可以选择追加到链表尾部,add是默认为尾部追加addfirst是从头部追加

从头部开始追加(add)

简单来说,尾部追加节点只需要把指向位置修改下就行了

具体操作,我们首先需要将尾节点的数据暂时存储起来,然后建立一个新的节点,初始化,需要注意,新节点的前一个节点的值为尾节点值,新增节点的后一个节点为nul,然后将新建的节点追加到尾部,如果链表为空,头部和尾部都是同一个节点,都是新建的节点,否则把前尾节点的下一个节点指向当前尾节点

源码:

void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
从头部追加的方法(addfirst)

将头节点赋值给临时变量,然后新建节点,前一个节点指向null,新建节点的下一个节点的值为头节点的值,然后将新建节点变成头节点,如果头节点为空,那么就是链表为空,头尾节点就是一个节点,此时上一个头节点的前一个节点就指向当前节点

源码:

private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}

通过这两个方法的对比,可以发现头部追加节点和尾部追加节点是非常相像的,前者是移动头节点的 prev 指向,后者是移动尾节点的next指向

LinkedList节点删除

和追加有一些类似,也是可以选择从头部删除或者是从尾部删除,删除的时候会把节点的值以及前后指向节点都变为null,这样有利于垃圾回收(GC)

从头部删除的话,首先我们先拿出头节点的值来作为方法的返回值,拿出头节点的下一个节点来,将前后设为null帮助垃圾回收,然后头节点的下一个节点成为头节点,如果next为空,则说明链表为空,如果链表不为空,则将头节点的下一个节点指向null,然后修改一下链表大小

源码:

private E unlinkFirst(Node<E> f) {
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null;
first = next;
if (next == null)
last = null;
null
else
next.prev = null;
size--;
modCount++;
return element;
}

可以发现,链表结构的节点新增和删除都只需要将前后节点的指向修改下就可以,这说明LinkedList的新增和删除速度很快

LinkedList节点查询

链表的查询是比较慢的,而在LinkedList中进行节点查询不是按照从头循环到尾的方法,而是用的简单二分法,先看index是在链表的前半部分还是后半部分,如果是前半边,就从头找,如果是后半边,就从尾找,这样可以提高一些性能,而且因为链表的性质,即只能从第一个或者最后一个去访问其他的元素,所以简单二分法已经是最优解了

源码:

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

LinkedList中的接口的新增方法

LinkedList迭代器

LinkedList使用ListIterator迭代接口来实现双向的迭代访问,这个接口提供了向前以及向后的迭代方法

从头到尾的方向的迭代

首先判断一下有没有下一个元素,如果下一个节点的索引小于链表的大小,那么就说明有下一个元素,然后我们取一个元素,看一下版本号有无变化,然后再检查一遍,next是当前的节点,在上一次执行next()方法的时候被赋值的,如果是第一次执行,那么就是在初始化迭代器的时候被赋值的,然后next是下一个节点,为下一次的迭代做准备

源码:

public boolean hasNext() {
return nextIndex < size;
} public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}
从尾到头的迭代

首先我们要确定上次节点的索引位置,如果上次节点索引位置大于0,那么就代表有节点可以迭代,然后我们取前一个节点,同样检查版本号,在next为空的时候,有两个可能,第一个,说明这是第一次迭代,取尾节点,第二个,上次操作的时候把尾节点删掉了,而在next不为空的时候,这就说明已经发生过迭代,直接去前一个节点就可以了,然后改变索引位置

源码:

public boolean hasPrevious() {
return nextIndex > 0;
} public E previous() {
checkForComodification();
if (!hasPrevious())
throw new NoSuchElementException();
(next.prev)
lastReturned = next = (next == null) ? last : next.prev;
nextIndex--;
return lastReturned.item;
}

一些问题:

ArrayList 和 LinkedList 有何异同?

不同:

底层数据结构方面

ArrayList 底层是数组

LinkedList 底层是双向链表

应用场景方面

ArrayList 更适合于快速的查找匹配,不适合频繁新增删除

LinkedList 更适合于经常新增和删除,对查询反而很少的场景

相同:

最大容量

ArrayList 有最大容量的,为 Integer 的最大值,大于这个值 JVM 是不会为数组分配内存空间的

LinkedList 底层是双向链表,理论上可以无限大,但是实际上,LinkedList 实际大小用的是 int 类型,这也说明了 LinkedList 不能超过 Integer 的最大值,不然会溢出

** null 值**

ArrayList 允许 null 值新增,也允许 null 值删除

LinkedList 新增删除时对 null 值没有特殊校验,是允许新增和删除的。

线程安全

当两者作为非共享变量时,比如说仅仅是在方法里面的局部变量时,是没有线程安全问题的,只有当两者是共享变量时,才会有线程安全问题

Java LinkedList【笔记】的更多相关文章

  1. Java开发笔记(六十七)清单:ArrayList和LinkedList

    前面介绍了集合与映射两类容器,它们的共同特点是每个元素都是唯一的,并且采用二叉树方式的类型还自带有序性.然而这两个特点也存在弊端:其一,为啥内部元素必须是唯一的呢?像手机店卖出了两部Mate20,虽然 ...

  2. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  3. 20145330第五周《Java学习笔记》

    20145330第五周<Java学习笔记> 这一周又是紧张的一周. 语法与继承架构 Java中所有错误都会打包为对象可以尝试try.catch代表错误的对象后做一些处理. 使用try.ca ...

  4. Java学习笔记4

    Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...

  5. Java开发笔记(序)章节目录

    现将本博客的Java学习文章整理成以下笔记目录,方便查阅. 第一章 初识JavaJava开发笔记(一)第一个Java程序Java开发笔记(二)Java工程的帝国区划Java开发笔记(三)Java帝国的 ...

  6. Java开发笔记(七十)Java8新增的几种泛型接口

    由于泛型存在某种不确定的类型,因此很少直接运用于拿来即用的泛型类,它更经常以泛型接口的面目出现.例如几种基本的容器类型Set.Map.List都被定义为接口interface,像HashSet.Tre ...

  7. JAVA自学笔记15

    JAVA自学笔记15 @例题1:共有5个学生,请把五个学生的信息存储到数组中,并遍历数组,并获取每个学生的信息 Students[] students=new Student[5]; Student ...

  8. JAVA自学笔记19

    JAVA自学笔记19 1.集合总结 Collection(单列集合) List(有序可重复) ArrayList:底层数据结构是数组 ,查询快,增删慢.线程不安全,效率高 Vector:底层数据结构是 ...

  9. JAVA自学笔记17

    JAVA自学笔记17 1.Map接口 1)概述 将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值.可以存储键值对的元素 2)与Collection接口的不同: ①Map是双列的 ...

随机推荐

  1. 资源:Kafka消息队列下载路径

    Kafka下载路径 http://kafka.apache.org/downloads.html

  2. Redis:redis.conf配置文件 - 及配置详解

    配置文件详解(文章最后有完整的redis.conf文件) ###################################  NETWORK  ######################### ...

  3. Java:Java的重写与重载区分

    最明显的区别为:重写只存在于子类与父类中,重载存在于一个类中. 具体区别如下: 一.重写(override) override是重写(覆盖)了一个方法,以实现不同的功能.一般是用于子类在继承父类时,重 ...

  4. SoapUI Pro 最新版本和最新功能

    专为整个后端的端到端测试而构建 创建全面的端到端测试,以从API定义或实时端点验证API的整个工作流程.只需单击几下即可传递响应数据并添加断言-无需编码. 综合生成或配置数据 通过简单的数据驱动测试来 ...

  5. Java Lambda 表达式你会用吗?

    先看再点赞,给自己一点思考的时间,如果对自己有帮助,微信搜索[程序职场]关注这个执着的职场程序员.我有什么:Java技能,面试经验指导,简历优化,职场规划指导,技能提升方法,讲不完的职场故事,个人成长 ...

  6. tableview折叠动效

    缘起于看见书旗小说的列表有点击折叠的动效,觉得十分炫酷.想了三分钟,不知道怎么写.晚上百度了下,知道了大致流程,于是自己实现了下,发现不少坑,于是写下这篇博文 实现原理: 1 tableview ce ...

  7. 计算机基础 | 文档神器docsify安装及基本使用

    为啥要用docsify? 神器Docsify让你的文档变得美观,配合typora,从此爱上看文档,各种优点:小巧.快速.美观.方便.快捷.上手快,可以浏览如下优秀案例 ve-charts pyecha ...

  8. C语言:位运算符

    异或        ^     两个二进制位相同结果为0:不相同结果为1              1^1=0    1^0=1   0^1=1  0^0=1 按位或    |      两个二进制位 ...

  9. 1.在配置XML文件时出现reference file contains errors (http://www.springframework.org/schema/beans/...解决方案

    解决方案: 第一步:将 Preferences > XML > XML Files > Validation中"Honour all XML schema location ...

  10. springMVC-5-视图解析器

    视图和视图解析器工作流程 第一步:获取到ModelAndView对象 请求处理方法执行完成后,无论返回是String,View 还是 ModeMap 类型,Spring MVC 也会在内部将它们装配成 ...