文章目录
(一)双向链表:简介
(二)双向链表:clear
(三)双向链表:add
(四)双向链表:remove
(五)双向链表:测试
(六)双向链表:总结
(七)双向链表:源码分析
(一)双向链表:简介

首先增加成员变量,如下:

然后修改node(int index)方法,如下:
private Node<E> node(int index) {
rangeCheck(index);
if (index < (size >> 1)) {
Node<E> node = first;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
} else {
Node<E> node = last;
for (int i = size - 1; i > index; i--) {
node = node.prev;
}
return node;
}
}
(二)双向链表:clear
@Override
public void clear() {
size = 0;
first = null;
last = null;
}
此时节点两两之间互相引用,但是还是会被JVM虚拟机销毁,因为JVM除了看对象是否被引用,还要是否被gc root对象引用

gc root对象之一:被栈指针(局部变量)指向的对象
如果节点间接被gc root对象引用着,也不会被销毁
(三)双向链表:add
头节点的prev和尾节点的next指向的都是null

此时如果想往2号节点的位置添加节点,不需要像之前那样通过node(int index)方法找前一个节点了,直接用prev就可以了
首先让前一位元素(1号节点)的next指向新节点

再让2号节点的prev指向新节点

再让新节点的next指向2号节点,prev指向1号节点,最后调整序号就可以了

初步代码如下:

但是我们还要处理一些特殊情况(往头节点/尾节点的位置添加)

最后考虑只有一个元素的情况,如下:

最开始什么都没有,Node<E> oldLast = last;获取的oldLast为null,后面执行oldLast.next = last;必然会报错

代码如下:

(四)双向链表:remove
假设我们要删除2号节点

首先让前一个结点(1号结点)的next指向后一个结点(3号结点)

再让后一个结点的prev指向前一个结点

此时2号元素没有被引用了,被销毁,最后重新调整序号就可以了

代码如下:

考虑边界情况后的完整代码如下:
(无非就是prev可能是null,next可能是null)

(五)双向链表:测试
测试代码如下:
static void testList(List<Integer> list) {
list.add(11);
list.add(22);
list.add(33);
list.add(44);
list.add(0, 55); // [55, 11, 22, 33, 44]
list.add(2, 66); // [55, 11, 66, 22, 33, 44]
list.add(list.size(), 77); // [55, 11, 66, 22, 33, 44, 77]
list.remove(0); // [11, 66, 22, 33, 44, 77]
list.remove(2); // [11, 66, 33, 44, 77]
list.remove(list.size() - 1); // [11, 66, 33, 44]
Asserts.test(list.indexOf(44) == 3);
Asserts.test(list.indexOf(22) == List.ELEMENT_NOT_FOUND);
Asserts.test(list.contains(33));
Asserts.test(list.get(0) == 11);
Asserts.test(list.get(1) == 66);
Asserts.test(list.get(list.size() - 1) == 44);
System.out.println(list);
}
为了测试方便,修改代码如下:


测试结果如下:
(目前只修改了LinkedList里面的Node内部类的toString()方法)

(六)双向链表:总结


(七)双向链表:源码分析
JDK官方提供的LinkedList跟我们之前写的动态数组很相近,可以自己进去阅读源码

注意:JDK官方提供的LinkedList里面的clear()方法不仅断掉first和last两根线,还断掉了结点之间的线,如下:

目的是为了节省内存,比如在执行clear()方法的同时来了一个迭代器(属于gc root对象)引用最后面一个节点,因为后面的1、2、3节点都连接着,所以不会被销毁,但是迭代器要的只是4号节点

如果把节点之间的线也断掉,效果如下:

无关的节点就会被销毁,如下:

转载:https://blog.csdn.net/qq_42528769/article/details/106853254