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

add方法理解ArrayList的擴(kuò)容機(jī)制

 更新時間:2023年03月07日 08:32:53   作者:ovO  
這篇文章主要為大家介紹了add方法理解ArrayList的擴(kuò)容機(jī)制示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

ArrayList的構(gòu)造方法(前置知識)

可快速過

一些基本成員變量:

// 默認(rèn)初始大小
private static final int DEFAULT_CAPACITY = 10;
// 空數(shù)組 用于空實例
private static final Object[] EMPTY_ELEMENTDATA = new Object[0];
// 用于默認(rèn)大小空實例的共享空數(shù)組實例。
// 我們把它從EMPTY_ELEMENTDATA數(shù)組中區(qū)分出來,以知道在添加第一個元素時容量需要增加多少。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new Object[0];
// 保存ArrayList數(shù)據(jù)的數(shù)組
transient Object[] elementData;
// 大小
private int size;
// 數(shù)組的最大長度
private static final int MAX_ARRAY_SIZE = 2147483639;

構(gòu)造方法:

   /**
     * 默認(rèn)初始容量大小
     */
    private static final int DEFAULT_CAPACITY = 10;
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    /**
     *默認(rèn)構(gòu)造函數(shù),使用初始容量10構(gòu)造一個空列表(無參數(shù)構(gòu)造)
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    /**
     * 帶初始容量參數(shù)的構(gòu)造函數(shù)。(用戶自己指定容量)
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {//初始容量大于0
            //創(chuàng)建initialCapacity大小的數(shù)組
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {//初始容量等于0
            //創(chuàng)建空數(shù)組
            this.elementData = EMPTY_ELEMENTDATA;
        } else {//初始容量小于0,拋出異常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
   /**
    *構(gòu)造包含指定collection元素的列表,這些元素利用該集合的迭代器按順序返回
    *如果指定的集合為null,throws NullPointerException。
    */
     public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

ArrayList的add方法(理解擴(kuò)容機(jī)制)

add 添加元素

    /**
     * 將指定的元素追加到此列表的末尾。
     */
    public boolean add(E e) {
        // 添加元素之前,先試探,容量夠不夠
        // Increments modCount!! 這里有個failfast機(jī)制
        // 簡而言之就是并發(fā)場景下通過modcount的值判斷當(dāng)前的操作是否是最新的modcount的數(shù)據(jù)
        ensureCapacityInternal(size + 1);  
        //這里看到ArrayList添加元素的實質(zhì)就相當(dāng)于為數(shù)組賦值
        elementData[size++] = e;
        return true;
    }

得到最小擴(kuò)容量

我們接下來看看這個“試探容量的方法”ensureCapacityInternal()怎么實現(xiàn)的

我們約定一個值,也就是傳參進(jìn)來的size+1,叫minCapacity(最小需要容量)

   //得到最小擴(kuò)容量    就是你至少要擴(kuò)容至這么多,才能容納下我的數(shù)據(jù)
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
              // 獲取默認(rèn)的容量和傳入?yún)?shù)的較大值
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        ensureExplicitCapacity(minCapacity);
    }

當(dāng)要add進(jìn)第1個元素時,minCapacity為1,在Math.max()方法比較后,minCapacity為10。

判斷是否需要擴(kuò)容

然后是ensureExplicitCapacity():

  //判斷是否需要擴(kuò)容
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            //調(diào)用grow方法進(jìn)行擴(kuò)容,調(diào)用此方法代表已經(jīng)開始擴(kuò)容了
            grow(minCapacity);
    }

我們來梳理一下:

  • 當(dāng)我們要 add 進(jìn)第 1 個元素到 ArrayList 時,elementData.length為0 (因為還是一個空的 list),因為執(zhí)行了 ensureCapacityInternal() 方法 ,所以minCapacity此時為 10。此時,minCapacity - elementData.length > 0成立,所以會進(jìn)入 grow(minCapacity) 方法,此時數(shù)組容量變?yōu)?0
  • 當(dāng) add 第 2 個元素時,minCapacity 為 2,此時 elementData.length(容量)在添加第一個元素后擴(kuò)容成 10 了。此時,minCapacity - elementData.length > 0 不成立,所以不會進(jìn)入 (執(zhí)行)grow(minCapacity) 方法。
  • 添加第 3、4···到第10個元素時,依然不會執(zhí)行 grow()方法,數(shù)組容量都為10。
  • 直到添加第 11 個元素,minCapacity(為 11)比 elementData.length(為 10)要大。進(jìn)入 grow 方法進(jìn)行擴(kuò)容。

擴(kuò)容方法

按照elementData.length(newCapacity)擴(kuò)容1.5倍,然后看看夠不夠minCapacity

不夠的話,newCapacity就=minCapacity

hugeCapacity()比較一下newCapacity是否超過MAX_ARRAY_SIZE,超過就賦為Integer.MAX_VALUE

然后就進(jìn)行擴(kuò)容,Arrays.copyof方法

    /**
     * 要分配的最大數(shù)組大小
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    /**
     * ArrayList擴(kuò)容的核心方法。
     */
    private void grow(int minCapacity) {
        // oldCapacity為舊容量,newCapacity為新容量
        int oldCapacity = elementData.length;
        //將oldCapacity 右移一位,其效果相當(dāng)于oldCapacity /2,
        //我們知道位運(yùn)算的速度遠(yuǎn)遠(yuǎn)快于整除運(yùn)算,整句運(yùn)算式的結(jié)果就是將新容量更新為舊容量的1.5倍,
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //然后檢查新容量是否大于最小需要容量,若還是小于最小需要容量,那么就把最小需要容量當(dāng)作數(shù)組的新容量,
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
       // 如果新容量大于 MAX_ARRAY_SIZE,進(jìn)入(執(zhí)行) `hugeCapacity()` 方法來比較 minCapacity 和 MAX_ARRAY_SIZE,
       //如果minCapacity大于最大容量
       //則新容量則為`Integer.MAX_VALUE`,否則,新容量大小則為 MAX_ARRAY_SIZE 即為 `Integer.MAX_VALUE - 8`。
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

int newCapacity = oldCapacity + (oldCapacity >> 1),所以 ArrayList 每次擴(kuò)容之后容量都會變?yōu)樵瓉淼?1.5 倍左右(oldCapacity 為偶數(shù)就是 1.5 倍,否則是 1.5 倍左右)! 奇偶不同,比如 :10+10/2 = 15, 33+33/2=49。如果是奇數(shù)的話會丟掉小數(shù)

tips:

  • java 中的 length屬性是針對數(shù)組說的,比如說你聲明了一個數(shù)組,想知道這個數(shù)組的長度則用到了 length 這個屬性.
  • java 中的 length() 方法是針對字符串說的,如果想看這個字符串的長度則用到 length() 這個方法.
  • java 中的 size() 方法是針對泛型集合說的,如果想看這個泛型有多少個元素,就調(diào)用此方法來查看!

資料:javaguide

以上就是add方法理解ArrayList的擴(kuò)容機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于add方法ArrayList擴(kuò)容的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot JPA出現(xiàn)錯誤:No identifier specified for en解決方案

    SpringBoot JPA出現(xiàn)錯誤:No identifier specified&nb

    這篇文章主要介紹了SpringBoot JPA出現(xiàn)錯誤:No identifier specified for en解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • springboot]logback日志框架配置教程

    springboot]logback日志框架配置教程

    這篇文章主要介紹了springboot]logback日志框架配置,logback既可以通過application配置文件進(jìn)行日志的配置,又可以通過logback-spring.xml進(jìn)行日志的配置,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2022-04-04
  • Java中Parser的用法

    Java中Parser的用法

    這篇文章主要介紹了Java?Parser使用指南,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • 使用easyexcel導(dǎo)出的excel文件,使用poi讀取時異常處理方案

    使用easyexcel導(dǎo)出的excel文件,使用poi讀取時異常處理方案

    這篇文章主要介紹了使用easyexcel導(dǎo)出的excel文件,使用poi讀取時異常處理方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java Runtime類詳解_動力節(jié)點(diǎn)Java學(xué)院整理

    Java Runtime類詳解_動力節(jié)點(diǎn)Java學(xué)院整理

    Runtime類封裝了運(yùn)行時的環(huán)境。每個 Java 應(yīng)用程序都有一個 Runtime 類實例,使應(yīng)用程序能夠與其運(yùn)行的環(huán)境相連接。下面通過本文給大家分享Java Runtime類詳解,需要的朋友參考下吧
    2017-04-04
  • 詳解Servlet 3.0/3.1 中的異步處理

    詳解Servlet 3.0/3.1 中的異步處理

    這篇文章主要介紹了詳解Servlet 3.0/3.1 中的異步處理,實例分析了servlet 3.0異步處理的技巧,非常具有實用價值,需要的朋友可以參考下
    2017-04-04
  • Nacos單機(jī)版安裝啟動的全流程

    Nacos單機(jī)版安裝啟動的全流程

    這篇文章主要介紹了Nacos單機(jī)版安裝啟動的全流程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java中的vector類使用示例小結(jié)

    Java中的vector類使用示例小結(jié)

    Vector與ArrayList的實現(xiàn)基本相似,同樣是基于動態(tài)數(shù)組,同樣是需要擴(kuò)容,下面舉了三個簡短的例子來幫助大家理解vertor:
    2016-05-05
  • Java選擇排序和垃圾回收機(jī)制詳情

    Java選擇排序和垃圾回收機(jī)制詳情

    這篇文章主要介紹Java選擇排序和垃圾回收機(jī)制,創(chuàng)建對象就會占據(jù)內(nèi)存,如果程序在執(zhí)行過程中不能再使用某個對象,這個對象是徒耗內(nèi)存的垃圾,下面來看看文章具體內(nèi)容吧
    2021-10-10
  • IDEA將Maven項目中指定文件夾下的xml等文件編譯進(jìn)classes的方法

    IDEA將Maven項目中指定文件夾下的xml等文件編譯進(jìn)classes的方法

    這篇文章主要介紹了IDEA將Maven項目中指定文件夾下的xml等文件編譯進(jìn)classes的方法,幫助大家更好的利用IDEA進(jìn)行Java的開發(fā)學(xué)習(xí),感興趣的朋友可以了解下
    2021-01-01

最新評論