LinkedList理解(2)元素删除

上一篇文章我们说了LinkedList,并说了往里添加了元素。这篇文章我们来说说LinkedList元素的删除,话不多说,上代码,还是那个Person类

还是那两个属性,name,age,提供了一些简单的get与set方法。写我们的main方法

和前文一样,new了一个LinkedList,并往里添加了四个元素,看过前文的朋友都知道现在LinkedList目前在堆内存中的样子如下图:

现在我们来删除王五这个用户,运行一下

看一下结果

好奇怪,打印返回的删除状态居然是false,代码中明明删掉王五了,为什么打印的结果还是4?如果经常看本专栏文章的人,大概已经猜到了原因,这个王五是新new出来的,并不是perList里的王五,Person这个类没有重写equals方法,删除元素依赖于equals方法,到底是不是呢,我们来看一下源码:

不出所料,又看到了熟悉的equals,真是无处不在,这段代码其实是从第一个Node节点(first节点)开始对比item的值,如果equals成功就执行unlink()方法,并返回删除成功的布尔值true。我们画一画查找王五的这个过程。

大致就是这个样子,就大家仔细看图里的文字描述,现在我们来看看unlink()方法都做了啥

preview

 

注意,在本示例中,上图的黑色字体注释部分不会执行。好吧,我承认,多年前我看这段代码被绕晕了,prev.next,next.prev都是些什么鬼啊!苍天啊!大地啊!

别怕,上面代码看似烧脑但是逻辑相当简单,就是把包含王五的这个Node从双向链表中移出来,然后把王五相邻的两个Node的next和prev重新指向一下,我们画一下图:

简单吧,debug一下看是不是和图中画的一致,测试代码前别忘了在Person里重写equals方法

debug看一下,已经删除了王五,size也更新成了3。

打印结果也和期待中一样,打印删除状态也为true了。

说到这儿,我们再来看一下ArrayList以对象方式删除元素的源码,来和LinkedList比较一下

再看fastRemove()方法

大体上一致,两者都在元素中循环查找,LinkedList是把Node(包含Person)从链表的移出(通过修改上下节点的引用来实现),ArrayList删除底层数组元素后又把底层数组都往前复制了一格内容(忘记了的朋友可以复习一下,传送门:ArrayList的元素删除),现在我们来比较一下这两者间的时间复杂度。

假设要删除的元素都在这两个List中的第n位置,由于两者都循环查找了n次,省略循环查找这个步骤,说以我们直接看删除,前面的一系列文章中我们已经讲过了,由于ArrayList删除元素后,底层数组要往前复制一格,ArrayList底层数组删除元素时间复杂度为O(n)。再来看LinkedList,LinkedList底层链表删除元素只是简单的修改了一下引用地址,时间复杂度为O(1)。

由以上推断看来,LinkedList的删除效率似乎要好很多,实际真的如此吗?答案是不一定。下一篇文章我们将写一段代码来分析一下,LinkedList和ArrayList在删除元素时的真实效率。

以上我们说的删除用的是List的如下API

public boolean remove(Object o);

LinkedList还有一种删除方式,用下标方式删除,如下

public E remove(int index);

下一篇文章一起讲解。

注:示例中,用对象的方式来删除元素,只是想告诉大家,这种删除方式是用equals方法来查找元素进而删除的,实际工作中很少遇到需要new一个对象去删除的情况。 不建议一上来就重写equals方法,除非你有特殊的需求。如果重写了equals方法,请一并重写hashCode方法,这个问题在 说说Java里的equals(中)一文中已经说过了。

转载无限欢迎,但请注明「清浅池塘」和「https://zhuanlan.zhihu.com/p/28373321」。转载请在文中保留此段,感谢您对作者版权的尊重。如需商业转载或刊登,请联系作者获得授权。自助转载请点击:https://www.rightknights.com/materi

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值