Debug LinkedList
Debug LinkedList源码
前置知识
- LinkedList基于链表,LinkedList的Node节点定义
成员变量
//链表中元素的数量
transient int size = 0; /**
* 链表的头节点:用于遍历
*/
transient Node<E> first; /**
* 链表的尾节点:用于添加元素
*/
transient Node<E> last;
2.1 Debug 分析第一个元素是如何进入链表的
编写测试代码,打上断点:
进入方法内部:
- add方法默认添加到链表的尾部
- 该方法等同于addLast(区别就是add方法需要返回一个true,而addLast没有任何返回值)
进入linkLast方法内部:
/**
* 当前方法执行完后,若添加的节点为第一个节点,链表的last和first都指向新节点
*/
void linkLast(E e) {
//获取到链表的最后一个元素
final Node<E> l = last;
//创建一个节点,前一个节点为当前链表的last,后一个节点为空
final Node<E> newNode = new Node<>(l, e, null);
//修改last为新添加的节点
last = newNode;
//若链表为空,first节点为新添加的节点,否则添加前最后一个节点的next指向新节点
if (l == null)
first = newNode;
else
l.next = newNode;
//链表长度加一
size++;
//链表修改次数加1
modCount++;
}
//=================================================================
Node带三个参数的构造函数:
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
2.2 Debug 分析如何通过下标插入指定位置add(index,e)
编写测试用例:
进入方法内部:
public void add(int index, E element) {
//检查下标是否合法:大于等于0小于等于size【return index >= 0 && index <= size;】
checkPositionIndex(index);
//若等于size,相当于在链表尾部添加节点
if (index == size)
linkLast(element);
else
//linkBefore中的Before指的是传入索引元素前
linkBefore(element, node(index));
}
进入node(index)方法:返回索引为index的元素
Node<E> node(int index) {
// assert isElementIndex(index);
//查找元素的思路是遍历一半,先折半分区,然后若在小于折半的区域就从first开始往后遍历,反之从last往前遍历
//右移一位相当于除以2
if (index < (size >> 1)) {
//获取到first节点
Node<E> x = first;
//从first遍历到index的位置
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
//获取到next的节点
Node<E> x = last;
//从last往前遍历到index的位置
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
回到linkBefore方法:
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
//获取index节点的上一个节点
final Node<E> pred = succ.prev;
//创建新节点,下一个节点指向index节点,上一个节点指向index节点的上一个节点
final Node<E> newNode = new Node<>(pred, e, succ);
//index节点的上一个节点指向变为指向新节点
succ.prev = newNode;
//**若index节点的头节点为空,相当于从头部插入节点,直接将新节点赋给first节点
if (pred == null)
first = newNode;
else
//index的上一个节点的下一个节点指向改为新节点
pred.next = newNode;
//节点长度+1
size++;
//链表修改次数+1
modCount++;
}
2.3 Debug 分析如何通过下标获取指定元素
编写测试代码,打上断点:
进入get方法内部:
public E get(int index) {
//检查下标范围
checkElementIndex(index);
//遍历一半,返回节点的值
return node(index).item;
}
LinkedList支持的查询除了通过下标获取外,还支持getLast和getFirst
get(0)和getFirst时间复杂度有区别吗?
理论上来说,getFirst和getLast都是直接获取到节点,时间复杂度为O(1),而通过get(index)方法查询节点,都会折半后遍历一半的元素,时间复杂度为O(n)。但实际情况下,for循环遍历的第一个元素就100%是头节点或尾节点,不会进入之后的循环,实际运行的也是O(1)。
2.4 Debug 分析如何通过下标删除元素
打上断点:
进入方法内部:
public E remove(int index) {
//检查下标范围
checkElementIndex(index);
//node(index)获取需要删除的节点,折半遍历
return unlink(node(index));
}
进入unlink方法内部:
删除中间元素的过程图:
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) {
//若删除的节点为头节点,将当前节点的下一个节点赋值给first节点
first = next;
} else {
//若删除的节点为中间节点,将当前节点的上一个节点的下一个节点指向变为当前节点的下一个节点(step1)
prev.next = next;
//当前节点的上一个节点指向置为null(step2)
x.prev = null;
}
if (next == null) {
//若删除的节点为尾节点,将当前节点的上一个节点赋给last
last = prev;
} else {
//若删除的节点为中间节点,将当前节点的下一个节点的上一个节点指向变为当前节点的上一个节点(step3)
next.prev = prev;
//当前节点的下一个节点指向置为null(step4)
x.next = null;
}
//节点元素内容置为空
x.item = null;
//链表长度-1
size--;
//链表修改次数+1
modCount++;
//返回删除节点内容
return element;
}
2.5 Debug 分析如何通过对象删除节点(内容)
public boolean remove(Object o) {
//若节点为null,从first往下遍历(说明LinkedList是允许为空值的,并且允许多个)
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
}
//若节点不为空,遍历链表后删除节点
else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
Debug LinkedList的更多相关文章
- jmeter sampler maven项目排错记
eclipse 创建的maven项目,引入jar包之后出现红色叹号,一直找不到原因,连main方法都无法运行,提示找不到类: 错误: 找不到或无法加载主类 soapsampler.SoapSample ...
- Java集合框架源码分析(2)LinkedList
链表(LinkedList) 数组(array)和数组列表(ArrayList)都有一个重大的缺陷: 从数组的中间位置删除一个元素要付出很大的代价,因为数组中在被删除元素之后的所有元素都要向数组的前端 ...
- java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE 的理解
[2013-12-06 11:06:21,715] [C3P0PooledConnectionPoolManager[identityToken->2tl0n98y1iwg7cbdzzq7a|7 ...
- Java总结 - List实现类ArrayList&LinkedList
本文是根据源码进行学习的,如果我有什么理解不对的地方请多指正,谢谢您 上面基本就是List集合类的类图关系了,图中省略掉了比如Cloneable等标记接口,那么List分别具体的主要实现类有:Arra ...
- 【Java源码】集合类-LinkedList
一.类继承关系 LinkedList和ArrayList都实现了List接口.所以有List的特性,同时LinkedList也实现了Deque,所以它也具有双端队列和栈的特性. public clas ...
- DEBUG ArrayList
1,ArrayList面试必问 说说ArrayList和LinkedList的区别? ArrayList基于数组实现,LinkedList基于链表实现,不同的数据结构决定了ArrayList查询效率比 ...
- Debug HashMap
目录 1,HashMap面试必问 2,Debug源码的心得体会 3,JDK 1.7 3.1 用debug分析一个元素是如何加入到HashMap中的[jdk1.7] 3.2 用debug分析HashMa ...
- Java自学第6期——Collection、Map、迭代器、泛型、可变参数、集合工具类、集合数据结构、Debug
集合:集合是java中提供的一种容器,可以用来存储多个数据. 集合和数组既然都是容器,它们有啥区别呢? 数组的长度是固定的.集合的长度是可变的. 数组中存储的是同一类型的元素,可以存储基本数据类型值. ...
- 记一次debug记录:Uncaught SyntaxError: Unexpected token ILLEGAL
在使用FIS3搭建项目的时候,遇到了一些问题,这里记录下. 这里是发布搭建代码: // 代码发布时 fis.media('qa') .match('*.{js,css,png}', { useHash ...
随机推荐
- 前端日常工作中常用开发小技巧 ---JavaScript
1.格式化金钱值 const ThousandNum = num => num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "," ...
- .NET 开源工作流: Slickflow流程引擎高级开发(七)--消息队列(RabbitMQ)的集成使用
前言:工作流流程过程中,除了正常的人工审批类型的节点外,事件类型的节点处理也尤为重要.比如比较常见的事件类型的节点有:Timer/Message/Signal等.本文重点阐述消息类型的节点处理,以及实 ...
- Linux虚拟机下安装Oracle 11G教程图文解说
1.安装环境 操作系统:Red hat 6.5 内存:内存最低要求256M (使用:grep MemTotal /proc/meminfo 命令查看) 交换空间:SWAP交换空间大小根据内存大小决定( ...
- wsl环境下配置ubuntu16.04
wsl环境下配置ubuntu16.04 在公司同事的安利下,终于给自己用了8年的老笔记本(戴尔XPS L502X)换上了固态硬盘(WD500G,SATA3接口) 当然,系统重装了一遍,所有的软件也都没 ...
- 关于数据文件的文件头1-P2
文章目录 1 疑问点 2 问题模拟 2.1 dump 0,1块 2.2 查看trc文件 2.3 如何查看 1 疑问点 这里引用p2处的一段话: 事实上,每个文件的前128个块,都是文件头,被Oracl ...
- HTTPS协议详解(三):PKI 体系
转自:https://blog.csdn.net/hherima/article/details/52469488 1.RSA身份验证的隐患 身份验证和密钥协商是TLS的基础功能,要求的前提是合 ...
- 从0开始,手把手教你开发并部署上线一个知识测验微信小程序
上线项目演示 微信搜索[放马来答]或扫以下二维码体验: 项目源码 项目源码 其他版本 Vue答题App实战教程 Hello小程序 1.注册微信小程序 点击立即注册,选择微信小程序,按照要求填写信息 2 ...
- CSS(二)- 选择器 - 伪元素和伪类(思维导图)
伪元素 伪元素可以创建一些文档语言无法创建的虚拟元素.比如:文档语言没有一种机制可以描述元素内容的第一个字母或第一行,但伪元素可以做到(::first-letter.::first-line).同时, ...
- 02 drf源码剖析之快速了解drf
02 drf源码剖析之快速了解drf 目录 02 drf源码剖析之快速了解drf 1. 什么是drf 2. 安装 3. 使用 3. DRF的应用场景 1. 什么是drf drf是一个基于django开 ...
- Hello!GitHub 好用好玩值得收藏的开源项目集合~
这是我许久以来从各处发现的极佳开源项目,希望分享给大家~ 如果帮到你了,给我个赞好嘛 编程语言类 ️learn-go-with-tests(通过单元测试学Go) GitHub地址:https://gi ...