最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

新手入門(mén)了解ArrayList擴(kuò)容機(jī)制

 更新時(shí)間:2020年10月27日 16:40:10   作者:愛(ài)編程DE文兄  
這篇文章主要介紹了新手入門(mén)了解ArrayList擴(kuò)容機(jī)制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

我們下面用最簡(jiǎn)單的代碼創(chuàng)建ArrayList并添加11個(gè)元素,并 一 一 講解底層源碼;在說(shuō)之前,給大家先普及一些小知識(shí):

  》ArrayList底層是用數(shù)組來(lái)實(shí)現(xiàn)的

  》數(shù)組一旦創(chuàng)建后,大小就是固定的,如果超出了數(shù)組大小后,就會(huì)創(chuàng)建一個(gè)新的數(shù)組

  》接下來(lái)所謂數(shù)組的擴(kuò)容實(shí)質(zhì)上是重新創(chuàng)建一個(gè)大小更大的新數(shù)組

@Test
  public void testArrayList() {
    //創(chuàng)建一個(gè)泛型為String的ArrayList(這里泛型是什么不重要)
    ArrayList<String> list = new ArrayList<String>();
    //依次添加11個(gè)元素
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");
    list.add("6");
    list.add("7");
    list.add("8");
    list.add("9");
    list.add("10");
    list.add("11");
  }

上面的代碼中,我們就只調(diào)用了add(),在看add()源碼前,我必須給你們先介紹一些在A(yíng)rrayList的常量和變量,因?yàn)樵诮酉聛?lái)的源碼中會(huì)涉及到這些,怕你們到時(shí)一臉蒙

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

  》DEFAULT_CAPACITY:default_capcity,默認(rèn)的容量大小,也就是當(dāng)你第一次創(chuàng)建數(shù)組并往里面添加第一個(gè)元素時(shí),數(shù)組的默認(rèn)容量大小

  》DEFAULTCAPACITY_EMPTY_ELEMENTDATA:defaultcapacity_empty_elementdata是默認(rèn)的空數(shù)組,他的作用是當(dāng)elementData為{},即空數(shù)組時(shí),把它賦值給elementData,要是理解不了,請(qǐng)你往下繼續(xù)看!

  》elementData:表示的就是當(dāng)前存儲(chǔ)元素的數(shù)組

  》size:他表示當(dāng)前還沒(méi)有添加新元素前的數(shù)組中有效的元素個(gè)數(shù),比如說(shuō)數(shù)組長(zhǎng)度為10,只保存了5個(gè)元素,那有效長(zhǎng)度就是5

  》MAX_ARRAY_SIZE:最大數(shù)組長(zhǎng)度,它用來(lái)標(biāo)識(shí)當(dāng)前數(shù)組可保存元素的最大長(zhǎng)度,值為Integer_MAX_VALUE -8,即2147483647 - 8 ,這里的 8 代表8字節(jié)用來(lái)保存數(shù)組本身的內(nèi)存大小。

現(xiàn)在我們進(jìn)入到add()里面看他們具體如何實(shí)現(xiàn)的,如下代碼:

public boolean add(E e) {
    
    ensureCapacityInternal(size + 1); // Increments modCount!!
    elementData[size++] = e;
    return true;
  }

  》ensureCapacityInternal(size + 1):這個(gè)方法意為“確保內(nèi)部變量”,什么意思呢?他是用來(lái)判斷當(dāng)前數(shù)組的容量是否足夠,不足就擴(kuò)容;等下我們會(huì)進(jìn)入這個(gè)方法來(lái)看他如何具體實(shí)現(xiàn)的,size表示當(dāng)前還未添加新元素前的數(shù)組有效元素個(gè)數(shù),而size+1表示傳入當(dāng)前數(shù)組的最小容量(有效長(zhǎng)度)
  》elementData[size++] = e:這段語(yǔ)句意思是給數(shù)組做賦值操作,簡(jiǎn)單說(shuō)就是給數(shù)組添加元素;比如說(shuō)當(dāng)前數(shù)組已經(jīng)有3個(gè)元素了,那現(xiàn)在再添加一個(gè)元素a,則這一步為elementData[3]=a;

  》return true:代表添加成功;

現(xiàn)在我們就進(jìn)入到ensureCapacityInternal(),如下代碼:

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
  }

這里面涉及兩個(gè)方法ensureExplicitCapacity()和calculateCapacity():

  》calculateCapacity():計(jì)算容量,它用來(lái)計(jì)算當(dāng)前的數(shù)組所需的最小容量minCapacity, 你可以理解為當(dāng)前數(shù)組的有效長(zhǎng)度;源碼如下:

private static int calculateCapacity(Object[] elementData, int minCapacity) {    //若傳入的是個(gè)空數(shù)組,則返回的是最小容量 是 默認(rèn)容量(10) 和 當(dāng)前最小容量(0)之間的最大值
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
      return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
  }

PS:第一次添加元素時(shí)calculateCapacity返回的最小容量minCapacity是10,從第二次開(kāi)始minCapacity為2,第三次為3,依次類(lèi)推..在這里第一次返回10大家不要糾結(jié)它的意義,重點(diǎn)在第二次及之后表示的意思

  》ensureExplicitCapacity():判斷是否需要擴(kuò)容;查看它的源碼:

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code當(dāng)最小容量大于當(dāng)前的數(shù)組大小時(shí)
    if (minCapacity - elementData.length > 0)      //計(jì)算擴(kuò)容后的數(shù)組大小
      grow(minCapacity);
  }

我們第一次list.add(),最小容量minCapacity是10,elementData.length長(zhǎng)度為0,所以條件成立,進(jìn)入grow()(第二次minCapacity是2,elementData.length為10,條件不成立就不再擴(kuò)容了;當(dāng)?shù)?1次時(shí),11>10,又可以擴(kuò)容了)

private void grow(int minCapacity) {
    // 得到當(dāng)前數(shù)組的大小,即老數(shù)組大小
    int oldCapacity = elementData.length;
    //將舊數(shù)組大小+舊數(shù)組/2,即舊數(shù)組的1.5倍是新數(shù)組的大小(先不要在意>>1的意思,你只要知道oldCapacity >> 1表示oldCapacity/2就行)
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //如果擴(kuò)容后的是數(shù)組大小還是小于最小所需容量,直接讓minCapacity賦值到新容量
    if (newCapacity - minCapacity < 0)
      newCapacity = minCapacity;
    //若新容量大小大于數(shù)組長(zhǎng)度的最大預(yù)設(shè)值;由于擴(kuò)容后是原數(shù)組的1.5倍,則非常有可能會(huì)溢出這個(gè)預(yù)設(shè)值
    if (newCapacity - MAX_ARRAY_SIZE > 0)
      newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    //上面都是為了確定最終的新容量的大小,這個(gè)方法是真正的擴(kuò)容實(shí)現(xiàn)
    elementData = Arrays.copyOf(elementData, newCapacity);
  }

相信大家這上面大部分都能夠理解,可能就一個(gè)地方不太清楚:當(dāng)newCapacity > MAX_ARRAY_SIZE(新容量大于預(yù)設(shè)值較特殊的情況,一般數(shù)組長(zhǎng)度不會(huì)擴(kuò)容到這么大)時(shí)調(diào)用hugeCapacity有啥用?我們看下hugeCapacity()的源碼:

private static int hugeCapacity(int minCapacity) {
    //若最小容量小于0的情況,拋出異常
    if (minCapacity < 0) // overflow
      throw new OutOfMemoryError();
    //若最小容量>最大預(yù)設(shè)值,返回Integer.Max_VALUE,否則是MAX_ARRAY_SIZE(Integer.Max_VALUE-8)
    return (minCapacity > MAX_ARRAY_SIZE) ?
      Integer.MAX_VALUE :
      MAX_ARRAY_SIZE;
  }

hugeCapacity()是用來(lái)限制新容量的大小的,是不能超出Integer.MAX_VALUE值的,最后說(shuō)一點(diǎn),數(shù)組的最大長(zhǎng)度并不是MAX_ARRAY_SIZE,而是Integer.MAX_VALUE。

  》Arrays.copyOf(elementData, newCapacity),就不看源碼了,簡(jiǎn)單說(shuō)一下:它這個(gè)方法能返回一個(gè)擴(kuò)容后的數(shù)組,將舊數(shù)組elementData的數(shù)據(jù)復(fù)制到長(zhǎng)度為newCapacity的新數(shù)組中。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 排序算法圖解之Java冒泡排序及優(yōu)化

    排序算法圖解之Java冒泡排序及優(yōu)化

    冒泡排序即通過(guò)對(duì)待排序的序列從前往后,依次比較相鄰元素的值,若發(fā)現(xiàn)逆序則交換位置,使較大的元素逐漸移動(dòng)到后部。本文通過(guò)圖片和示例介紹了冒泡排序的實(shí)現(xiàn)及優(yōu)化,需要的可以參考一下
    2022-11-11
  • SpringBoot實(shí)現(xiàn)二維碼掃碼登錄的原理及項(xiàng)目實(shí)踐

    SpringBoot實(shí)現(xiàn)二維碼掃碼登錄的原理及項(xiàng)目實(shí)踐

    本文主要介紹了SpringBoot實(shí)現(xiàn)二維碼掃碼登錄的原理及項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • spring@value注入配置文件值失敗的原因分析

    spring@value注入配置文件值失敗的原因分析

    這篇文章主要介紹了spring@value注入配置文件值失敗的原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 如何設(shè)置springboot啟動(dòng)端口

    如何設(shè)置springboot啟動(dòng)端口

    spring boot是個(gè)好東西,可以不用容器直接在main方法中啟動(dòng),而且無(wú)需配置文件,方便快速搭建環(huán)境。下面給大家介紹springboot啟動(dòng)端口的設(shè)置方法和spring boot創(chuàng)建應(yīng)用端口沖突8080 問(wèn)題,感興趣的朋友一起看看吧
    2017-08-08
  • SpringBoot整合Mongodb實(shí)現(xiàn)增刪查改的方法

    SpringBoot整合Mongodb實(shí)現(xiàn)增刪查改的方法

    這篇文章主要介紹了SpringBoot整合Mongodb實(shí)現(xiàn)簡(jiǎn)單的增刪查改,MongoDB是一個(gè)以分布式數(shù)據(jù)庫(kù)為核心的數(shù)據(jù)庫(kù),因此高可用性、橫向擴(kuò)展和地理分布是內(nèi)置的,并且易于使用。況且,MongoDB是免費(fèi)的,開(kāi)源的,感興趣的朋友跟隨小編一起看看吧
    2022-05-05
  • eclipse實(shí)現(xiàn)可認(rèn)證的DH密鑰交換協(xié)議

    eclipse實(shí)現(xiàn)可認(rèn)證的DH密鑰交換協(xié)議

    這篇文章主要介紹了eclipse實(shí)現(xiàn)可認(rèn)證的DH密鑰交換協(xié)議,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • Spring Boot @Conditional注解用法示例介紹

    Spring Boot @Conditional注解用法示例介紹

    這篇文章主要給大家介紹了關(guān)于Spring Boot @Conditional注解用法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Mybatis-Plus實(shí)體類(lèi)注解方法與mapper層和service層的CRUD方法

    Mybatis-Plus實(shí)體類(lèi)注解方法與mapper層和service層的CRUD方法

    CRUD是指在做計(jì)算處理時(shí)的增加(Create)、讀取查詢(xún)(Retrieve)、更新(Update)和刪除(Delete)幾個(gè)單詞的首字母簡(jiǎn)寫(xiě)。主要被用在描述軟件系統(tǒng)中DataBase或者持久層的基本操作功能,下面讓我們一起看看吧
    2022-03-03
  • java發(fā)起http請(qǐng)求調(diào)用post與get接口的方法實(shí)例

    java發(fā)起http請(qǐng)求調(diào)用post與get接口的方法實(shí)例

    在實(shí)際開(kāi)發(fā)過(guò)程中,我們經(jīng)常需要調(diào)用對(duì)方提供的接口或測(cè)試自己寫(xiě)的接口是否合適,下面這篇文章主要給大家介紹了關(guān)于java發(fā)起http請(qǐng)求調(diào)用post與get接口的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • Java報(bào)錯(cuò):Java.io.FileNotFoundException解決方法

    Java報(bào)錯(cuò):Java.io.FileNotFoundException解決方法

    這篇文章主要介紹了Java.io.FileNotFoundException的產(chǎn)生原因和解決方法,造成這個(gè)報(bào)錯(cuò)的原因可能有文件路徑錯(cuò)誤、文件被刪除或移動(dòng)和權(quán)限問(wèn)題,文中將解決的辦法介紹的非常詳細(xì),需要的朋友可以參考下
    2024-12-12

最新評(píng)論

定兴县| 北川| 眉山市| 昭平县| 陆良县| 万盛区| 丹寨县| 昌吉市| 商洛市| 囊谦县| 贵阳市| 鹤山市| 全南县| 巩留县| 曲阜市| 洛宁县| 农安县| 沙湾县| 赣榆县| 玉树县| 来宾市| 黔东| 九寨沟县| 紫金县| 长丰县| 温泉县| 满洲里市| 合江县| 祁门县| 遂宁市| 阳泉市| 大竹县| 兰州市| 台东县| 兰考县| 彰化县| 明溪县| 天峻县| 台中市| 射阳县| 张家港市|