List原始碼分析
ArrayList
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{}
根據上面我們可以清晰的發現:ArrayList底層其實就是一個陣列,ArrayList中有擴容這麼一個概念,正因為它擴容,所以它能夠實現“動態”增長
以上是怎麼得到的結論?由建構函式得出的
add(E e)
步驟:
檢查是否需要擴容
插入元素
首先,我們來看看這個方法:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
該方法很短,我們可以根據方法名就猜到他是幹了什麼:
確認list容量,嘗試容量加1,看看有無必要
新增元素
接下來我們來看看這個小容量(+1)是否滿足我們的需求:
隨後呼叫ensureExplicitCapacity()來確定明確的容量,我們也來看看這個方法是怎麼實現的:
grow擴容:
copyOf方法
到目前為止,我們就可以知道add(E e)的基本實現了:
首先去檢查一下陣列的容量是否足夠
足夠:直接新增
不足夠:擴容
擴容到原來的1.5倍
第一次擴容後,如果容量還是小於minCapacity,就將容量擴充為minCapacity。
add(int index, E element)
步驟:
檢查角標
空間檢查,如果有需要進行擴容
插入元素
我們來看看插入的實現:
我們發現,與擴容相關ArrayList的add方法底層其實都是arraycopy()來實現的
看到arraycopy(),我們可以發現:該方法是由C/C++來編寫的,並不是由Java實現:
總的來說:arraycopy()還是比較可靠高效的一個方法。
get/remove等方法以後再說
總結:
ArrayList是基於動態陣列實現的,在增刪時候,需要陣列的拷貝複製。
ArrayList的預設初始化容量是10,每次擴容時候增加原先容量的一半,也就是變為原來的1.5倍
刪除元素時不會減少容量,若希望減少容量則呼叫trimToSize()
它不是執行緒安全的。它能存放null值。
Arraylist 和 Vector 的區別?
ArrayList 是 List 的主要實現類,底層使用 Object[ ]儲存,適用於頻繁的查詢工作,執行緒不安全 ;
Vector 是 List 的古老實現類,底層使用 Object[ ]儲存,執行緒安全的。
ArrayList在底層陣列不夠用時在原來的基礎上擴充套件0.5倍,Vector是擴充套件1倍。
Vector執行緒安全是因為方法上加了synchronized.
LinkedList
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{}
建構函式
add
add方法
如果做過連結串列的練習,對於下面的程式碼並不陌生的~
add方法實際上就是往連結串列最後新增元素
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
List集合總結
ArrayList、LinkedList、Vector算是在面試題中比較常見的的知識點了。下面我就來做一個簡單的總結:
ArrayList:
底層實現是陣列
ArrayList的預設初始化容量是10,每次擴容時候增加原先容量的一半,也就是變為原來的1.5倍
在增刪時候,需要陣列的拷貝複製(navite 方法由C/C++實現)
LinkedList:
底層實現是雙向連結串列[雙向連結串列方便實現往前遍歷]
Vector:
底層是陣列,現在已少用,被ArrayList替代,原因有兩個:
Vector所有方法都是同步,有效能損失。
Vector初始length是10 超過length時 以100%比率增長,而ArrayList是50%。相比於ArrayList更多消耗記憶體。
總的來說:查詢多用ArrayList,增刪多用LinkedList。
ArrayList增刪快的幾種極端情況:
在末尾增刪+中間刪除都是ArrayList快
相關文章
- .net原始碼分析 – List原始碼
- lodash原始碼分析之List快取原始碼快取
- List介面下的集合原始碼分析——LinkedList原始碼
- Java List 容器原始碼分析的補充Java原始碼
- Java容器 | 基於原始碼分析List集合體系Java原始碼
- 詳解Java 容器(第③篇)——容器原始碼分析 - ListJava原始碼
- Java集合原始碼探究~ListJava原始碼
- Mybatis(五)--原始碼分析傳入單個list引數和多個list引數寫法MyBatis原始碼
- set\list\map部分原始碼解析原始碼
- java原始碼-java.util.ListJava原始碼
- Retrofit原始碼分析三 原始碼分析原始碼
- linux核心原始碼 -- list連結串列Linux原始碼
- 【JDK原始碼分析系列】ArrayBlockingQueue原始碼分析JDK原始碼BloC
- 集合原始碼分析[2]-AbstractList 原始碼分析原始碼
- 集合原始碼分析[3]-ArrayList 原始碼分析原始碼
- 集合原始碼分析[1]-Collection 原始碼分析原始碼
- Android 原始碼分析之 AsyncTask 原始碼分析Android原始碼
- Guava 原始碼分析之 EventBus 原始碼分析Guava原始碼
- 以太坊原始碼分析(36)ethdb原始碼分析原始碼
- 以太坊原始碼分析(38)event原始碼分析原始碼
- 以太坊原始碼分析(41)hashimoto原始碼分析原始碼
- 以太坊原始碼分析(43)node原始碼分析原始碼
- 以太坊原始碼分析(51)rpc原始碼分析原始碼RPC
- 以太坊原始碼分析(52)trie原始碼分析原始碼
- 深入解析C# List<T>的原始碼C#原始碼
- 深度 Mybatis 3 原始碼分析(一)SqlSessionFactoryBuilder原始碼分析MyBatis原始碼SQLSessionUI
- k8s client-go原始碼分析 informer原始碼分析(4)-DeltaFIFO原始碼分析K8SclientGo原始碼ORM
- k8s client-go原始碼分析 informer原始碼分析(6)-Indexer原始碼分析K8SclientGo原始碼ORMIndex
- 5.2 spring5原始碼--spring AOP原始碼分析三---切面原始碼分析Spring原始碼
- Spring原始碼分析——搭建spring原始碼Spring原始碼
- 精盡MyBatis原始碼分析 - MyBatis-Spring 原始碼分析MyBatis原始碼Spring
- 以太坊原始碼分析(35)eth-fetcher原始碼分析原始碼
- 以太坊原始碼分析(20)core-bloombits原始碼分析原始碼OOM
- 以太坊原始碼分析(24)core-state原始碼分析原始碼
- 以太坊原始碼分析(29)core-vm原始碼分析原始碼
- 以太坊原始碼分析(34)eth-downloader原始碼分析原始碼
- List集合就這麼簡單【原始碼剖析】原始碼
- k8s client-go原始碼分析 informer原始碼分析(5)-Controller&Processor原始碼分析K8SclientGo原始碼ORMController