1. 程式人生 > >JDK集合面試20問

JDK集合面試20問

1. HashMap的內部實現原理是什麼?

HashMap內部實現原理是陣列+連結串列,通過雜湊演算法將key值雜湊到陣列中,如果到相同的位置,則通過拉鍊法解決雜湊衝突。在JDK8中新增了紅黑樹結構,當HashMap中的雜湊衝突連結串列結構超過8個數據時,會從連結串列結構轉換為紅黑樹結構。

2. HashMap的key值能否是null,如果能,key=null如何儲存以及如何讀取的?如果不能,為什麼?

HashMap的key值可以是null。如果key=null,則會將它放置在陣列下標為0的位置。

3. HashMap如何實現擴容?

HashMap擴容和初始容器大小與負載因子有關。HashMap的初始容器大小為16,預設的負載因子為0.75,當實際容量超過16*0.75=12個元素時會進行擴容。擴容後的容器大小是擴容前的2倍,第一次擴容後的容器大小為32。

4. 設定HashMap的容量有沒有注意的地方,為什麼?

指定HashMap的容量時,建議是2的冪次方。

HashMap在定址是會key的hash值與容器長度做與運算,(n - 1) & hash。當n的長度為2的冪次方時,n-1的二進位制形式就會是111111,這樣與操作效率會非常的快。

5. HashMap是否是執行緒安全的?如果不是,多執行緒下併發操作它可能會帶來什麼問題?如果是,它是怎麼實現的?

HashMap不是執行緒安全的。如果在多執行緒下併發操作不僅會導致髒資料,甚至可能會造成死迴圈。(關於死迴圈產生的原因參考https://www.cnblogs.com/yulinfeng/p/8558983.html

6. LinkedHashMap的內部實現原理是什麼?它是否支援key=null?

LinkedHashMap是插入有序的Map集合。它直接繼承了HashMap,所以很多都直接複用了HashMap方法,所以也支援key=null。它在內部除了沿用HashMap的底層結構,還單獨維護了一個雙向連結串列,在對Map進行put操作時,同時還會將資料寫到了連結串列的尾部,保證了插入有序。

7. TreeMap的內部實現原理是什麼?它是否支援key=null?

TreeMap結構也是有序的,不同的是它是字典有序,由於它底層是紅黑樹結構,插入時會進行比較key值的順序,所以不允許key=null的情況。

8. 介紹下Hashtable

Hashtable是執行緒安全的Map型別,但它的執行緒安全代價是為整個散列表加鎖,效率很低,幾乎已經廢棄。如果要使用執行緒安全的Map,應該使用ConcurrentHashMap,它的實現是分段鎖,能最大的提高效率。

9. 以上三種Map型別分別可以應用到哪些場景?你在哪些場景下使用過?

HashMap的使用場景很多,這個使用場景就太多了,比如用作本地快取。

LinkedHashMap因為它的連結串列結構可以實現LRU(最近最少使用),即快取空間有限,當元素多餘快取空間,可淘汰掉最近最少使用的元素。在LinkedHashMap維護了一個accessOrder欄位,預設為false,當設定為true時,如果訪問一個key值,就會將這個元素放置連結串列頭部,這樣在連結串列尾部的元素就是不常用的元素,空間不足直接remove末尾的元素即可。所以當要實現LRU快取時,就可以將accessOrder設定為true實現。

TreeMap沒有實際應用過,如果有需要排序的場景則使用TreeMap

Set

10. HashSet的內部實現原理是什麼,它有什麼特點?

HashSet集合的特點是不允許有重複的元素,且無序的,允許null值。它在內部維護一個HashMap,儲存在HashSet中的元素實際上儲存在HashMap的key中。

11. LinkedHashSet的內部實現原理是什麼,它有什麼特點?

LinkedHashSet繼承自HashMap,在內部維護一個雙向連結串列保證插入有序,允許null值。

12. TreeSet的內部實現原理是什麼,它有什麼特點?

TreeSet是一個有序的集合,它的作用是提供有序的Set集合,TreeSet是基於TreeMap實現的。不允許有null值。

13. 以上三種Set型別分別可以應用到哪些場景?你在哪些場景下使用過?

HashSet可應用於批量查詢時去重。

如果需要返回的資料和入參的資料順序一致則可以使用LinkedHashSet。

List

14. ArrayList的內部實現原理什麼?

底層通過陣列實現,建立一個ArrayList物件例項時不會初始化陣列,當插入第一條資料時會建立一個大小為10的陣列。

15. 既然ArrayList的底層實現是陣列,那定義ArrayList時,需要定義它的大小嗎?

可以不用定義容器的大小,預設大小為10,當容量大小不足時此時將會進行擴容。

16. ArrayList的擴容機制是什麼?

每次新增的容量是舊容量的一半,擴容後呼叫System.arraycopy方法拷貝到新的陣列。

17. 如果初始化ArrayList時,定義一個容量大小為11,此時擴容了幾次,容量大小為16呢?

不進行擴容。

18. LinkedList的內部實現原理是什麼?

底層通過連結串列實現,所以不存在擴容。

19. Vector和ArrayList、LinkedList的區別?

Vector是執行緒安全的額,ArrayList、LinkedList不是執行緒安全的。Vector的執行緒安全是為每個方法加上synchronized關鍵字,效率不高,不常用。

20. ArrayList與LinkedList分別可以應用到哪些場景?

大多數情況下使用ArrayList,因為ArrayList是陣列實現,它隨機讀取的速度更快,但插入指定位置慢;LinkedList由於是連結串列實現,所以隨機讀取的速度慢,但插入指定位置快。

關注CoderBuff公眾號,回覆“面試”獲取更多