自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

ArrayList 源碼淺析

網絡
ArrayList作為我們開發(fā)中最常用的集合,作為極高頻次使用的類,我們不妨閱讀源碼一談究竟。

前言

ArrayList作為我們開發(fā)中最常用的集合,作為極高頻次使用的類,我們不妨閱讀源碼一談究竟。

介紹

ArrayList繼承關系如下

AaaryList主要實現(xiàn)了List接口,同時標記為可以序列化Serializable、可復制CloneAble、支持隨機訪問RandomAccess。

幾個重要的成員變量

  1. /**     * 默認容量     */    private static final int DEFAULT_CAPACITY = 10;    /**     * 用于空實例的共享空數(shù)組實例。     */    private static final Object[] EMPTY_ELEMENTDATA = {};    /**     * 用于默認大小的空實例的共享空數(shù)組實例。我們將其與空元素數(shù)據(jù)區(qū)分開來,以了解添加第一個元素時要膨脹多少。     */    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};    /**     * 存儲ArrayList元素的數(shù)組緩沖區(qū)。ArrayList的容量是此數(shù)組緩沖區(qū)的長度。     */    transient Object[] elementData; // non-private to simplify nested class access    /**     * ArrayList的大?。ㄋ脑財?shù))。     */    private int size; 

數(shù)據(jù)結構

ArrayList底層就是一個數(shù)組,數(shù)組會隨著數(shù)據(jù)的增長而擴容,數(shù)組的擴容就是建立一個新的容量大的數(shù)組,然后把舊數(shù)組上面的數(shù)據(jù)復制進新數(shù)組。關于擴容,后面會詳細講解。

因為是數(shù)組,所以支持隨機訪問,且有序。

常用方法

ArrayList()無參構造方法

  1. public ArrayList() {        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;    } 

初始化數(shù)組為一個空數(shù)組。與空元素數(shù)據(jù)區(qū)分開來,以了解添加第一個元素時要膨脹多少。

add(E e) 添加元素

將指定的元素追加到此列表的末尾

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

  1. private static int calculateCapacity(Object[] elementData, int minCapacity) {        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {            return Math.max(DEFAULT_CAPACITY, minCapacity);        }        return minCapacity;    }    private void ensureCapacityInternal(int minCapacity) {        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));    }    private void ensureExplicitCapacity(int minCapacity) {        modCount++;        // overflow-conscious code        if (minCapacity - elementData.length > 0)            grow(minCapacity);    } 

當添加元素,會先檢查是否超出容量,如果超出,則需要擴容。

當?shù)谝淮翁砑釉貢r,size為默認值0,會計算出一個最小容量minCapacity,如果是無參構造創(chuàng)建的,則會取默認的容量10,

Math.max(DEFAULT_CAPACITY, minCapacity),這里傳入的minCapacity為0,所以獲取更大的10。

如果計算出的最小容量大于原容量minCapacity - elementData.length > 0,則會進行擴容。

  1. private void grow(int minCapacity) {        // overflow-conscious code        int oldCapacity = elementData.length;        int newCapacity = oldCapacity + (oldCapacity >> 1);        if (newCapacity - minCapacity < 0)            newCapacity = minCapacity;        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);    } 

擴容算法是,擴為老容量的1.5倍,如果擴容后的容量仍然小于需要的最小容量minCapacity,則新的容量就取最小容量。

如果擴容后的大小超過最大容量,則會進行下面的操作

  1. private static int hugeCapacity(int minCapacity) {        if (minCapacity < 0// overflow            throw new OutOfMemoryError();        return (minCapacity > MAX_ARRAY_SIZE) ?            Integer.MAX_VALUE :            MAX_ARRAY_SIZE;    } 

計算出擴容后的容量后,進行擴容,也就是,新建一個數(shù)組初始化為新容量,然后復制舊元素到新數(shù)組。elementData = Arrays.copyOf(elementData, newCapacity);

  1. public static <T> T[] copyOf(T[] original, int newLength) {        return (T[]) copyOf(original, newLength, original.getClass());    } 
  1. public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {        @SuppressWarnings("unchecked")        T[] copy = ((Object)newType == (Object)Object[].class)            ? (T[]) new Object[newLength]            : (T[]) Array.newInstance(newType.getComponentType(), newLength);        System.arraycopy(original, 0, copy, 0,                         Math.min(original.length, newLength));        return copy;    } 

為什么不能在forEach里面修改列表

ArrayList在新增、刪除元素都會執(zhí)行modCount++

modCount定義在ArrayList的父類AbstractList。

  1. /**     * 此列表在結構上被修改的次數(shù)。結構修改是指那些改變列表大小的修改,或者以某種方式干擾列表,使得正在進行的迭代可能產生不正確的結果。 迭代器和列表迭代器方法返回的迭代器和列表迭代器實現(xiàn)使用此字段。如果此字段的值意外更改,迭代器(或列表迭代器)將拋出ConcurrentModificationException以響應下一個、刪除、上一個、設置或添加操作。這提供了快速失效行為,而不是在迭代過程中面對并發(fā)修改時的非確定性行為。 子類使用此字段是可選的。如果子類希望提供fail fast迭代器(和列表迭代器),那么它只需在add(int,E)和remove(int)方法(以及它重寫的任何其他方法,這些方法會導致列表的結構修改)中增加該字段。對add(int,E)或remove(int)的單個調用只能向該字段添加一個,否則迭代器(和列表迭代器)將拋出虛假的ConcurrentModificationException。如果實現(xiàn)不希望提供故障快速迭代器,則可以忽略此字段。     */    protected transient int modCount = 0

然后我們來看下forEach的實現(xiàn)。

  1. @Override    public void forEach(Consumer<? super E> action) {        Objects.requireNonNull(action);        final int expectedModCount = modCount;        @SuppressWarnings("unchecked")        final E[] elementData = (E[]) this.elementData;        final int size = this.size;        for (int i=0; modCount == expectedModCount && i < size; i++) {            action.accept(elementData[i]);        }        if (modCount != expectedModCount) {            throw new ConcurrentModificationException();        }    } 

在遍歷前,會暫存modCount值,每次循環(huán)都判斷下modCount是否有更改,若更改了,里面跳出循環(huán),隨后拋出異常。

責任編輯:梁菲 來源: 阿里云云棲號
相關推薦

2009-08-14 17:45:52

C# ArrayLis

2022-09-27 18:56:28

ArrayList數(shù)組源代碼

2020-12-14 08:03:52

ArrayList面試源碼

2017-02-27 09:03:37

Mesos架構源碼

2021-07-20 10:26:53

源碼底層ArrayList

2011-04-19 15:38:16

MongodbCursor

2009-07-08 14:06:22

ClassLoaderJDK源碼

2011-12-02 13:04:06

Java

2021-05-26 05:22:09

Virtual DOMSnabbdom虛擬DOM

2009-07-08 12:53:29

JDK源碼Java.lang.B

2017-07-17 11:52:54

jQuery源碼分析前端框架類庫

2018-08-20 16:00:23

MySQL并發(fā)控制MVCC

2011-03-14 09:33:35

Mono

2023-09-08 13:46:12

ArrayList數(shù)據(jù)存儲容器

2009-12-03 17:43:27

Linux服務器

2021-07-29 12:05:18

Vue3Api前端

2009-08-21 17:53:25

C#網絡編程客戶端程序

2009-08-12 18:35:36

C# ArrayLis

2009-08-21 17:39:20

服務器端程序C#網絡編程

2025-01-07 08:11:06

ArrayArrayList場景
點贊
收藏

51CTO技術棧公眾號