摘要:需要注意的是,通過構造函數定義初始量是動態數組的實際大小。帶容量的構造函數新建一個容量為的數組默認構造函數,默認為空構造一個包含指定元素的第一個構造方法使用提供的來初始化數組的大小。
前言
今天介紹經常使用的一個Java集合類——ArrayList(基于JDK1.8.0_121)。ArrayList在工作和日常面試中經常被使用或者提到。總的來說,工作中使用ArrayList主要是因為動態數組的方便性,面試中出現ArrayList經常是和LinkedList/Vector一起出現,分析這三種集合的異同。
ArrayList類圖圖片是直接從IntelliJ中導出來的,其中:藍色線條意味著繼承,綠色線條意味著接口實現。
ArrayList源碼剖析 ArrayList定義public class ArrayListextends AbstractList implements List , RandomAccess, Cloneable, java.io.Serializable
我們首先需要明白并且牢記在內心的是,ArrayList本質上是一個數組,但是與Java中基礎的數組所不同的是,它能夠動態增長自己的容量。
通過ArrayList的定義,可以知道ArrayList繼承了AbstractList,同時實現了List,RandomAccess,Cloneable和java.io.Serializable接口。
繼承了AbstractList類,實現了List,意味著ArrayList是一個數組隊列,提供了諸如增刪改查、遍歷等功能。
實現了RandomAccess接口,意味著ArrayList提供了隨機訪問的功能。RandomAccess接口在Java中是用來被List實現,用來提供快速訪問功能的。在ArrayList中,即我們可以通過元素的序號快速獲取元素對象。
實現了Cloneable接口,意味著ArrayList實現了clone()函數,能被克隆。
實現了java.io.Serializable接口,意味著ArrayList能夠通過序列化進行傳輸。
private static final int DEFAULT_CAPACITY = 10; transient Object[] elementData; private int size;
(1)ArrayList的默認容量為10;
(2)elementData是"Object類型的數組",所有ArrayList元素都保存在elementData中。在ArrayList中,elementData是一個動態數組。需要注意的是,ArrayList通過構造函數ArrayList(int initialCapacity)定義初始量initialCapacity;
(3)size是動態數組的實際大小。
//ArrayList帶容量的構造函數 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { //新建一個容量為initialCapacity的數組 this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } //ArrayList默認構造函數,默認為空 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } // 構造一個包含指定元素的list public ArrayList(Collection extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { this.elementData = EMPTY_ELEMENTDATA; } }
第一個構造方法使用提供的initialCapacity來初始化elementData數組的大小。
第二個構造方法默認數組為0。
第三個構造方法則將提供的集合轉成數組返回給elementData(返回若不是Object[]將調用Arrays.copyOf方法將其轉為Object[])。
public boolean add(E e) { //擴容判斷 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } public void add(int index, E element) { //判斷index是否越界,錯誤產生IndexOutOfBoundsException rangeCheckForAdd(index); //進行擴容檢查 ensureCapacityInternal(size + 1); // Increments modCount!! //對數組進行復制,將空出的Index位置出入element,并將index后的所有數據后移一個位置。 System.arraycopy(elementData, index, elementData, index + 1, size - index); //將index上的數據設置為element elementData[index] = element; //容量+1 size++; }刪除
public E remove(int index) { //邊界檢查 rangeCheck(index); modCount++; //oldValue即要刪除的元素 E oldValue = elementData(index); //要復制的元素 int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); //釋放最后一個元素 elementData[--size] = null; // clear to let GC do its work return oldValue; } public boolean remove(Object o) { //對o進行判斷 if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; }更新
public E set(int index, E element) { //數組擴容 rangeCheck(index); //獲取要更新的位置的數據 E oldValue = elementData(index); //更新元素 elementData[index] = element; return oldValue; }總結 1.ArrayList底層是通過數組來保存數據的。默認的容量是10. 2.JDK1.8中,ArrayList擴容使用位運算newCapacity = oldCapacity + (oldCapacity >> 1) 3.ArrayList實現java.io.Serializable的方式。當寫入到輸出流時,先寫入“容量”,再依次寫入“每一個元素”;當讀出輸入流時,先讀取“容量”,再依次讀取“每一個元素”。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67665.html
摘要:而在集合中,值僅僅是一個對象罷了該對象對本身而言是無用的。將這篇文章作為集合的總結篇,但覺得沒什么好寫就回答一些面試題去了,找了一會面試題又覺得不夠系統。 前言 聲明,本文用的是jdk1.8 花了一個星期,把Java容器核心的知識過了一遍,感覺集合已經無所畏懼了??!(哈哈哈....),現在來總結一下吧~~ 回顧目錄: Collection總覽 List集合就這么簡單【源碼剖析】 Ma...
摘要:是棧,它繼承于。滿二叉樹除了葉結點外每一個結點都有左右子葉且葉子結點都處在最底層的二叉樹。沒有鍵值相等的節點。這是數據庫選用樹的最主要原因。 在我們學習Java的時候,很多人會面臨我不知道繼續學什么或者面試會問什么的尷尬情況(我本人之前就很迷茫)。所以,我決定通過這個開源平臺來幫助一些有需要的人,通過下面的內容,你會掌握系統的Java學習以及面試的相關知識。本來是想通過Gitbook的...
摘要:底層使用的是雙向鏈表數據結構之前為循環鏈表,取消了循環。快速隨機訪問就是通過元素的序號快速獲取元素對象對應于方法。而接口就是用來標識該類支持快速隨機訪問。僅僅是起標識作用。,中文名為雙端隊列。不同的是,是線程安全的,內部使用了進行同步。 前言 學習情況記錄 時間:week 2 SMART子目標 :Java 容器 記錄在學習Java容器 知識點中,關于List的需要重點記錄的知識點。...
摘要:用戶自己指定容量創建大小的數組創建空數組默認構造函數,其默認初始容量為構造一個包含指定集合的元素的列表,按照它們由集合的迭代器返回的順序。以正確的順序返回該列表中的元素的迭代器。此方法充當基于陣列和基于集合的之間的橋梁。 目錄: 0-0-1. 前言 0-0-2. 集合框架知識回顧 0-0-3. ArrayList簡介 0-0-4. ArrayList核心源碼 0-0-5. Ar...
摘要:線程不安全底層數據結構是鏈表。的默認初始化容量是,每次擴容時候增加原先容量的一半,也就是變為原來的倍刪除元素時不會減少容量,若希望減少容量則調用它不是線程安全的。 前言 聲明,本文用得是jdk1.8 前一篇已經講了Collection的總覽:Collection總覽,介紹了一些基礎知識。 現在這篇主要講List集合的三個子類: ArrayList 底層數據結構是數組。線程不安全 ...
閱讀 1339·2021-09-22 15:09
閱讀 2668·2021-08-20 09:38
閱讀 2408·2021-08-03 14:03
閱讀 874·2019-08-30 15:55
閱讀 3375·2019-08-30 12:59
閱讀 3556·2019-08-26 13:48
閱讀 1891·2019-08-26 11:40
閱讀 672·2019-08-26 10:30