Java面經3

集合

1、Map和ConcurrentHashMap的區別?
Map是一個接口、ConcurrentHashMap是一實現了Map接口的類,並且通過分段鎖機制實現併發。
2、hashMap內部具體如何實現的?
數據結構:數組+鏈表(當鏈表長度到達8之後,會自動轉化成紅黑樹)。
put:key的hash值,與hashMap的數組長度-1相與,得出的值即爲需要存的數組的位置,然後通過尾插法插入鏈表中或者插入紅黑樹中;
get:獲取key的hash值,與hashMap的數組長度-1相與,得出的值即爲應存在的數組中的位置;若是鏈表則遍歷,紅黑樹則使用二叉搜索;當hashcode相等時,再比較equal,若equal也返回true,則返回該對象。
size:basecount存儲當前size,但當高併發時,對於失敗的CAS會被記錄到counterCells中,返回size=basecount+counterCells中的數目
resize函數:當hashmap當前的size大於負載因子乘以數組長度,則需要rezise。將當前的容量擴大一倍,將原數組中的鏈表重新插入新數組中。
3、如果hashMap的key是一個自定義的類,怎麼辦?
最好寫成一個不可變類
需要重寫hashCode()和equal()方法
4、ArrayList和LinkedList的區別,如果一直在list的尾部添加元素,用哪個效率高?
ArrayList:使用數組實現
LinkedList:使用鏈表實現
由於ArrayList實現是數組,當不斷在尾部添加元素的時候,超出數組的長度,會自動擴展,涉及到申請新的空間,以及將原數組複製到新的數組中;而LinkedList理論上是可以添加無數個節點。
5、HashMap底層,數組的長度爲啥是2^n?
數據存到哪個鏈表中的算法; 這個算法實際就是取模,源碼中做了優化將取餘操作轉化成位運算,但 hash%length==hash&(length-1)的前提是length是2的n次方。
6、ConcurrentHashMap鎖加在了哪些地方?
JDK1.8 中取消了segments字段,直接採用transient volatile HashEntry<k,v>[] table保存數據,採用table數組元素作爲鎖,從而實現了對每一條鏈表進行加鎖,進一步減少併發衝突的概率。
7、TreeMap底層,紅黑樹原理?
自平衡的二叉搜索樹
插入、查詢、刪除時間複雜度均爲log(n)
特徵:

  • 根節點時黑色
  • 葉子節點是黑色
  • 點僅有黑色和紅色
  • 兩個紅色節點不能直接相連
  • 從根節點到葉子節點,經過的所有黑色節點樹相同

8、concurrenthashmap有啥優勢,1.7,1.8區別?
HashMap1.7和1.8區別

1.7 1.8
數據結構 數組+鏈表 數組+鏈表+紅黑樹
鏈表的插入方式 前插 後插

ConcurrentHashMap 1.7和1.8區別

1.7 1.8
數據結構 Segment + HashEntry 數組+鏈表+紅黑樹
加鎖方式 ReentrantLock CAS+Synchronized

9、ArrayList是否會越界?
會越界。在多線程的情況下,兩個線程同時add,當一個add完成時,正好是Array的最後一個數組,在還未擴容之前,另一個線程add會報數組越界的錯誤。
10、什麼是TreeMap?
有序的鍵值對,可以傳入一個Comparator,對Key進行排序。
11、ConcurrentHashMap的原理是什麼?
分段鎖+CAS+Synchronized
12、Java集合類框架的基本接口有哪些?
Collection、Map
Collection:List、Map、Queue
Map:SortMap
13、爲什麼集合類沒有實現Cloneable和Serializable接口?
如果集合類實現了Cloneable和Serializable接口,則其聚集的類必須先要實現這兩個接口,這樣的話很多類都無法作爲集合類的模板參數。
克隆和序列化是跟具體的場景實現有關的,所以應該由集合的實現類來決定如何實現克隆和序列化
14、什麼是迭代器?
迭代器是一種設計模式,它是一個對象,它可以遍歷並選擇序列中的對象,而開發人員不需要了解該序列的底層結構。迭代器通常被稱爲“輕量級”對象,因爲創建它的代價小。
  Java中的Iterator功能比較簡單,並且只能單向移動:
  (1) 使用方法iterator()要求容器返回一個Iterator。第一次調用Iterator的next()方法時,它返回序列的第一個元素。注意:iterator()方法是java.lang.Iterable接口,被Collection繼承。
  (2) 使用next()獲得序列中的下一個元素。
  (3) 使用hasNext()檢查序列中是否還有元素。
  (4) 使用remove()將迭代器新返回的元素刪除。
15、Iterator和ListIterator的區別是什麼?

Iterator ListIterator
遍歷Set和List集合 遍歷List
從頭往後遍歷 既可以前向也可以後向
幷包含其他的功能,比如:增加元素,替換元素

16、快速失敗(fail-fast)和安全失敗(fail-safe)的區別是什麼?
一:快速失敗(fail—fast)
在用迭代器遍歷一個集合對象時,如果遍歷過程中對集合對象的內容進行了修改(增加、刪除、修改),則會拋出Concurrent Modification Exception。
原理:迭代器在遍歷時直接訪問集合中的內容,並且在遍歷過程中使用一個 modCount 變量。集合在被遍歷期間如果內容發生變化,就會改變modCount的值。每當迭代器使用hashNext()/next()遍歷下一個元素之前,都會檢測modCount變量是否爲expectedmodCount值,是的話就返回遍歷;否則拋出異常,終止遍歷。
注意:這裏異常的拋出條件是檢測到 modCount!=expectedmodCount 這個條件。如果集合發生變化時修改modCount值剛好又設置爲了expectedmodCount值,則異常不會拋出。因此,不能依賴於這個異常是否拋出而進行併發操作的編程,這個異常只建議用於檢測併發修改的bug。
場景:java.util包下的集合類都是快速失敗的,不能在多線程下發生併發修改(迭代過程中被修改)。
二:安全失敗(fail—safe)
採用安全失敗機制的集合容器,在遍歷時不是直接在集合內容上訪問的,而是先複製原有集合內容,在拷貝的集合上進行遍歷。
原理:由於迭代時是對原集合的拷貝進行遍歷,所以在遍歷過程中對原集合所作的修改並不能被迭代器檢測到,所以不會觸發Concurrent Modification Exception。
缺點:基於拷貝內容的優點是避免了Concurrent Modification Exception,但同樣地,迭代器並不能訪問到修改後的內容,即:迭代器遍歷的是開始遍歷那一刻拿到的集合拷貝,在遍歷期間原集合發生的修改迭代器是不知道的。
場景:java.util.concurrent包下的容器都是安全失敗,可以在多線程下併發使用,併發修改。
17、HashMap和Hashtable有什麼區別?

HashMap HashTable
非線程安全 線程安全
可接受null值 不能接收null

18、ArrayList和LinkedList有什麼區別?

ArrayList LinkedList
數據結構 數組實現 鏈表實現
隨機的 get/set O(1) O(n)
add O(1) O(1)
insert O(n) O(1)
remove O(n) O(1)

19、ArrayList,Vector,LinkedList的存儲性能和特性是什麼?
Vector線程安全的,基於數組的
20、Collection 和 Collections的區別。
Collection是一個接口
Collections是一個工具類,其中提供了一系列靜態方法,用於對集合中元素進行排序、搜索以及線程安全等各種操作。
21、你所知道的集合類都有哪些?主要方法?

22、List、Set、Map是否繼承自Collection接口?
Map不是。
23、闡述ArrayList、Vector、LinkedList的存儲性能和特性

24、List、Map、Set三個接口存取元素時,各有什麼特點?
Map、Set 插入、刪除、查找均爲O(1)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章