欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java的ArrayList擴(kuò)容源碼解析

 更新時(shí)間:2024年01月11日 10:02:56   作者:好奇的7號(hào)  
這篇文章主要介紹了Java的ArrayList擴(kuò)容源碼解析,通過(guò)動(dòng)態(tài)擴(kuò)容,ArrayList能夠在添加元素時(shí)保持高效的性能,擴(kuò)容操作是有一定開銷的,但由于擴(kuò)容的時(shí)間復(fù)雜度為O(n),其中n是當(dāng)前元素個(gè)數(shù),所以平均情況下,每次添加元素的時(shí)間復(fù)雜度仍然是O(1),需要的朋友可以參考下

ArrayList擴(kuò)容源碼

1、擴(kuò)容原理概括

ArrayList的擴(kuò)容原理如下:

  • 初始容量:在創(chuàng)建ArrayList對(duì)象時(shí),默認(rèn)會(huì)分配一個(gè)初始容量。初始容量可以通過(guò)構(gòu)造函數(shù)進(jìn)行指定,若未指定,則默認(rèn)為10。例如,ArrayList<String> list = new ArrayList<>();會(huì)創(chuàng)建一個(gè)初始容量為10的ArrayList。
  • 添加元素:當(dāng)向ArrayList中添加元素時(shí),會(huì)先檢查當(dāng)前元素個(gè)數(shù)是否已經(jīng)達(dá)到了數(shù)組的容量上限。如果元素個(gè)數(shù)等于或超過(guò)了容量上限,就需要進(jìn)行擴(kuò)容。
  • 擴(kuò)容機(jī)制:擴(kuò)容時(shí),ArrayList會(huì)創(chuàng)建一個(gè)更大的新數(shù)組,并將原有的元素復(fù)制到新數(shù)組中。默認(rèn)情況下,新數(shù)組的大小是原來(lái)容量的1.5倍(即增長(zhǎng)50%)。例如,如果當(dāng)前容量為10,那么擴(kuò)容后的新容量為15。
  • 數(shù)組復(fù)制:在擴(kuò)容時(shí),ArrayList使用System.arraycopy()方法將原始數(shù)組中的元素復(fù)制到新的數(shù)組中。這是一個(gè)底層的高效數(shù)組復(fù)制方法,可以快速地將原有的數(shù)據(jù)移動(dòng)到新數(shù)組中。
  • 更新引用:在完成數(shù)組復(fù)制后,ArrayList會(huì)更新內(nèi)部的引用,指向新的數(shù)組。這樣,原先的數(shù)組就會(huì)被垃圾回收器回收。

通過(guò)動(dòng)態(tài)擴(kuò)容,ArrayList能夠在添加元素時(shí)保持高效的性能。擴(kuò)容操作是有一定開銷的,但由于擴(kuò)容的時(shí)間復(fù)雜度為O(n),其中n是當(dāng)前元素個(gè)數(shù),所以平均情況下,每次添加元素的時(shí)間復(fù)雜度仍然是O(1)。

同時(shí),擴(kuò)容的增長(zhǎng)因子(即容量的增加比例)也可以被修改,以滿足特定需求。

2、源碼解析

例如,對(duì)于如下list進(jìn)行添加元素,初始容量設(shè)置為5,添加6個(gè)元素:

ArrayList<String> list = new ArrayList<>(5);
list.add("1");
list.add("2");
list.add("3");
list.add("777");
list.add("888");
list.add("999");

對(duì)于一開始的前五個(gè)元素而言:

public boolean add(E e) {
        modCount++;
        add(e, elementData, size);//e是“1”,size是0,即目前元素?cái)?shù)量,也可以理解為數(shù)組的索引
        return true;
}
 
//add源碼:
private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)//當(dāng)元素?cái)?shù)量等于arraylist數(shù)組長(zhǎng)度,才grow擴(kuò)容
            elementData = grow();
        elementData[s] = e;//否則直接在索引位置賦值
        size = s + 1;//并將索引右移
}

但在第6個(gè)元素“999”添加進(jìn)去的時(shí)候,要進(jìn)入grow方法進(jìn)行擴(kuò)容:

private void add(E e, Object[] elementData, int s) { //e是“999”,s為5
        if (s == elementData.length)//已經(jīng)相等
            elementData = grow();//步入grow
        elementData[s] = e;
        size = s + 1;
}
 
//grow源碼:輸入size + 1
private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;//舊的數(shù)組大小
 
//接下來(lái),檢查當(dāng)前數(shù)組是否為空,或者不是使用默認(rèn)初始容量的空數(shù)組(即DEFAULTCAPACITY_EMPTY_ELEMENTDATA)。如果是空數(shù)組,則說(shuō)明是第一次添加元素,使用默認(rèn)初始容量。
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);//計(jì)算新數(shù)組大小
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
}
 
//ArraysSupport.newLength源碼:
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        // assert oldLength >= 0
        // assert minGrowth > 0
//minGrowth就是6 - 5 = 1,即,至少需要增大的容量
//prefGrowth為數(shù)組的舊容量的1/2
//求其max,一般為1/2。加上oldlength,所以為1.5倍
        int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
        if (newLength - MAX_ARRAY_LENGTH <= 0) {
            return newLength;
        }
        return hugeLength(oldLength, minGrowth);
    }
 
//最后調(diào)用Arrays.copyOf,內(nèi)部使用System.arraycopy()方法將原始數(shù)組中的元素復(fù)制到新的數(shù)組中

實(shí)現(xiàn)擴(kuò)容后,添加元素步驟同上,結(jié)束,return true

到此這篇關(guān)于Java的ArrayList擴(kuò)容源碼解析的文章就介紹到這了,更多相關(guān)ArrayList擴(kuò)容源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis執(zhí)行SQL命令的流程分析

    Mybatis執(zhí)行SQL命令的流程分析

    這篇文章主要介紹了Mybatis執(zhí)行SQL命令的流程分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • 詳解Spring Boot對(duì) Apache Pulsar的支持

    詳解Spring Boot對(duì) Apache Pulsar的支持

    Spring Boot通過(guò)提供spring-pulsar和spring-pulsar-reactive自動(dòng)配置支持Apache Pulsar,類路徑中這些依賴存在時(shí),Spring Boot自動(dòng)配置命令式和反應(yīng)式Pulsar組件,PulsarClient自動(dòng)注冊(cè),默認(rèn)連接本地Pulsar實(shí)例,感興趣的朋友一起看看吧
    2024-11-11
  • java簡(jiǎn)單坦克大戰(zhàn)制作代碼

    java簡(jiǎn)單坦克大戰(zhàn)制作代碼

    這篇文章主要介紹了java簡(jiǎn)單坦克大戰(zhàn)制作代碼,利用Java語(yǔ)言中的集合、Swing、線程等知識(shí)點(diǎn)編寫一個(gè)坦克大戰(zhàn)游戲,需要的朋友可以參考下
    2016-07-07
  • SpringBoot詳解整合MyBatis過(guò)程中可能遇到的問(wèn)題

    SpringBoot詳解整合MyBatis過(guò)程中可能遇到的問(wèn)題

    因?yàn)镾pring Boot框架開發(fā)的便利性,所以實(shí)現(xiàn)Spring Boot與數(shù)據(jù)訪問(wèn)層框架(例如MyBatis)的整合非常簡(jiǎn)單,主要是引入對(duì)應(yīng)的依賴啟動(dòng)器,并進(jìn)行數(shù)據(jù)庫(kù)相關(guān)參數(shù)設(shè)置即可
    2022-07-07
  • SpringBoot中注解@ConfigurationProperties與@Value的區(qū)別與使用詳解

    SpringBoot中注解@ConfigurationProperties與@Value的區(qū)別與使用詳解

    本文主要介紹了SpringBoot中注解@ConfigurationProperties與@Value的區(qū)別與使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 深入理解Java中的volatile關(guān)鍵字(總結(jié)篇)

    深入理解Java中的volatile關(guān)鍵字(總結(jié)篇)

    volatile這個(gè)關(guān)鍵字,不僅僅在Java語(yǔ)言中有,在很多語(yǔ)言中都有的,而且其用法和語(yǔ)義也都是不盡相同的。這篇文章主要介紹了Java中的volatile關(guān)鍵字,需要的朋友可以參考下
    2018-10-10
  • Java核心庫(kù)實(shí)現(xiàn)簡(jiǎn)單的AOP

    Java核心庫(kù)實(shí)現(xiàn)簡(jiǎn)單的AOP

    這篇文章主要介紹了如何用Java核心庫(kù)實(shí)現(xiàn)簡(jiǎn)單的AOP,幫助大家為了更好的理解和學(xué)習(xí)AOP的思想,感興趣的朋友可以了解下
    2020-08-08
  • 詳解Java 微服務(wù)架構(gòu)

    詳解Java 微服務(wù)架構(gòu)

    這篇文章主要介紹了Java 微服務(wù)架構(gòu)的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2021-02-02
  • Java8新特性Lambda表達(dá)式的一些復(fù)雜用法總結(jié)

    Java8新特性Lambda表達(dá)式的一些復(fù)雜用法總結(jié)

    lambda表達(dá)式是JAVA8中提供的一種新的特性,它支持Java也能進(jìn)行簡(jiǎn)單的“函數(shù)式編程”。 下面這篇文章主要給大家介紹了關(guān)于Java8新特性Lambda表達(dá)式的一些復(fù)雜用法的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-07-07
  • Java?代碼本地設(shè)置Hadoop用戶名密碼的方法

    Java?代碼本地設(shè)置Hadoop用戶名密碼的方法

    在Hadoop環(huán)境中,通常使用Kerberos進(jìn)行身份驗(yàn)證,這篇文章主要介紹了Java?代碼本地設(shè)置Hadoop用戶名密碼的方法,需要的朋友可以參考下
    2024-08-08

最新評(píng)論