#JDK成长笔记6:LinkedList的五脏六腑你了解吗?
时间:2023-04-01 18:25:48
Java
上一节,你看过LinkedList的add方法的源码,脑洞大开了吗?其实核心原理就是辅助指针+Node双向链表数据结构。相信经过前面的学习,大家应该已经热身完毕了,后面的学习会让我们提速。去!去!在本节中,您还需要深入到LinkedList的其他方法,探索它们的底层原理。学完这节,你就可以自己写一个LinkedList,甚至可以类比写一个单向链表的List,反向单向链表等等。您还可以克服链表的许多算法问题。当面试问到ArrayList和LinkedList的时候,相信你会信手拈来。让我们一起开始吧!另一个add(intindex,Ee)方法另一个add(intindex,Ee)方法
有了之前的经验,相信现在你不需要我一步步给你展示源码原理了。我直接用核心源码+配图的方式给大家讲解原理。你要按照我的想法自己看源码,自己画图告诉别人是最好的学习方式。我们先来看另一个add方法,在某个位置添加一个元素。核心源码示意图如下:从add方法源码的脉络可以看出,在调用add方法时,会根据要插入的位置的索引。如果和上一节提到的普通add(Ee)方法一样,调用的是linkLast方法。主要区别是当没有向尾节点添加元素时调用linkBefore方法。linkBefore的核心是通过node(intindex)来定位元素。如下图所示:首先看源码的脉络,核心是一个if和两个for循环。再看细节,if条件是什么意思?如图,右移1,类似于除以2,类似于二分法的思想。然后for循环开始通过x.next或者x.prev从前面或者从后面到前面查找元素。是这个思路,还是不错的亮点,很多时候算法会有二分法,或者分而治之的思路。index位置的元素被node方法确认后,开始执行linkBefore方法。如下图所示:上面的源码上下文主要分为三个步骤。可以按照如下思路:1.将上一个节点定位的元素记录为succ传入,用一个辅助指针pred指向定位元素的上一个节点。2、然后创建一个newNode,它的prev指针指向pred所在的位置,tail指针指向succ,也就是要定位的元素。3、最后修改定位元素的prev指针指向新元素,修改pred位置的元素tail指针指向新元素。最后就会形成上面的结果。其实你可以发现,和linkLast很相似,linkLast是使用辅助指针l指向last来帮助在末尾添加节点。而linkBefore是通过,先定位元素后,利用定位元素的prev的前一个节点作为辅助插入元素。只要记住这个思路,你就可以自己写两个add方法了。删除系列方法
删除系列方法 链表的删除方法,大部分都非常相似,都是一些指针的转换。最好的分析方法是画图。相信到这里,你已经掌握了分析源码的基本方法和方法,这里就不一步步给你看源码了。只是给大家解释一下源码的原理图。首先是removeLast方法的源码示意图,如下图:源码的核心上下文是用一个l指针记录尾节点的位置,然后通过l.prev找到上一个元素,记录为prev,最后一个元素断开l.next=null,让last指针指向新的尾节点prev。看一下removeFirst方法的示意图:其实可以看到和前面的removeLast很像,只是用f指针记录头节点的位置,然后next记录f.next。断开与原始头节点的连接next.prev=null。最后让第一个指针指向新的头节点。事实上,你只需要记住这个想法。双向链表使用一个辅助指针来记录prev或next+head/tail指针的位置,这样就可以非常简单的从头节点或尾节点删除元素。手写应该不会太难。最后看一下remove(index)方法的源码示意图:可以看到,remove(index)方法使用了node方法来定位元素,然后使用了两个辅助指针prev和next到记录定位到的元素节点的前后。定位元素的源码原理在上一节已经讲过了,就是二分法+for循环遍历查找。通过prev和next这两个指针,可以分别断开定位元素x的前后指针,重新连接next和prev,从某个位置删除元素。核心原理是通过定位+前后辅助指针实现的。这个思路你要记住,你可以自己试试手写的remove方法。下面我们就带大家领略LinkedList的核心方法。它还有一些高级的方法,比如addAll、toArray等,你可以自己简单的看一下,其实对你现在来说并不难。看看这些方法就可以找到核心原理并总结出来。另外,Vector和Stack这两个集合类与ArrayList完全相似。再加上Vector默认展开一倍,是线程安全的,底层是通过synchronized实现的。Statck继承了Vector,通过数组实现了一种类似栈的数据结构。您可以在将来简单地扫描它。这两个集合类除了非常老的源码或者业务程序,现在基本不用了,因为底层的synchronized锁太影响性能了。您应该在本节中学习的一个想法是总结。当你根据上下文阅读源代码并画图后,你不能就此止步。一定要总结一点,几点。总结反映了做一件事的产出。做任何事情都是一样的,比如IDC机柜机器的运维管理,需要创建一个excel记录每台机器的购买时间、电池状态、硬盘状态等。Excel是一个输出结果,一个汇总。工作的时候,很多事情最好有个结果。无论是文档、过程点,还是里程碑,最好是让你总结和记录结果。相信坚持下去,你会收获很多。金句甜点