關(guān)于ArrayList初始化容量的問(wèn)題
ArrayList初始化容量的問(wèn)題
(所有的圖片的代碼來(lái)源于JDK1.8中的源碼)
可能很多同學(xué)聽(tīng)到網(wǎng)上其他人說(shuō)ArrayList的底層數(shù)組elementData的初始化容量是10。
其實(shí)并不是!
下圖是我們經(jīng)常初始化ArrayList使用的構(gòu)造器:
而DEFAULTCAPACITY_EMPTY_ELEMENTDATA也是一個(gè)空的數(shù)組,請(qǐng)看下面的圖示:
說(shuō)白了就是,每次我們調(diào)用初始化一個(gè)空白的集合ArrayList,它的底層數(shù)組其實(shí)是空的。那人們說(shuō)的初始化容量是10到底是從哪來(lái)的呢?
其實(shí)是:當(dāng)我們第一次為ArrayList添加元素的時(shí)候,底層數(shù)組擴(kuò)容到了10。
下面我們就分析一下這個(gè)過(guò)程
當(dāng)我們通過(guò)ArrayList調(diào)用add()方法添加元素的時(shí)候,其實(shí)底層一共需要調(diào)用了4個(gè)方法(如果需要擴(kuò)容的話,則調(diào)用5個(gè)方法。Math.max()和Arrays.copyOf()不計(jì)入其內(nèi)。)
下面先給出源代碼視圖,然后我們一一分析代碼:
首先假設(shè)我們使用
ArrayList<Integer> arrayList = new ArrayList<>();
構(gòu)造的是一個(gè)空的ArrayList,此時(shí)ArrayList底層的elementData是一個(gè)DEFAULTCAPACITY_EMPTY_ELEMENTDATA(上面有源碼)。
接著調(diào)用了ensureCapacityInternal,然后參數(shù)size+1,也就是1(size代表我們集合中元素的個(gè)數(shù))。
接著調(diào)用calculateCapacity(計(jì)算容量),通過(guò)判斷elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA(也就是判斷我們?cè)诔跏蓟疉rrayList的時(shí)候,是不是使用的是默認(rèn)的構(gòu)造器),如果是初始化的時(shí)候使用的是默認(rèn)的狗再去,接著就返回DEFAULT_CAPACITY和上面我們傳的參數(shù)中的最大值,而DEFAULT_CAPACITY在源碼就是我們常說(shuō)的初始化容量10,此時(shí)該方法返回DEFAULT_CAPACITY,如果不是使用默認(rèn)構(gòu)造器初始化的話,則直接返回我們傳入的參數(shù)(也就是我們一開(kāi)始的size+1)。
到目前為止我們的底層數(shù)組elementData的容量仍然是0,并沒(méi)有進(jìn)行擴(kuò)容,接著調(diào)用ensureExplicitCapacity()方法,在該方法內(nèi)部首先調(diào)用modCount++表明此刻在修改ArrayList如果不懂modCount的含義,你可以看我的另一篇文章ArrayList源碼解析,
里面有講到modCount。接著判斷一下:如果我們傳進(jìn)來(lái)的參數(shù)minCapacity(size+1)大于我們當(dāng)前底層數(shù)組elementData的長(zhǎng)度(此時(shí)為0),則需要擴(kuò)容,接著調(diào)用了grow()方法進(jìn)行了擴(kuò)容。
在grow()方法中,首先通過(guò)將element的容量擴(kuò)容至原來(lái)的1.5倍(有時(shí)是小于1.5倍)(同時(shí)這里也是ArrayList的自動(dòng)擴(kuò)容機(jī)制),接著判斷如果擴(kuò)容后的容量仍舊小于minCapacity,就把minCapacity作為新容量,否則什么也不做,接著判斷如果新容量大于最大數(shù)組容量的話,繼續(xù)調(diào)用hugeCapacity()進(jìn)行擴(kuò)容(一般調(diào)用這個(gè)的話會(huì)爬出異常),最后通過(guò)Arrays.copyOf()進(jìn)行數(shù)組的擴(kuò)容。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java連接orcale數(shù)據(jù)庫(kù)示例分享
這篇文章主要介紹了java連接orcale數(shù)據(jù)庫(kù)示例,需要的朋友可以參考下2014-02-02java中Sources目錄Resources目錄的區(qū)別解讀
這篇文章主要介紹了java中Sources目錄Resources目錄的區(qū)別解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12SpringMVC中的@RequestMapping注解的使用詳細(xì)教程
@RequestMapping注解的作用就是將請(qǐng)求和處理請(qǐng)求的控制器方法關(guān)聯(lián)起來(lái),建立映射關(guān)系,本文主要來(lái)和大家詳細(xì)講講它的具體使用,感興趣的可以了解一下2023-07-07解決SpringBoot加載application.properties配置文件的坑
這篇文章主要介紹了SpringBoot加載application.properties配置文件的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08springboot 整合 freemarker代碼實(shí)例
這篇文章主要介紹了springboot 整合 freemarker代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10Spring Boot 與 Kotlin 使用JdbcTemplate連接MySQL數(shù)據(jù)庫(kù)的方法
本文介紹在Spring Boot基礎(chǔ)下配置數(shù)據(jù)源和通過(guò) JdbcTemplate 編寫(xiě)數(shù)據(jù)訪問(wèn)的示例。感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-01-01