JDK1.8源碼分析之ArrayList

上傳人:文*** 文檔編號:62181528 上傳時間:2022-03-14 格式:DOCX 頁數(shù):9 大?。?3.87KB
收藏 版權(quán)申訴 舉報 下載
JDK1.8源碼分析之ArrayList_第1頁
第1頁 / 共9頁
JDK1.8源碼分析之ArrayList_第2頁
第2頁 / 共9頁
JDK1.8源碼分析之ArrayList_第3頁
第3頁 / 共9頁

下載文檔到電腦,查找使用更方便

0 積分

下載資源

還剩頁未讀,繼續(xù)閱讀

資源描述:

《JDK1.8源碼分析之ArrayList》由會員分享,可在線閱讀,更多相關《JDK1.8源碼分析之ArrayList(9頁珍藏版)》請在裝配圖網(wǎng)上搜索。

1、文檔供參考,可復制、編制,期待您的好評與關注! JDK1.8源碼分析之ArrayList 一、前言   分析了Map中主要的類之后,下面我們來分析Collection下面幾種常見的類,如ArrayList、LinkedList、HashSet、TreeSet等。下面通過JDK源碼來一起分析ArrayList底層是如何實現(xiàn)的。(PS:把JVM看完了之后終于可以有成片的時間來閱讀源碼了,感覺簡直不能更爽)。 二、ArrayList數(shù)據(jù)結(jié)構(gòu)   分析一個類的時候,數(shù)據(jù)結(jié)構(gòu)往往是它的靈魂所在,理解底層的數(shù)據(jù)結(jié)構(gòu)其實就理解了該類的實現(xiàn)思路,具體的實現(xiàn)細節(jié)再具體分析。   ArrayLis

2、t的數(shù)據(jù)結(jié)構(gòu)如下:      說明:底層的數(shù)據(jù)結(jié)構(gòu)就是數(shù)組,數(shù)組元素類型為Object類型,即可以存放所有類型數(shù)據(jù)。我們對ArrayList類的實例的所有的操作底層都是基于數(shù)組的。下面我們來分析通過數(shù)組是如何保證庫函數(shù)的正確實現(xiàn)的。 三、ArrayList源碼分析   3.1 類的繼承關系 public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable   說明:ArrayList繼承AbstractList抽象父類

3、,實現(xiàn)了List接口(規(guī)定了List的操作規(guī)范)、RandomAccess(可隨機訪問)、Cloneable(可拷貝)、Serializable(可序列化)。   3.2 類的屬性   ? public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable { // 版本號 private static final long serialVersionUID = 868345258112

4、2892189L; // 缺省容量 private static final int DEFAULT_CAPACITY = 10; // 空對象數(shù)組 private static final Object[] EMPTY_ELEMENTDATA = {}; // 缺省空對象數(shù)組 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 元素數(shù)組 transient Object[] elementData; // 實際

5、元素大小,默認為0 private int size; // 最大數(shù)組容量 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; } View Code   說明:類的屬性中核心的屬性為elementData,類型為Object[],用于存放實際元素,并且被標記為transient,也就意味著在序列化的時候,此字段是不會被序列化的。   3.3 類的構(gòu)造函數(shù)   1. ArrayList(int)型構(gòu)造函數(shù)   ? public ArrayList(int initi

6、alCapacity) { if (initialCapacity > 0) { // 初始容量大于0 this.elementData = new Object[initialCapacity]; // 初始化元素數(shù)組 } else if (initialCapacity == 0) { // 初始容量為0 this.elementData = EMPTY_ELEMENTDATA; // 為空對象數(shù)組 } else { // 初始容量小于0,拋出異常 throw

7、 new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } View Code   說明:指定elementData數(shù)組的大小,不允許初始化大小小于0,否則拋出異常。   2. ArrayList()型構(gòu)造函數(shù) ? public ArrayList() { // 無參構(gòu)造函數(shù),設置元素數(shù)組為空 this.elementData

8、= DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } View Code   說明:當未指定初始化大小時,會給elementData賦值為空集合。   3. ArrayList(Collection)型構(gòu)造函數(shù)   ? public ArrayList(Collection c) { // 集合參數(shù)構(gòu)造函數(shù) elementData = c.toArray(); // 轉(zhuǎn)化為數(shù)組 if ((size = elementData.length) != 0) {

9、 // 參數(shù)為非空集合 if (elementData.getClass() != Object[].class) // 是否成功轉(zhuǎn)化為Object類型數(shù)組 elementData = Arrays.copyOf(elementData, size, Object[].class); // 不為Object數(shù)組的話就進行復制 } else { // 集合大小為空,則設置元素數(shù)組為空 this.elementData = EMPTY_ELEMENTDATA; } }

10、 View Code   說明:當傳遞的參數(shù)為集合類型時,會把集合類型轉(zhuǎn)化為數(shù)組類型,并賦值給elementData。   3.4 核心函數(shù)分析   1. add函數(shù) ? public boolean add(E e) { // 添加元素 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } View Code   說明:在add函數(shù)我們發(fā)現(xiàn)還有其他的函數(shù)ensu

11、reCapacityInternal,此函數(shù)可以理解為確保elementData數(shù)組有合適的大小。ensureCapacityInternal的具體函數(shù)如下  ? private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 判斷元素數(shù)組是否為空數(shù)組 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); // 取較大值

12、 } ensureExplicitCapacity(minCapacity); } View Code   說明:在ensureCapacityInternal函數(shù)中我們又發(fā)現(xiàn)了ensureExplicitCapacity函數(shù),這個函數(shù)也是為了確保elemenData數(shù)組有合適的大小。ensureExplicitCapacity的具體函數(shù)如下 ? private void ensureExplicitCapacity(int minCapacity) { // 結(jié)構(gòu)性修改加1 modCount+

13、+; if (minCapacity - elementData.length > 0) grow(minCapacity); } View Code   說明:在ensureExplicitCapacity函數(shù)我們又發(fā)現(xiàn)了grow函數(shù),grow函數(shù)才會對數(shù)組進行擴容,ensureCapacityInternal、ensureExplicitCapacity都只是過程,最后完成實際擴容操作還是得看grow函數(shù),grow函數(shù)的具體函數(shù)如下   ? private void grow(int minCapacity) {

14、 int oldCapacity = elementData.length; // 舊容量 int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量為舊容量的1.5倍 if (newCapacity - minCapacity < 0) // 新容量小于參數(shù)指定容量,修改新容量 newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) // 新容量大于最大容量

15、 newCapacity = hugeCapacity(minCapacity); // 指定新容量 // 拷貝擴容 elementData = Arrays.copyOf(elementData, newCapacity); } View Code   說明:正常情況下會擴容1.5倍,特殊情況下(新擴展數(shù)組大小已經(jīng)達到了最大值)則只取最大值。   當我們調(diào)用add方法時,實際上的函數(shù)調(diào)用如下   說明:程序調(diào)用add,實際上還會進行一系列調(diào)用,可能會調(diào)用到grow,grow可能會調(diào)用hugeCapacity。   下面通過

16、兩種方式給出調(diào)用add的例子,并分析最后的elementData數(shù)組的大小。   示例一(只給出了會影響到最終結(jié)果的核心代碼)  List lists = new ArrayList(); lists.add(8);   說明:初始化lists大小為0,調(diào)用的ArrayList()型構(gòu)造函數(shù),那么在調(diào)用lists.add(8)方法時,會經(jīng)過怎樣的步驟呢?下圖給出了該程序執(zhí)行過程和最初與最后的elementData的大小   說明:我們可以看到,在add方法之前開始elementData = {};調(diào)用add方法時會繼續(xù)調(diào)用,直至grow,最后e

17、lementData的大小變?yōu)?0,之后再返回到add函數(shù),把8放在elementData[0]中。   示例二核心代碼如下 List lists = new ArrayList(6); lists.add(8);   說明:調(diào)用的ArrayList(int)型構(gòu)造函數(shù),那么elementData被初始化為大小為6的Object數(shù)組,在調(diào)用add(8)方法時,具體的步驟如下:   說明:我們可以知道,在調(diào)用add方法之前,elementData的大小已經(jīng)為6,之后再進行傳遞,不會進行擴容處理。   2. set函數(shù)  ? public

18、 E set(int index, E element) { // 檢驗索引是否合法 rangeCheck(index); // 舊值 E oldValue = elementData(index); // 賦新值 elementData[index] = element; // 返回舊值 return oldValue; } View Code   說明:設定指定下標索引的元素值?! ?   3. indexOf函數(shù) ? // 從首

19、開始查找數(shù)組里面是否存在指定元素 public int indexOf(Object o) { if (o == null) { // 查找的元素為空 for (int i = 0; i < size; i++) // 遍歷數(shù)組,找到第一個為空的元素,返回下標 if (elementData[i]==null) return i; } else { // 查找的元素不為空 for (int i = 0; i < size;

20、 i++) // 遍歷數(shù)組,找到第一個和指定元素相等的元素,返回下標 if (o.equals(elementData[i])) return i; } // 沒有找到,返回空 return -1; } View Code   說明:從頭開始查找與指定元素相等的元素,注意,是可以查找null元素的,意味著ArrayList中可以存放null元素的。與此函數(shù)對應的lastIndexOf,表示從尾部開始查找。   4. get函數(shù) ? pu

21、blic E get(int index) { // 檢驗索引是否合法 rangeCheck(index); return elementData(index); } View Code   說明:get函數(shù)會檢查索引值是否合法(只檢查是否大于size,而沒有檢查是否小于0),值得注意的是,在get函數(shù)中存在element函數(shù),element函數(shù)用于返回具體的元素,具體函數(shù)如下  ? E elementData(int index) { return (E) elementData[index

22、]; } View Code   說明:返回的值都經(jīng)過了向下轉(zhuǎn)型(Object -> E),這些是對我們應用程序屏蔽的小細節(jié)。   5. remove函數(shù)   ? public E remove(int index) { // 檢查索引是否合法 rangeCheck(index); modCount++; E oldValue = elementData(index); // 需要移動的元素的個數(shù) int numMoved = size -

23、 index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); // 賦值為空,有利于進行GC elementData[--size] = null; // 返回舊值 return oldValue; } View Code   說明:remove函數(shù)用戶移除指定下標的元素,此時會把指定下標到數(shù)組末尾的元素向前移動一個單位,并且會把數(shù)組最后一個元素設置為null,這樣是為了方便之后將整個數(shù)組不被使用時,會被GC,可以作為小的技巧使用。 四、總結(jié)   ArrayList有其特殊的應用場景,與LinkedList相對應。其優(yōu)點是隨機讀取,缺點是插入元素時需要移動大量元素,效率不太高。至此,ArrayList的源碼分析就到這里, 9 / 9

展開閱讀全文
溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

相關資源

更多
正為您匹配相似的精品文檔

相關搜索

關于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號:ICP2024067431-1 川公網(wǎng)安備51140202000466號


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務平臺,本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請立即通知裝配圖網(wǎng),我們立即給予刪除!