精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

ArrayList 從源碼角度剖析底層原理

開發 前端
對于 ArrayList 來說,我們平常用的最多的方法應該就是 add 和 remove 了,本文就主要通過這兩個基礎的方法入手,通過源碼來看看 ArrayList 的底層原理。

[[412204]]

對于 ArrayList 來說,我們平常用的最多的方法應該就是 add 和 remove 了,本文就主要通過這兩個基礎的方法入手,通過源碼來看看 ArrayList 的底層原理。

add

默認添加元素

這個應該是平常用的最多的方法了,其用法如下。

接下來我們就來看看 add 方法的底層源碼。

ensureCapacityInternal 作用為:保證在不停的往 ArrayList 插入數據時,數組不會越界,并且實現自動擴容。

這里的 minCapacaity 的值,實際上就是在調用完當前這次 add 操作之后,數組中元素的數量

注意,這里說當前這次 add 操作完成。舉個例子,調用 add 之前,ArrayList 中有3個元素,那么此時這個 minCapacity 的值就為 4

此外,可以看到將函數 calculateCapacity 的返回值作為了 ensureExplicitCapacity 的輸入。

calculateCapacity 做了什么,用大白話來說是,如果當前數組是空的,則直接返回 數組默認長度(10) 和 minCapacity 的最大值,否則就直接返回 minCapacity 。

接下里是 ensureExplicitCapacity ,源碼如下:

modCount 表示該 ArrayList 被更改過多少次,這里的更改不只是新增,刪除也是一種更改。通過上面的了解我們知道,如果當前數組內的元素個數是小于數組長度的,則 minCapacity 的值一定是小于 elementData.length 的。

相反,如果數組內的元素個數已經和數組長度相等了,則 0>0 一定是 false ,此時就會調用 grow 函數來進行數組擴容。

核心邏輯很簡單,新的數組長度 = 舊數組長度 + 舊數組長度/2。

這里的右移,就相當于直接除以2

所以通過這里的源碼我們驗證,ArrayList 的擴容是每次擴容 1.5 倍。但是這里會有一個疑問,因為上文提到擴容時 minCapacity 的值和數組長度應該是相等的,所以 新數組長度 - minCapacity 應該永遠大于0才對,為什么會有小于0的情況?

答案是 addAll 。

可以看到,add 和 addAll 底層都會調用 ensureCapacityInternal 。add 是往數組中添單個元素,而 addAll 則是往數組中添加整個數組。假設 addAll 我們傳進了一個很大的值,舉個例子,ArrayList 的默認數組長度為 10 ,擴容一次之后長度為 15 ,假設我們傳入的數組元素有 10 個,那么即使擴容一次還是不足以放下所有的元素,因為 15 < 20。

所以才會出現 newCapacity(擴容之后的數組長度) < minCapacity(執行完當前操作之后的數組內元素數量) 的情況,所以當這種情況出現之后,就會直接將 minCapacity 的值賦給 newCapacity 。

除此之外,還會有個極端的情況,假設 addAll 往里面塞入了 Integer.MAX_VALUE 個元素呢?這就是 hugeCapacity 函數要處理的邏輯了。首先如果溢出了就直接拋出 OOM 異常,其次會保證其容量不會超過 Integer.MAX_VALUE。

最后是真正執行擴容的操作,調用了 java.util 包里的 Arrays.copyOf 方法。從上圖可以看出,這個方法中傳入了兩個參數,分別是存放元素的數組、新的數組長度,舉個例子:

  1. int[] elementData = {1, 2, 3, 4, 5};  
  2. int[] newElementData = Arrays.copyOf(elementData, 10); 
  3. System.out.println(newElementData); // [1 2 3 4 5 0 0 0 0 0] 

數組擴容完成之后,就會將本次 add 的元素寫入 elementData 的末尾了,elementData[size++] = e 。

接下來我們用流程圖來總結一下 add 操作的整個核心流程。

指定添加元素的位置

了解完了 add 和 addAll,我們趁熱打鐵,來看看可以指定元素位置的 add ,其接受兩個參數,分別是:

  1. 新元素在數組中的下標
  2. 新元素本身

這里和最開始的 add 就有些不同了,之前的 add 方法會將元素放在數組的末尾,而 add(int index, E element) 則會將元素插入到數組中指定的位置,接下來從源碼層面看看。

首先,由于這個方法允許用戶傳入數組下標,所以首先要做的事情就是檢查傳入的數組下標是否合法,如果不合法則會直接拋出 IndexOutOfBoundsException 異常。

很簡單的判斷,下標 index 不能小于0,并且不能超過數組中的元素個數,舉個例子:

像上圖這種情況,調用 add(int index, E element) 之前,數組內有3個元素,即使底層數組的長度為10 ,但是數組下標如果傳入5,是會拋出 IndexOutOfBoundsException 異常的。在上圖這種情況,index 的值最大只能為3才不會報錯,因為 index(下標為3) > size(3個元素) 肯定不為 true 。

完成了校驗之后,還是會調用上面聊到過的 ensureCapacityInternal 方法,根據需要,來對底層的數組進行擴容。然后調用 System.arraycopy 方法,這個方法比較關鍵,也比較難理解,所以我就簡單一句話把它的作用概括了——將制定下標后的元素全部往后移動一位。

System.arraycopy 接收 4 個參數,分別是:

  • 原數組
  • 原數組中的起始下標
  • 目標數組
  • 目標數組中的起始下標

光看參數,不結合例子,其實很難理解,我這里舉個簡單的例子。

假設現在數組里有元素 [1 2 3] ,然后此時我調用方法 add(1, 4) ,表明我想要將元素 4 插入到數組下標為 1 的位置,那么此時 index 的值為1,size 的值為 3。

System.arraycopy 的方法就會變成 System.arraycopy(elementData, 1, elementData, 2, 2),也就是將 elementData 從下標 1 開始的兩個元素(也就是 2 和 3),拷貝到 elementData 的從下標 2 開始的地方。

可能還是有點繞,說人話就是執行完后,elementData 就變成了 [1 2 2 3],然后再對 elementData 進行賦值,將下標為 1 的元素改為本次需要 add 的元素。再說句人話就變成了 [1 4 2 3]。

所以綜上來看,沒有什么黑魔法,主要需要了解的就是兩個關鍵的函數,分別是 Arrays.copy 和 System.arraycopy 。我們需要把這兩個封裝好的函數的作用給記住。

  • Arrays.copy 數組擴容
  • System.arraycopy 將數組中某個下標之后元素全部往后移動一位

所以從這里就可以看到,看源碼的好處,主要有兩個方面。第一,我相信你在刷題的時候一定也遇到過需要將數組的元素整個后移的 case,但是你可能并不知道可以使用 System.arraycopy ,就算你知道有這么個函數可能就連參數都看不懂;第二,知道了 System.arraycopy ,但是覺得這些函數完全沒有應用場景。

remove

了解數據怎么來,接下來我們來看一下數據是怎么被移除的。首先我們來看最常用的兩種:

  • 按照下標移除
  • 根據元素移除

根據下標移除

首先是根據下標移除

這里也會先檢查傳入的 index 是否合法,但是這里的 index 和 add 中調用的 rangeCheck 還有點區別。add 中的 rangeCheckForAdd 會判斷 index 是否為負數,而 remove 中的 rangeCheck 則只會判斷 index 是否 >= 數組中的元素個數。

其實從函數的名稱就能看出,rangeCheckForAdd 是專門給 add 方法用的

那如果此時傳入的 index 真的是負數怎么辦?其實是會拋出 ArrayIndexOutOfBoundsException ,因為remove 方法上加了 Range 注解。

完成后,還是會更新 modCount 的值,這也驗證了我們上面提到的 modCount 代表的更改中也包含了刪除。

接下來會計算一個 numMoved ,代表需要被移動的元素數量。add 一個元素,對應的下標的元素都需要往后順移一位,remove 同理,刪除了某個位置的元素后,其后面對應的所有的元素都需要往前順移一位,就像這樣:

知道了需要移動多少個元素之后,我們的 System.arraycopy 就又可以登場了。完成了元素的移動之后,數組的末尾必然會空出來一個元素,直接將其設置為 null 然后交給 GC 回收即可,最后把被移除的值返回。

根據值移除

舉個例子,根據值移除就長下面這樣這樣。

廢話不多說,直接看核心源碼

完了,第二行就給整懵了,移除一個 null 是什么鬼?還要循環去移除?

實際上,ArrayList 允許我們傳 null 值進去,再舉個例子。

看完這個例子,應該就能夠明白為什么要做 o == null 的判斷了。如果傳入的是 null ,ArrayList 會對底層的數組進行遍歷,并移除匹配到的第一個值為 null 的元素。

如果值不為 null 也是同理,如果數組中有多個一樣的值,ArrayList 也會對其進行遍歷,并且移除匹配到的第一個值。通過源碼可以看到,無論值是否為 null ,其都會調用真正的刪除元素方法 fastRemove ,干的事情就跟 remove 做的幾乎一樣。

他們的唯一的區別在于,按照下標移除,會返回被移除的元素;按照值移除只會返回是否移除成功。

總結

所以,看完 ArrayList 的部分源碼之后,我們就可以知道,ArrayList 的底層數據結構是數組。雖然對于用戶來說 ArrayList 是個動態的數組,但是實際上底層是個定長數組,只是在必要的時候,對底層的數組進行擴容,每次擴容 1.5 倍。但是從源碼也看出來了,擴容、刪除都是有代價的,特別是在極端的情況,會需要將大量的元素進行移位。

所以我們得出結論,ArrayList 如果有頻繁的隨機插入、頻繁的刪除操作是會對其性能造成很大影響的, 總結來說,ArrayList 適合用于讀多寫少的場景。

另一個很重要很重要的點,這里提一下,ArrayList 不是線程安全的。多線程的情況下會出現數據不一致或者會拋出 ConcurrentModificationException 異常,關于這塊后面有機會再聊吧

了解完如何向一個數據結構中存取、移除數據,其實就已經能夠順理成章的理解跟其相關的很多事情了。 

舉個例子,indexOf 方法用于返回指定元素在數組中的下標,了解完 remove 中的遍歷匹配,或者說你甚至可以直接靠直覺就應該想到,indexOf 不就是個 for 循環匹配嗎?lastIndexOf 不就是個反向的 for 循環匹配嗎?所以在這里再貼出源碼除了讓文章篇幅更長之外,沒有任何意義。這個感興趣的話可以找源碼看一看。

責任編輯:武曉燕 來源: SH的全棧筆記
相關推薦

2020-12-14 08:03:52

ArrayList面試源碼

2022-09-27 18:56:28

ArrayList數組源代碼

2025-09-02 03:33:00

2021-04-15 09:07:52

hotspotJavaC++

2020-12-17 08:03:57

LinkedList面試源碼

2015-09-15 10:52:52

2022-03-08 11:29:06

Linux進程系統

2018-02-25 13:15:10

智能制造

2022-10-28 10:23:27

Java多線程底層

2021-10-26 10:22:27

ArrayList阿里云

2019-11-25 16:05:20

MybatisPageHelpeJava

2019-10-16 16:33:41

Docker架構語言

2021-01-16 12:10:24

Go語言計算機位開發

2022-11-11 10:48:55

AQS源碼架構

2023-06-09 14:01:00

架構程序APP

2023-03-13 07:43:51

PHP類型轉換

2023-08-11 08:42:49

泛型工廠繼承配置

2024-01-19 12:48:00

Redis存儲數據庫

2020-04-27 07:13:37

Nginx底層進程

2023-03-06 08:40:43

RedisListJava
點贊
收藏

51CTO技術棧公眾號

亚洲黄色性网站| 亚洲黄色成人| 精品视频一区二区三区免费| 欧美精品一区二区三区在线看午夜| 国产黄色片视频| 欧美wwwwww| 欧美午夜宅男影院在线观看| 高清日韩一区| 国产黄色片免费看| 国产精品一区2区3区| 91黄色激情网站| 亚洲激情电影在线| www.色呦呦| 亚洲精品男同| 亚洲无亚洲人成网站77777| 三级在线免费看| 中文在线手机av| 91在线你懂得| 国产精品免费福利| 欧美日韩中文字幕在线观看| 精品三级在线观看视频| 欧美亚洲免费在线一区| 国产又粗又大又爽的视频| 国产美女自慰在线观看| 黄色在线一区| 亚洲性xxxx| 男插女视频网站| 欧美a级在线观看| 国产精品网站在线观看| 超碰97在线人人| 免费毛片一区二区三区| 欧洲美女日日| 精品国产三级a在线观看| 日本精品久久久久中文字幕| 含羞草www国产在线视频| 91美女在线观看| 国产精品视频免费在线| 精品一区二区三区人妻| 欧美亚洲在线日韩| 精品999久久久| 国产小视频精品| xxx在线免费观看| 中文字幕一区二区三区精华液| 国产中文一区二区| 国产一区二区视频网站| 欧美.日韩.国产.一区.二区| 亚洲欧美精品伊人久久| 精品国产aⅴ一区二区三区东京热| 日韩欧美精品电影| 亚洲国产精品久久久男人的天堂 | 国产成人精品亚洲线观看| 在线观看视频欧美| 国产主播自拍av| 毛片免费不卡| 国产亚洲成av人在线观看导航| www.成人av| 一卡二卡三卡在线观看| 久久久777| 久久琪琪电影院| 日韩精品一区二区亚洲av性色| 亚洲丝袜啪啪| 亚洲精品大尺度| 亚洲av无码专区在线播放中文| 精品乱码一区二区三区四区| 欧美日韩中文字幕在线视频| 免费在线黄网站| 污污网站在线看| 一区二区三区精品视频| 亚洲在线视频一区二区| 成人高清免费在线播放| 久久综合久久综合久久综合| 国产免费一区| 黄色一级大片在线免费看国产| 精品无人码麻豆乱码1区2区 | 久久xxxx精品视频| 97精品欧美一区二区三区| 青春草免费视频| 欧美xxav| 日韩在线播放av| 日本猛少妇色xxxxx免费网站| 综合伊思人在钱三区| 日韩精品在线第一页| 国产亚洲色婷婷久久99精品91| 成人av婷婷| 欧美zozo另类异族| 午夜不卡久久精品无码免费| jizz性欧美2| 精品国内二区三区| 交换做爰国语对白| 中文无码日韩欧| 欧美精品一区二区高清在线观看| 熟妇高潮一区二区| 亚洲人和日本人hd| 在线播放日韩精品| 91导航在线观看| 99久久激情| 九九热最新视频//这里只有精品| 欧美又粗又大又长| 一本色道久久综合亚洲精品高清| 欧美一级黄色网| 伊人久久中文字幕| 日韩精品乱码av一区二区| 国产精品久久久久久久久久小说| 中文字幕一区二区三区人妻四季| 九九**精品视频免费播放| 69堂成人精品视频免费| 免费成人在线看| 成人av在线播放网站| 欧美日韩视频在线一区二区观看视频 | 国内精品久久久久久久97牛牛| 日韩有码片在线观看| 精品一区在线视频| 日韩国产欧美在线播放| 91免费看国产| 欧美 日韩 中文字幕| 国产欧美视频在线观看| 最新欧美日韩亚洲| 国产美女高潮在线| 精品视频一区二区三区免费| 韩国三级丰满少妇高潮| 西瓜成人精品人成网站| 日韩亚洲综合在线| 日韩特黄一级片| 久久一区国产| 91在线免费看片| 黄色在线播放| 一区二区三区在线视频观看58 | а√在线天堂官网| 日韩欧美在线第一页| 又色又爽又黄视频| 小嫩嫩12欧美| 九九久久国产精品| 亚洲视频在线观看免费视频| 成人黄色av网站在线| 色噜噜狠狠色综合网| 国产蜜臀在线| 3d动漫精品啪啪1区2区免费| 欧美亚一区二区三区| 欧美激情成人在线| 国产精品视频区1| 亚洲色图 校园春色| 亚洲色欲色欲www在线观看| 青青视频在线播放| 中文字幕一区二区三区中文字幕| 亚洲天堂日韩电影| 国产奶水涨喷在线播放| 久久99国产精品尤物| 欧美一进一出视频| aa级大片免费在线观看| 日韩午夜激情免费电影| ass极品国模人体欣赏| 男女精品网站| 国产在线精品一区二区中文| 午夜伦理大片视频在线观看| 欧美午夜电影在线播放| 高清中文字幕mv的电影| 久久亚洲国产| 国产精品免费看久久久香蕉| 免费一级在线观看| 欧美日韩国产在线看| 亚洲国产精品狼友在线观看| 午夜精品国产| 91久久国产婷婷一区二区| 1024视频在线| 欧美性猛交xxxx乱大交退制版| 国产全是老熟女太爽了| 一区二区三区在线电影| 亚洲www在线观看| 婷婷视频在线| 欧美精品视频www在线观看 | 亚洲视频在线观看一区| 天天色综合社区| 国产成人手机高清在线观看网站| 51色欧美片视频在线观看| 天天操天天干天天操| 亚洲大型综合色站| 成人性生活免费看| 亚洲精选在线| 好吊色欧美一区二区三区 | 国产亚洲一区二区在线| 国产一级片毛片| 久久噜噜亚洲综合| 日韩欧美黄色大片| 日韩精品电影| 成人免费观看a| 色呦呦在线资源| 精品sm捆绑视频| 毛片视频网站在线观看| 久久久久99精品一区| 99久久国产宗和精品1上映| 欧美理论电影大全| 国产中文字幕日韩| 牛牛精品在线| 亚洲精品久久久久久久久久久| www日韩精品| 久久久精品人体av艺术| 在线免费观看视频黄| 久久裸体网站| http;//www.99re视频| 波多野结衣视频一区二区| 亚洲精品在线观看www| a片在线免费观看| 亚洲欧洲美洲综合色网| 国产人妖在线观看| 香蕉久久久久久久av网站| 亚洲精品日韩成人| 91亚洲无吗| 国产精品88a∨| av一区在线观看| 日韩欧美国产电影| 午夜精品免费观看| 国产精品色一区二区三区| av电影中文字幕| 日韩av网站免费在线| 99re6这里有精品热视频| 亚洲成人一品| 91精品国产综合久久久久久蜜臀| 色噜噜狠狠狠综合欧洲色8| 亚洲欧美日韩图片| 国产成人免费看一级大黄| 疯狂做受xxxx高潮欧美日本| 自拍偷拍第9页| proumb性欧美在线观看| jizz18女人| 美日韩精品视频| 综合色婷婷一区二区亚洲欧美国产| 中文字幕av一区二区三区四区| 国产精品久久久久久久久久久久久久 | 99视频精品免费观看| 日韩av一区二区三区在线观看| 影音先锋欧美激情| 国产有码一区二区| 中文字幕人成乱码在线观看| 久久久国产精品x99av| 三级在线观看| 精品国内片67194| 国产精品久久久久久久成人午夜| 偷拍一区二区三区| 久久久久亚洲av片无码| 国产亚洲精品7777| 大地资源二中文在线影视观看| 精品综合久久久久久8888| 日韩欧美在线播放视频| 海角社区69精品视频| 婷婷视频在线播放| 欧美精品一区二区三区精品| 久久国产精品一区二区三区| 欧美高清hd| 成人疯狂猛交xxx| 五月激情久久| 欧美一级电影久久| 成年男女免费视频网站不卡| 欧美成人激情视频| 九七电影韩国女主播在线观看| 亚洲人成网站免费播放| 四虎精品在线| 亚洲国产小视频在线观看| www.麻豆av| 欧美一区三区四区| 国产欧美熟妇另类久久久| 欧美视频在线不卡| 日本妇乱大交xxxxx| 色网站国产精品| 无码免费一区二区三区| 色综合久久中文综合久久97| 91精品国产乱码久久久张津瑜| 亚洲成人高清在线| 国产亚洲精品码| 亚洲一区二区三区中文字幕在线| 五月婷婷一区二区| 一区二区不卡在线视频 午夜欧美不卡在| 色欲人妻综合网| 亚洲精品一二三| 久草免费新视频| 亚洲1区2区3区视频| 在线看成人av| 亚洲国产一区在线观看| 日韩av在线播放观看| 亚洲第一成年网| 毛片毛片女人毛片毛片| 天天操天天色综合| 欧美一级淫片免费视频黄| 色婷婷亚洲精品| 中文字幕精品一区二| 在线观看日韩高清av| 国产男人搡女人免费视频| 欧美伊人久久大香线蕉综合69| 在线视频 中文字幕| 欧美一级艳片视频免费观看| 亚洲视频一区在线播放| 日韩视频一区在线观看| 丰满少妇在线观看bd| 日韩av网站在线| jzzjzzjzz亚洲成熟少妇| 搡老女人一区二区三区视频tv| 动漫一区在线| 久久久久在线观看| 国产极品一区| 国产一区二区三区高清| 999久久久国产精品| 亚洲 欧美 日韩 国产综合 在线| 奇米精品一区二区三区在线观看 | 国产精品毛片无码| 精品在线视频一区二区三区| 久久综合国产| 蜜臀av无码一区二区三区| 久久99精品国产.久久久久| 网站免费在线观看| 亚洲欧美激情插 | 免费视频一区二区三区在线观看| 蜜桃福利午夜精品一区| 久久理论电影网| 国产一级做a爰片在线看免费| 在线观看免费一区| 欧美一级特黄aaaaaa| 久久精品亚洲热| 久久91导航| 国内一区在线| 亚洲欧美亚洲| www.污污视频| 欧美激情中文不卡| 看片网址国产福利av中文字幕| 91精品婷婷国产综合久久竹菊| 国产在线视频网站| 91精品国产沙发| 亚洲视频一起| 中文字幕在线中文| 麻豆成人91精品二区三区| 中文幕无线码中文字蜜桃| 亚洲mv在线观看| 亚洲精品国产片| 欧美精品在线视频观看| 日本久久久久| 亚洲电影一二三区| 日韩精品乱码av一区二区| a毛片毛片av永久免费| 精品成人乱色一区二区| 黄色一级a毛片| 久久久免费精品视频| 亚洲一区二区三区免费| 欧美性受xxxx黑人猛交88| 久久99久久99精品免视看婷婷| 黄免费在线观看| 91搞黄在线观看| 九色在线播放| 国产成人一区二区在线| 久久av资源| 日本中文字幕高清| 国产精品免费丝袜| 一本久道久久综合无码中文| 一区二区三区天堂av| 91精品国产66| 亚洲午夜精品福利| 久久爱www久久做| 国产色无码精品视频国产| 欧美精品色一区二区三区| 黄色网址免费在线观看| 亚洲一区二区三区在线免费观看| 中文字幕免费一区二区| 美女流白浆视频| 亚洲成a人v欧美综合天堂下载| 手机亚洲第一页| 国产精品黄色av| 98精品视频| 18深夜在线观看免费视频| 亚洲不卡在线观看| 欧美精品a∨在线观看不卡| 国产成人鲁鲁免费视频a| 日韩欧美午夜| 国产91在线免费观看| 亚洲444eee在线观看| 国产精品二线| 亚洲一区二区久久久久久| 韩国久久久久| 中文字幕免费高清| 69久久99精品久久久久婷婷| 大桥未久在线播放| 欧美国产一区二区在线| 美女任你摸久久 | 综合久久精品| 亚洲av无码一区二区三区网址| 色婷婷av一区二区三区软件 | 亚洲熟妇av一区二区三区| 国产精品无人区| 超碰人人人人人人| 日本91av在线播放| 久久久9色精品国产一区二区三区| 波多野结衣电影免费观看| 欧美性生交大片免费| 免费av网站在线观看| 国产一区免费在线| 青青青伊人色综合久久| 久久久一区二区三区四区| 亚洲男人天堂2023| 亚洲啊v在线免费视频| 日本三区在线观看| 亚洲综合一二三区| 色的视频在线免费看| 精品国产免费一区二区三区| 青草国产精品久久久久久|