前言
ArrayList 算是我們開發中最經常用到的一個集合了,使用起來很方便,對于內部元素的隨機訪問很快,今天來分析下ArrayList的一些原理方法,對于平常作業和面試都是非常有用的,
另外本人整理收藏了20年多家公司面試知識點整理 ,以及各種Java核心知識點免費分享給大家,我認為對面試來說是非常有用的,想要資料的話請點795983544 暗號CSDN,

一.ArrayList 簡介
ArrayList 是一個陣列佇列,相當于 動態陣列,與 Java 中的陣列相比,它的容量能動態增長,它繼承于 AbstractList,實作了 List, RandomAccess, Cloneable, java.io.Serializable 這些介面, 看過 ArrayList 原始碼的同學有沒有注意過有這么一個細節:為什么 ArrayList 實作了RandomAccess這個介面,但是 LinkedList 卻沒有實作這個介面?這是一個空介面,里面沒有任何的方法,有什么作用呢?
答案: RandomAccess 是一個標志介面,表明實作這個這個介面的 List 集合是支持快速隨機訪問的,也就是說,實作了這個介面的集合是支持 快速隨機訪問 策略的,而 LinkedList 是不能實作隨機訪問的,
二.ArrayList 資料結構
ArrayList 包含了兩個重要的物件:elementData 和 size,
- elementData 是"Object[]型別的陣列",它保存了添加到 ArrayList 中的元素,實際上,elementData
是個動態陣列,
那是不是有人就會問既然 ArrayList 本質是陣列,那為啥它的長度可以改變?
首先,陣列的確長度不能改變,不過,ArrayList 內部有一系列騷操作,大概就是它每次覺得長度不夠就會 創建一個新陣列,這個新陣列的容量比原來多出 50%,把原來的陣列 copy 過來,然后把以前的陣列銷毀掉,
- size 則是動態陣列的實際大小,
三. ArrayList 遍歷方式
- 第 1 種,普通 for 回圈隨機訪問,通過索引值去遍歷,
// 隨機訪問
List<String> list = new ArrayList<>();
int size = list.size();
for (int i = 0; i < size; i++) {
value = list.get(i);
}
- 第 2 種,通過迭代器遍歷,即通過 Iterator 去遍歷,
// 迭代器遍歷
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
value = iter.next();
}
- 第 3 種,增強 for 回圈遍歷,
// 增強 for 回圈
for (String s : list) {
value = s;
}
- 第 4 種 forEach + lambda 回圈遍歷
list.forEach(p -> {
p.hashCode();
});
四種遍歷比較
- 結論:如果資料量比較少的話貌似四種回圈耗時都差不多,但是隨著資料量的增長會發現 foreach 的效率是最好的,但是從上面我們會發現一個奇怪的現象,第一次回圈的時候forEach遍歷的時間是最長的盡管資料量非常少也會這樣,但是后面的耗時就正常了,如果放開測驗里面的預熱代碼,每次跑出來的耗時也是正常的,
四.ArrayList 洗掉資料
雖然有四種遍歷方式,但是能夠正確洗掉資料的方式只有兩種
- 第 1 種通過迭代器進行洗掉,這種方式的話,也是《阿里代碼規約》所推薦的,

Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
iter.next().hashCode();
iter.remove();
}
- 第 2 種倒序回圈洗掉
for(int i = list.size()-1;i>=0;i--){
list.remove(i);
}
下面再演示下錯誤的洗掉操作
- 普通 for 回圈正序洗掉,洗掉程序中元素向左移動,不能洗掉重復的元素
List<String> list = new ArrayList<>();
list.add("1");
list.add("1");
list.add("2");
for(int i=0;i<list.size();i++){
list.remove(i);
}
System.out.println(String.join(",",list));
結果輸出:1
- 增強 for 回圈洗掉會拋出 java.util.ConcurrentModificationException
五.ArryList 注意點
謹慎使用 ArrayList 中的 subList 方法
- ArrayList 的 subList 結果不可強轉成 ArrayList,否則會拋出 ClassCastException 例外,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList. 說明:subList 回傳的是 ArrayList 的內部類 SubList,并不是 ArrayList ,而是 ArrayList 的一個視圖,對于 SubList 子串列的所有操作最侄訓反映到原串列上,
List<String> list = new ArrayList<>();
list.add("1");
list.add("1");
list.add("2");
ArrayList<String> strings = (ArrayList)list.subList(0, 1);
運行結果:
Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList$SubList cannot be cast to java.util.ArrayList
at com.workit.demo.listener.ArrayListTest.main(ArrayListTest.java:29)
- 在 subList 場景中,高度注意對原集合元素個數的修改,會導致子串列的遍歷、增加、 洗掉均會產 ConcurrentModificationException 例外,
List<String> list = new ArrayList<>();
list.add("1");
list.add("1");
list.add("2");
List<String> subList = list.subList(0, 1);
// 對原 List 增加一個值
list.add("10");
subList.add("11"); // 這一行會報 java.util.ConcurrentModificationException
- 初始化 List 的時候盡量指定它的容量大小,(盡量減少擴容次數)
結束語
- 由于自己才疏學淺,難免會有紕漏,假如你發現了錯誤的地方,還望留言給我指出來,我會對其加以修正,
- 如果你覺得文章還不錯,你的轉發、分享、贊賞、點贊、留言就是對我最大的鼓勵,
- 感謝您的閱讀,十分歡迎并感謝您的關注,
另外本人整理收藏了20年多家公司面試知識點整理 ,以及各種Java核心知識點免費分享給大家,我認為對面試來說是非常有用的,想要資料的話請點795983544 暗號CSDN,


轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/143796.html
標籤:其他
上一篇:SpringBoot-web開發(四): SpringMVC的拓展、接管(原始碼分析)
下一篇:抖音無水印下載
