java面試基礎篇-List

一.ArrayList:

  底層為數組實現,執行緒不安全,查詢,修改快,增加刪除慢,

數據結構:數組以0為下標依次連續進行存儲

  數組查詢元素:根據下標查詢就行

  數組增加元素:如果需要給index為10的位置添加,則從index為11的位置開始右移

       數組刪除元素:如果需要刪除index為10的位置,則從index為11的位置開始左移

執行緒: 如果判斷執行緒安不安全只需要了解到是否進行加鎖,如果沒有加鎖的話,多個執行緒操作同一個對象時就會出現執行緒不安全的情況.

源碼:

1.new一個arraylist,調用add方法

 

2.查看add方法的源碼可以看出,並沒有任何加鎖操作,這就是執行緒不安全的 ,這裡首先會確認數組的容量,對其進行增加,並將新的元素加入到數組中

 

 使用場景:查詢 修改多

 

二.LikedList:

  底層為鏈表實現,執行緒不安全,查詢修改慢,增加刪除快

數據結構:鏈表的每個元素都存儲了下一個元素的地址,從而使一系列的隨機的記憶體地址串在了一起,只要有足夠的記憶體空間,就可以為鏈表分配記憶體

  鏈表查:當同時讀取所有元素時,鏈表的效率很高,讀第一個,讀第二個,以此類推。如果需要找到某個節點時,就需要遍歷整個節點,才可以找到需要的元素

  鏈表增加元素:只需要修改它前面的那個元素指針指向的地址即可

  鏈表刪除元素:只需要將前一個元素指針指向的地址更改即可

執行緒: 如果判斷執行緒安不安全只需要了解到是否進行加鎖,如果沒有加鎖的話,多個執行緒操作同一個對象時就會出現執行緒不安全的情況.

源碼:

1.new一個likedlist

 

2.可以看到likedlist源碼中也無任何的加鎖操作,其中add又調用了linklast

 

3.linklast里會吧新加元素設置為尾節點,所以創建了一個新的Node(節點)存起來,然後再新建一個節點,把之前的node指向鏈表的最後一個節點,然後再判斷一下l是否為空也就是之前的鏈表裡是否為空,如果為空則吧新的節點設為頭節點,否則就把next改為newnode,同時size和modcound自增

同樣的 也沒看到任何加鎖的操作

 

使用場景:增加刪除多

 

 

三,Vector 

  底層是數組實現,執行緒安全的,操作的時候使用synchronized進行加鎖 

  因為是數組實現的,curd方面可以參考arraylist,由於是加鎖的,所以比前兩個list效率更低的

源碼

1.new一個Vector,

  

 

 2. 可以看到這個方法使用了 synchronized來進行修飾,對此方法進行加鎖,因此這個方法對元素操作時是效率安全的,但效率相對較低,

同樣的首先確認元素,擴容+1,把新的元素放進去

  

 

  

 

 

題外話.怎樣來保證list的執行緒安全

  方式一:自己寫一個包裝類,根據業務,一般在進行add/update/remove操作時加鎖

  方式二:collections調用 synchronizedlist方法,

源碼:

1.創建一個list,會返回一個執行緒安全的list給你

  

2.可看到這個方法里首先是一個list集合,mutex是一個加鎖的對象

  

3.在繼續打開synchronizedrandomaccesslist

  

 

4,打開super,這裡可以看到這裡返回了一個同步的synchronizedlist,同樣也繼承了一個list方法

  

5.在synchronizedlist里可以找到常用的一些方法,同樣也是加鎖的,所以這個就變成執行緒安全了

  

 

  方式三:CopyOnWriteArrayList  

源碼:

1.new CopyOnWriteArrayList   使用ReentrantLock加鎖

  

2. CopyOnWriteArrayList 在使用get操作時沒有加鎖的 這個與synchronizedlist對比來說性能要更好一點

  

3,在add方法時可以看到用了ReentrantLock來進行加鎖,再用object數組獲取老的數組,並將老的數組獲取保存在len,

下面再用Arrays.copyof進行拷貝,將老的數組拷貝到新的數組newElements,並將長度+1,+1的原因就是為了存放新的元素,

目前記憶體里有兩個空間,一個空間是新的空間,另一個是舊的空間

  

  

setarray是為了將新的拷貝到舊的里,也就是改變了他的引用地址

最終unlock,把鎖釋放