ArrayList部分一共五篇文章了,而且引入了时间复杂度来分析,强烈建议你们必定要按顺序阅读,相关文章分别是:数组
一、ArrayList初始化 - Java那些事儿专栏post
二、ArrayList底层数组扩容原理 - Java那些事儿专栏debug
四、本文
指针
第三次强调,ArrayLIst是一个普通的类。cdn
好,如今咱们来讨论一下数组的删除,咱们知道数组一但在堆内存中建立出来,数组长度是不可变的,看如下源码:对象
添加10个用户blog
好比咱们要把“周八”这我的从数组中删除,如图:内存
咱们只能循环数组,找到“周八“的下标5,因为数组没有提供删除方法,咱们只能把下标为5的位置赋值为null(形成了数组空洞),“周八”这个Person对象已经没有引用指向它了,JVM的垃圾回收机制会在适当的时候回收它。但数组的长度仍是10。下次当咱们再循环查找某人时,稍不注意就会报空指针异常,虽然咱们能够写非空去判断,但仍是不太友好,咱们把null后面的全部元素引用复制一下,往前拷贝一份,把null这个空给填上,以下图rem
复制后:
null以后的ref引用都按顺序复制了一份到原来的null的位置,原有的1引用被覆盖,但perArr[9]里的引用的指向仍是不变(注意,是复制不是挪动,仔细看一下上面两个图)。
注意:perArr[8],perArr[9]指向的是同一个对象,这显然不是咱们所要的结果,再处理一下,咱们把perArr[9]的引用赋值为null。以下图:
问题彷佛解决了,但数组长度仍是10,还须要自行维护了一个size来记录长度,以上数组复制的代码,咱们都要本身去写,好在ArrayList这个类已经实现了,数组拷贝工做交给它就好,咱们只须要调用ArrayList这个类提供的remove删除元素就行,至于底层数组怎么拷贝,元素怎么删除由ArrayList对象自己去搞定(面向对象的思想),咱们来看一看ArrayList的两种元素删除方式,首先是按照下标删除:
咱们先看看删除前的元素,debug一下:
perList里面已经有了10个元素,执行一下这两句remove操做,再看一下debug的状况
下标为5的“周八”已经删除掉了,下标为5之后的元素也按照咱们以前的猜测往前移了一位,数组最后一个位置也置为null了。奇怪!“孙七”竟然没有删掉!打印出来的个数也是9
咱们看一下两种删除方式的源码。
基本上和咱们图中的分析一致,并采用size来记录元素的真实个数,这段代码里还调了一个方法rangeCheck()方法,咱们看一下:
好简单对不对,就是检查底层数组下标是否越界。咱们再看另一种删除方式
再看一下fastRemove()方法
和上面用下标删除方式一致,这儿就不细说了。
相信你们看到上面熟悉的equals()方法,就大概知道“孙七”为何没有删掉了,若是你写了一个类(Person),你须要这个类完美的支持List,你必需按照List的规范来写代码,咱们在
说说Java里的equals(中) - Java那些事儿专栏 一文中已经说得很清楚了,这儿就不细说了。
知道问题的缘由就好解决了,咱们重写equals()方法试一下。
重写完equals方法,执行一下再debug看一下
孙七已经删除掉了,孙七后面的全部人也向前复制了一格,末位置为null,size也是8了,再画一画图:
图中的“孙七”,“周八”已经没有引用指向它们,JVM虚拟机会在适当的时候进行回收。
咱们说一说ArrayList中删除元素的时间复杂度。在ArrayLIst中,若是底层数组长度为n。
当咱们用下标方式去删除元素时,若是删除的是最后一个元素,不会触发数组底层的复制,时间复杂度为O(1)。若是删除第i的元素,会触发底层数组复制n-i次,根据最坏状况,时间复杂度为O(n)。
由此看来,在ArrayList中删除指定元素的效率彷佛不是过高,删除元素会形成底层数组复制,这个问题在LinkedList有方案解决,请关注后续专栏文章。
示例中,用对象的方式来删除元素,只是想告诉你们,这种删除方式是用equals方法来查找元素的下标进而删除的,实际工做中不多遇到须要new一个对象去删除的状况。 不建议一上来就重写equals方法,除非你有特殊的需求。若是重写了equals方法,请一并重写hashCode方法,这个问题在 说说Java里的equals(中) - Java那些事儿专栏 一文中已经说过了。
下一篇:ArrayList的时间复杂度 - Java那些事儿专栏
注:本专栏文章首发于公众号:saysayJava。全部示例代码均已上传至公众号,须要请关注下载。
若是喜欢本系列文章,请为我点赞或顺手分享,您的支持是我继续下去的动力,您也能够在评论区留言想了解的内容,有机会本专栏会作讲解,最后别忘了关注一下我。
转载无限欢迎,但请注明「做者」和「原文地址」。转载请在文中保留此段,感谢您对做者版权的尊重。如需商业转载或刊登,请联系做者得到受权。