前段時間已經總結了有關Java併發的面試題:
Java併發基礎面試題總結
Java併發進階面試題總結
今天來學習一下有關Java集合的常見面試題。java
說說常見的集合有哪些吧
說說List,Set,Map三者的區別
Arraylist與LinkedList 區別
爲何要用Arraylist取代Vector呢
說一說ArrayList的擴容機制
HashMap和Hashtable的區別
HashMap的長度爲何是2的冪次方
HashMap的擴容操做是怎麼實現的
HashMap在JDK1.7和JDK1.8中有哪些不一樣
ConcurrentHashMap和Hashtable的區別
ConcurrentHashMap的具體實現知道嗎
HashSet是如何保證數據不可重複的
CopyOnWriteArrayList爲何併發安全且性能比Vector好
CopyOnWriteArrayList讀取效率爲何那麼高
Map接口和Collection接口是全部集合框架的父接口:git
List
:List接口存儲一組不惟一(能夠有多個元素引用相同的對象),有序的對象Set
:不容許重複的集合。不會有多個元素引用相同的對象。Map
:使用鍵值對存儲。Map會維護與Key有關聯的值。兩個Key能夠引用相同的對象,但Key不能重複,典型的Key是String類型,但也能夠是任何對象。動態數組
的數據結構,LinkedList是基於鏈表
的數據結構詳情請看:深刻剖析ArrayList源碼github
synchronized
修飾。(若是你要保證線程安全的話就使用 ConcurrentHashMap
吧!);null 能夠做爲鍵
,這樣的鍵只有一個,能夠有一個或多個鍵所對應的值爲 null。。可是在 HashTable 中 put 進的鍵值只要有一個 null,直接拋出 NullPointerException。Hashtable
默認的初始大小爲11
,以後每次擴充,容量變爲原來的2n+1
。HashMap
默認的初始化大小爲16
。以後每次擴充,容量變爲原來的2
倍。②建立時若是給定了容量初始值,那麼 Hashtable 會直接使用你給定的大小,而 HashMap 會將其擴充爲2的冪次方大小(HashMap 中的tableSizeFor()
方法保證)。也就是說 HashMap 老是使用2的冪做爲哈希表的大小
。鏈表
轉化爲紅黑樹
,以減小搜索時間。Hashtable 沒有這樣的機制。
主要是爲了
提升運算效率,
咱們使用的是2次冪的擴展(指長度擴爲原來2倍),因此,擴容後元素的位置要麼是在原位置,要麼是在原位置再移動2次冪的位置
。所以,咱們在擴充HashMap的時候,不須要像JDK1.7的實現那樣從新計算hash,只須要看看原來的hash值
新增的那個bit是1仍是0就行了,是0的話索引沒變,是1的話索引變成「原索引+oldCap。
有關 HashMap的擴容操做請移步:深刻剖析HashMap源碼面試
ConcurrentHashMap和Hashtable的區別主要體如今實現線程安全的方式上不一樣。segmentfault
在JDK1.7中,ConcurrentHashMap採用Segment
+ HashEntry
的方式進行實現,結構以下:數組
在JDK1.8中,放棄了Segment臃腫的設計,取而代之的是採用Node + CAS + Synchronized來保證併發安全進行實現,結構以下:安全
HashSet的底層其實就是HashMap,只不過咱們HashSet是實現了Set接口而且把數據做爲K值,而V值一直使用一個相同的虛值來保存,咱們能夠看到源碼:數據結構
public boolean add(E e) { return map.put(e, PRESENT)==null;// 調用HashMap的put方法,PRESENT是一個至始至終都相同的虛值 }
因爲HashMap的K值自己就不容許重複,而且在HashMap中若是K/V相同時,會用新的V覆蓋掉舊的V,而後返回舊的V,那麼在HashSet中執行這一句話始終會返回一個false,致使插入失敗,這樣就保證了數據的不可重複性。多線程
Vector是增刪改查方法都加了synchronized,保證同步,可是每一個方法執行的時候都要去得到鎖,性能就會大大降低,而CopyOnWriteArrayList 只是在增刪改上加鎖,可是讀不加鎖,在讀方面的性能就好於Vector,CopyOnWriteArrayList支持讀多寫少的併發狀況。併發
CopyOnWriteArrayList類的全部可變操做(add,set等等)都是經過建立底層數組的新副本來實現的。當 List 須要被修改的時候,並不直接修改原有數組對象,而是對原有數據進行一次拷貝,將修改的內容寫入副本中。寫完以後,再將修改完的副本替換成原來的數據,這樣就能夠保證寫操做不會影響讀操做了。
從 CopyOnWriteArrayList
的名字能夠看出,CopyOnWriteArrayList
是知足 CopyOnWrite
的 ArrayList,所謂 CopyOnWrite
的意思:就是對一塊內存進行修改時,不直接在原有內存塊中進行寫操做,而是將內存拷貝一份,在新的內存中進行寫操做,寫完以後,再將原來指向的內存指針指到新的內存,原來的內存就能夠被回收。