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。全部示例代碼均已上傳至公衆號,須要請關注下載。
若是喜歡本系列文章,請爲我點贊或順手分享,您的支持是我繼續下去的動力,您也能夠在評論區留言想了解的內容,有機會本專欄會作講解,最後別忘了關注一下我。
轉載無限歡迎,但請註明「做者」和「原文地址」。轉載請在文中保留此段,感謝您對做者版權的尊重。如需商業轉載或刊登,請聯繫做者得到受權。