深度解析Java中ArrayList的使用
一、ArrayList是什么
ArrayList 類是一個(gè)可以動(dòng)態(tài)修改的數(shù)組,與普通數(shù)組的區(qū)別就是它是沒(méi)有固定大小的限制,我們可以添加或刪除元素。ArrayList 繼承了 AbstractList ,并實(shí)現(xiàn)了 List 接口。
我們發(fā)現(xiàn)ArrayList類位于java.util包中,使用之前需要去引入它.
import java.util.ArrayList;
ArrayList如何定義:
ArrayList<E> arrayList = new ArrayList<E>();
此數(shù)E為泛型實(shí)參類型,只能為引用數(shù)據(jù)類型,ArrayList想存儲(chǔ)什么類型的數(shù)據(jù),我們就傳什么就可以。
List<E> list = new ArrayList<E>();
因我們的ArrayList是繼承于List的,所以我們可以用父類去接受子類對(duì)象,向上轉(zhuǎn)型。
二、ArrayList的構(gòu)造方法
我們發(fā)現(xiàn)ArrayList一共提供了三種構(gòu)造方法。
構(gòu)造方法1:
構(gòu)造一個(gè)空的順序表
List<Integer> list = new ArrayList<>();
構(gòu)造方法2:
構(gòu)造一個(gè)指定大小為5的順序表
List<Integer> list = new ArrayList<>(5);
構(gòu)造方法3:
此處傳入的要么是自己本身類型,或者是子類類型。
此處構(gòu)造一個(gè)和list2元素一致的順序表
List<Integer> list2 = new ArrayList<>(5); List<Integer> list = new ArrayList<>(list2);
初始時(shí)的坑
List list = new ArrayList();
這樣對(duì)順序表進(jìn)行初始化的話,沒(méi)有指定任何類型,這樣的話可以存放任意類型的元素,這樣會(huì)存在很大的安全隱患。
三、ArrayList的常見方法
常見方法
在我的上一篇實(shí)現(xiàn)順序表中,已經(jīng)把大多數(shù)方法手動(dòng)實(shí)現(xiàn)了一遍,此處我在說(shuō)明幾個(gè)重點(diǎn)的。
remove方法
ArrayList提供給我們兩個(gè)remove方法
一個(gè)是傳入要?jiǎng)h除的下標(biāo),一個(gè)是要?jiǎng)h除的引用。
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(10); list.add(8); list.remove(1); System.out.println(list); }
如果我們傳入的是int類型那么我們刪除的是該下標(biāo)的數(shù)據(jù)。
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(10); list.add(8); list.remove(new Integer(10)); System.out.println(list); }
如果我們傳入的是引用數(shù)據(jù)類型,那么將刪除該順序表中的該引用數(shù)據(jù)。
subList方法
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); System.out.println("截取之前的list:"+list); List<Integer> list1 = list.subList(1,3); list1.set(0,5); System.out.println("截取之后的list:"+list); }
為啥改了list1之后,list的數(shù)據(jù)也發(fā)生了變化。
因?yàn)樵诮厝≈蟛](méi)有復(fù)制一份內(nèi)容給list1,而是指向同一塊內(nèi)容。
遍歷ArrayList
方法1:
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); for (int i = 0; i < list.size(); i++) { System.out.print(list.get(i)+" "); } System.out.println(); }
方法2:
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); for (Integer x:list) { System.out.print(x+" "); } System.out.println(); }
方法3:
使用迭代器
方法 | 作用 |
---|---|
.next() | 返回迭代器寫一個(gè)元素,更新迭代器狀態(tài) |
.hasNext() | 檢測(cè)集合中是否還有元素 |
.remove() | 將迭代器返回的元素刪除 |
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); Iterator<Integer> it = list.listIterator(); while (it.hasNext()) { System.out.print(it.next()+" "); } System.out.println(); }
使用迭代器刪除元素
我們刪除集合小于3的元素
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); Iterator<Integer> it = list.listIterator(); while (it.hasNext()) { if(it.next() < 3) { it.remove(); } } System.out.println(list); }
迭代器的remove方法只能刪除當(dāng)前指向的元素。
四、ArrayList的擴(kuò)容機(jī)制
List<Integer> list = new ArrayList<>();
很多資料都在說(shuō)這樣初始化一個(gè)集合,說(shuō)默認(rèn)大小為10,那事實(shí)到底是不是如此呢?我們一步步查看源碼一探究竟。
我們發(fā)現(xiàn)當(dāng)前引用指向后面那個(gè)引用
我們發(fā)現(xiàn)這里的引用是一個(gè)空引用,初始集合時(shí),是一個(gè)空集合。
那如何擴(kuò)容呢?
既然我們的順序表是空的,那如何add呢?
如果是無(wú)參構(gòu)造的話,就傳一個(gè)默認(rèn)大小和傳入大小的最大值。
我們可以發(fā)現(xiàn)如果大于數(shù)組大小時(shí),就會(huì)grow。
我們可以發(fā)現(xiàn)計(jì)算一個(gè)新容量,和我們傳入的大小做比較,如果新容量小于傳入的大小時(shí),指定當(dāng)前集合大小為傳入的大小。否則,對(duì)集合大小進(jìn)行1.5倍擴(kuò)容。
但如果我們1.5倍擴(kuò)容的大小超過(guò)了這個(gè)指定的范圍2147483639時(shí)
系統(tǒng)會(huì)報(bào)一個(gè)內(nèi)存溢出異常。
1. 檢測(cè)是否真正需要擴(kuò)容,如果是調(diào)用grow準(zhǔn)備擴(kuò)容
2. 預(yù)估需要庫(kù)容的大小
初步預(yù)估按照1.5倍大小擴(kuò)容
如果用戶所需大小超過(guò)預(yù)估1.5倍大小,則按照用戶所需大小擴(kuò)容
真正擴(kuò)容之前檢測(cè)是否能擴(kuò)容成功,防止太大導(dǎo)致擴(kuò)容失敗
3. 使用copyOf進(jìn)行擴(kuò)容
到此這篇關(guān)于深度解析Java中ArrayList的使用的文章就介紹到這了,更多相關(guān)Java ArrayList內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring security數(shù)據(jù)庫(kù)表結(jié)構(gòu)實(shí)例代碼
這篇文章主要介紹了spring security數(shù)據(jù)庫(kù)表結(jié)構(gòu)實(shí)例代碼,需要的朋友可以參考下2017-09-09Springcloud Config配置中心使用與相關(guān)介紹
springcloud config是一個(gè)解決分布式系統(tǒng)的配置管理方案。它包含了 client和server兩個(gè)部分,server端提供配置文件的存儲(chǔ)、以接口的形式將配置文件的內(nèi)容提供出去,client端通過(guò)接口獲取數(shù)據(jù)、并依據(jù)此數(shù)據(jù)初始化自己的應(yīng)用2022-09-09java設(shè)計(jì)模式之外觀模式學(xué)習(xí)筆記
這篇文章主要為大家詳細(xì)介紹了java設(shè)計(jì)模式之外觀模式學(xué)習(xí)筆記,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10SpringCloud之分布式配置中心Spring Cloud Config高可用配置實(shí)例代碼
這篇文章主要介紹了SpringCloud之分布式配置中心Spring Cloud Config高可用配置實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04HttpClient實(shí)現(xiàn)調(diào)用外部項(xiàng)目接口工具類的示例
下面小編就為大家?guī)?lái)一篇HttpClient實(shí)現(xiàn)調(diào)用外部項(xiàng)目接口工具類的示例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10mybatis動(dòng)態(tài)sql之Map參數(shù)的講解
今天小編就為大家分享一篇關(guān)于mybatis動(dòng)態(tài)sql之Map參數(shù)的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03Java8使用stream實(shí)現(xiàn)list中對(duì)象屬性的合并(去重并求和)
這篇文章主要介紹了Java8使用stream實(shí)現(xiàn)list中對(duì)象屬性的合并(去重并求和),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01