ArrayList方面
ArrayList簡介:面試
ArrayList是一種以數組實現的List,它實現了List, RandomAccess, Cloneable, Serializable接口。數組
- 實現List接口表示它能夠支持刪除、添加和查找等操做。
- 實現RandomAccess接口表示它能夠支持隨機訪問(強調一點,並非由於實現RandomAccess接口,ArrayList才支持隨機訪問。RandomAccess只是一個標記接口,接口RandomAccess中內容是空的,只是做爲標記使用。)。
- 實現了Cloneable接口表示ArrayList能夠被克隆。
- 實現了Serializable接口表示ArrayList能夠被序列化。
ArrayList中的屬性安全
- DEFAULT_CAPACITY =10;表示默認的容量爲10。
- Object[] EMPTY_ELEMENTDATA ={};表示一個空數組,若是你傳入的容量爲0時使用,例如:ArrayList list=new ArrayList(0)。
- Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA={};表示一個空的數組,在你不傳入容量的時候使用,例如:ArrayList list=new ArrayList()時使用。在添加第一個元素的時候會初始化默認的大小10.
- Object[] elementData;用於存儲元素的數組。
- int size;表示元素的個數。
- modCount;對於add操做,remove操做,modCount會進行自增操做。表示ArrayList支持fail-fast。
ArrayList的構造方法(三種)dom
ArrayList list =new ArrayList(int initialCapacity)線程
傳入初始容量,若是小於0就拋出異常;若是大於0,則使用傳入的容量;若是等於0就使用EMPTY_ELEMENTDATA空數組。對象
ArrayList list=new ArrayList()blog
不傳入初始容量,默認使用
DEFAULTCAPACITY_EMPTY_ELEMENTDATA空數組,在添加第一個元素的時候擴容爲默認的大小DEFAULT_CAPACITY也就是10。索引
ArrayList list=new ArrayList(Collection c)接口
會將Collection集合轉化爲數組拷貝到element數組中(elementData=c.toArray())。隊列
ArrayList的各類操做
add(E e)
將元素添加到末尾,平均時間複雜度爲O(1);
- 檢查數組是否須要擴容
- 首先判斷elementData是否等於DEFAULTCAPACITY_EMPTY_ELEMENTDATA便是否爲空數組,若是是就初始化爲默認大小DEFAULT_CAPACITY(10);
- 新容量爲舊容量的1.5倍;若是發現仍是比須要的容量小,則以須要的容量爲標準;若是須要的容量已經超過最大的容量(MAX_ARRAY_SIZE),則使用最大的容量;最後以新容量拷貝出一個新的數組。
- 添加元素。
add(int index,E element)
將元素添加到指定位置,時間複雜度爲O(n),由於須要將index後的元素總體向後移動一位。
- 檢查index是否越界。
- 檢查是否須要進行擴容。
- 將index後的元素總體向後移動一位。
- 將index位置的元素賦值爲element。
- size++,表示元素個數增長一。
get(int index)
- 返回指定位置的元素,時間複雜度爲o(1)。
- 判斷index是否越界。
- 返回index位置的元素。
remove(int index)
刪除指定位置的元素,時間複雜度爲o(n),由於須要將index後的元素總體向前移動一位。
- 檢查是否越界。
- modCount++。
- 調用System.arrayCopy()方法對於數組自己進行復制,將index後的元素總體向前移動一位。
- 將最後一個元素設置爲null,幫助GC。
- 返回index位置的舊值。
remove(Object o)
刪除指定元素的值,時間複雜爲o(n)。
- 遍歷數組,若是刪除的元素爲null,使用==進行null的比較;若是刪除的元素不爲null,使用equals()進行比較。
- modCount++;
- 調用System.arrayCopy()方法將刪除元素位置後的全部元素總體向前移動一位。
- 將最後一個元素設置爲null,方便進行GC。
- 返回true或false表示刪除成功或者失敗。
ArrayList總結
- ArrayList使用數組存儲元素,當數組長度不夠的時候,會進行擴容,每次擴容爲1.5倍。
- ArrayList添加元素到尾部,平均時間複雜度爲O(1)。
- ArrayList添加元素到中間,平均時間複雜度爲O(n)。
- ArrayList刪除尾部的元素,平均時間複雜度爲O(1)。
- ArrayList從中間刪除元素比價慢,平均時間複雜度爲O(n)。
- ArrayList支持隨機訪問,時間複雜度爲O(1)。
LinkedList相關方面
LinkedList簡介:
相較於ArrayList的數組實現,LinkedList是基於雙向鏈表實現的。它實現了List, Deque,Queue, Cloneable, Serializable接口。
- 實現List接口表示它能夠支持刪除、添加和查找等操做。
- 實現Deque和Queue接口表示它能夠做爲雙端隊列進行使用,同時也能夠做爲棧進行使用。
- 實現了Cloneable接口表示ArrayList能夠被克隆。
- 實現了Serializable接口表示ArrayList能夠被序列化。
LinkedList的內部屬性
int size表示元素的個數,初始爲0。
- Node< E> first。表示鏈表的第一個節點。
- Node< E> last。表示鏈表中的最後一個節點。
- Node< E> 是一個雙向鏈表的結構。Node< E>內部包括Node< E> next,Node< E> prev和E item。
- modcount表示支持fail-fast。
LinkedList的主要方法
addFirst(E e)
在隊首添加元素,時間複雜度爲O(1)。
- 建立一個新的節點newNode。
- 將newNode賦值給first即first=newNode。
- 判斷newNode是否是第一個新添加的節點,若是是的話,將newNode賦值給last即last=newNode。
- size++。
- modcount++。
addLast(E e)
在隊尾添加元素和addFirst(E e)同理,時間複雜度爲O(1)。
add(int index,E element)
在指定位置添加元素,時間複雜度爲O(n)。由於須要遍歷,查找到插入位置的後繼節點。
- 判斷是否越界。
- 若是index小於size/2,從前日後進行遍歷找到插入位置的後繼節點;若是index大於size/2,從後往前遍歷找到插入位置的後繼節點。
- 按照雙線鏈表在中間插入元素的方法進行插入。
removeFirst()
刪除隊首的元素,時間複雜度爲O(1)。
- 若是鏈表中沒有元素,拋出異常。
- 查找first的後繼節點假設是first_next,將first設置爲null,方便進行GC。
- 將first設置爲first_next即first=first_next;判斷first_next是否爲null,若是first_next等於null,則將last設置爲null不然將first_next.prev設置爲null。
- size–。
- modcount++。
removeLast()
刪除隊尾的元素,時間複雜度爲O(1)。原理同上。
remove(int index)
刪除指定位置的元素,時間複雜度爲O(n),原理同add(int index,E element)。
LinkedList總結
- LinkedList是基於雙向鏈表實現,能夠做爲雙端隊列,棧來進行使用。
- LinkedList在隊首隊尾刪除添加比較快,時間複雜度爲O(1)。
- LinkedList在鏈表中間添加刪除比較慢,時間複雜度爲O(n)。
- 另外要注意的是,LinkedList是不支持隨機訪問的,因此訪問中間元素的效率比較低。
CopyOnWriteArrayList相關
CopyOnWriteArrayList簡介:
CopyOnWriteArrayList是ArrayList的線程安全版本,也是經過數組實現的。相較於ArrayList,CopyOnWriteArrayList使用ReentrantLock重入鎖加鎖,保證線程安全。每次對數組的修改都徹底拷貝一份新的數組來修改,修改完了再替換掉老數組,這樣保證了只阻塞寫操做,不阻塞讀操做,實現讀寫分離。
CopyOnWriteArrayList實現了List, RandomAccess, Cloneable, Serializable接口。
- 實現List接口表示它能夠支持刪除、添加和查找等操做。
- 實現RandomAccess接口表示它能夠支持隨機訪問(強調一點,並非由於實現了RandomAccess接口,ArrayList才支持隨機訪問。RandomAccess只是一個標記接口,接口RandomAccess中內容是空的,只是做爲標記使用。)。
- 實現了Cloneable接口表示ArrayList能夠被克隆。
- 實現了Serializable接口表示ArrayList能夠被序列化。
CopyOnWriteArrayList主要的內部屬性:
- ReentrantLock lock=new ReentrantLock();用於修改時進行加鎖。
- Object[]array用於純屬元素。
CopyOnWriteArrayList主要方法:
add(E e)
添加一個元素到末尾。
- 使用ReentrantLock進行加鎖。
- 使用getArray()方法獲取元素的數組。
- 新建一個數組大小是原數組的長度加一,並使用Arrays.copyof()方法將原數組拷貝到新數組中。
- 將添加的元素放到新數組的末尾。
- 將新數組覆蓋原數組。
- 解鎖。
add(int index,E element)
添加元素到制定的位置。
- 加鎖。
- 判斷是否越界,若是越界拋出異常。
- 若是索引等於數組長度,那就拷貝一個len+1的數組即newElements =Arrays.copyOf(elements,len+1)。
- 若是索引不等於數組長度,那就新建一個len+1的數組,將索引以前的部分拷貝到新數組索引以前,索引以後拷貝到新數組索引以後的位置。
- 把索引位置賦值爲待添加的元素。
- 把新數組賦值給當前對象的array屬性,覆蓋原數組。
- 解鎖。
get(int index)
獲取指定位置的元素,時間複雜度爲O(1)。
- 經過getAway()方法獲取數組。
- 返回指定位置的元素。
remove(int index)
刪除指定位置的元素,時間複雜度O(n)。
- 加鎖。
- 經過getAway()方法獲取舊數組。
- 若是移除的是最後一位,那麼直接拷貝一份n-1的新數組, 最後一位就自動刪除。
- 若是移除的不是最後一位,那麼新建一個n-1的新數組。將前index的元素拷貝到新數組中,將index後面的元素往前挪一位拷貝到新數組中。
- 將新數組賦值給當前對象的數組屬性。
- 解鎖並返回舊值。
CopyOnWriteArrayList總結:
- 對於寫操做,CopyOnWriteArrayList使用ReentrantLock重入鎖加鎖,保證線程安全。
- CopyOnWriteArrayList的寫操做要先拷貝一份新數組,在新數組中進行修改,修改完了再用新數組去替換舊的數組。
- CopyOnWriteArrayList採用讀寫分離的思想,讀操做不加鎖,可是寫操做須要加鎖。
- CopyOnWriteArrayList支持隨機快速訪問,時間複雜度爲O(1)。