Java面試題基礎篇(二)

LNhome發表於2018-03-28

集合

14、List, Set和Map 區別

List:
可以允許重複的元素。
可以插入多個null資料。
是一個有序的容器,保持了每一個元素的插入順序,輸出順序就是插入的順序。
常用的實現類有ArrayList,LinkedList和Vector,Arraylist使用最為流行,它提供了使用索引的隨意訪問,而LinkedList則對於經常需要從List中新增或刪除元素的場合更為適合。
Set:
不允許有重複的元素。
只允許有一個null元素。
常用的實現類是HashSet,LinkedHashSet和TreeSet,最為流行的是基於HashMap實現HashSet,TreeSet還實現了SortedSet介面,因此TreeSet是一個根據compare()和compareTo()的定義進行排序的有序容器。
Map:
Map 的 每個 Entry 都持有兩個物件,也就是一個鍵一個值,Map 可能會持有相同的值物件但鍵物件必須是唯一的。
TreeMap 也通過 Comparator  或者 Comparable 維護了一個排序順序。
Map 裡你可以擁有隨意個 null 值但最多隻能有一個 null 鍵。
Map 介面最流行的幾個實現類是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用)
List,Set,Map的使用場景:
如果經常使用索引訪問容器中的元素,那麼優先選擇List,如果已經知道索引的話,ArrayList可以提供更快速的訪問,如果需要經常刪除新增元素,那麼肯定要選擇LinkedList。如果需要容器中的元素按照插入的次序進行有序的儲存,還是選擇List,因為它是一個有序的容器,按照插入的順序進行儲存。
如果要保證插入元素的唯一性,那麼可以選擇一個Set的實現類,所有Set的實現類都遵循唯一型約束。Tree還是一個SortedSet,所有儲存於 TreeSet 中的元素可以使用 Java 裡的 Comparator 或者 Comparable 進行排序。LinkedHashSet 也按照元素的插入順序對它們進行儲存。
如果你以鍵和值的形式進行資料儲存那麼 Map 是你正確的選擇。你可以根據你的後續需要從 Hashtable、HashMap、TreeMap 中進行選擇。

15、Arraylist 與 LinkedList 區別

①ArrayList是實現了基於動態陣列的資料結構,而LinkedList是基於連結串列的資料結構;
②對於隨機訪問get和set,ArrayList要優於LinkedList,因為LinkedList要移動指標;
③對於新增和刪除操作add和remove,LinedList比較佔優勢,因為ArrayList要移動資料。 


16、ArrayList 與 Vector 區別

Vector是執行緒安全的,ArrayList不是執行緒安全的,導致Vector效率無法與ArrayList相比。
Vector和ArrayList都採用線性連續的儲存空間,底層都是陣列實現的,當儲存空間不足時,ArrayList預設增加50%,Vector預設增加原來的一倍。
Vector可以設定capacityIncrement,而ArrayList不可以,從字面理解就是capacity容量,Increment增加,容量增長的引數。

17、HashMap 和 Hashtable 的區別

(1)HashTable是執行緒安全的,而HashMap則是非執行緒安全的。HashTable實現方法裡面新增了synchronized關鍵字來確保執行緒同步,因而相對而言HashMap效率會更高。使用中若無特殊需求建議使用HashMap,在多執行緒環境中使用Collections.synchronizedMap()方法來獲取一個執行緒安全的集合。
(2)HashMap可以使用null作為key,而HashTable則不允許null作為key
(3)HashMap繼承AbstractMap,而HashTable繼承Dictionary抽象類,二者均實現Map介面。
(4)HashMap初始容量是16,HashTable初始容量是11,二者的填充因子預設都是0.75。
(5)HashMap擴容時是當前容量翻倍,HashTable擴容時是當前容量翻倍加1。
(6)HashMap和Hashtable的底層實現都是陣列+連結串列結構實現。
(7)兩者計算hash的方法不同:HashTable計算hash是直接使用key的hashcode對table陣列的長度直接進行取模;HashMap計算hash對key的hashcode進行了二次hash,以獲得更好的雜湊值,然後對table陣列長度取摸

18、HashSet 和 HashMap 區別

(1)HashSet是set的一個實現類,hashMap是Map的一個實現類。
(2)當呼叫HashSet的add方法時,實際上是向HashMap中增加了一行(key-value對),該行的key就是向HashSet增加的那個物件,該行的value就是一個Object型別的常量。
(3)HashSet以物件作為元素,而HashMap以(key-value)的一組物件作為元素。

19、HashMap 和 ConcurrentHashMap 的區別(參考https://www.cnblogs.com/remember-forget/p/6021644.html)

(1)Hashmap本質是陣列加連結串列。根據key取得hash值,然後計算出陣列下標,如果多個key對應到同一個下標,就用連結串列串起來,新插入的在前面。
(2)ConcurrentHashMap:在hashMap的基礎上,ConcurrentHashMap將資料分為多個segment,預設16個(concurrency level),然後每次操作對一個segment加鎖,避免多執行緒鎖的機率,提高併發效率。

20、HashMap 的工作原理及程式碼實現

HashMap概述:
HashMap是基於雜湊表的Map介面的實現,此實現提供所有可選的對映操作,並且可以使用null值和健,它不保證該順序永遠不變。HashMap不是執行緒安全的,如果想要執行緒安全的HashMap,可以通過Collections類的靜態方法synchronizedMap獲得執行緒安全的HashMap。Map map = Collections.synchronizedMap(new HashMap());
HashMap的資料結構
HashMap的底層資料結構是基於陣列和連結串列來實現的,它之所以有相當快的查詢速度主要是因為它通過計算雜湊碼來決定儲存的位置,能夠很快的計算出物件所儲存的位置。HashMap主要是通過key的hashCode來計算hash值的,只要hashCode相同,計算出來的hash值就一樣。如果儲存的物件多了,就有可能不同的物件計算出來的hash值是相同的,出現hash衝突,HashMap中通過連結串列來解決hash衝突。HashMap底層就是一個陣列結構,陣列中存放的是一個Entry物件,如果產生hash衝突,也就是說要儲存的那個位置上面已經儲存了物件了,這時候該位置儲存的就是一個連結串列了。
HashMap原始碼分析
(1)HashMap初始容量是16,預設載入因子是0.75。載入因子是表示Hash表中元素的填滿的程度,載入因子越大,填滿的元素越多,空間利用率高,查詢成本越小,但是衝突的機會就加大了,反之,載入因子越小,衝突機會減小了,但空間利用率小了,查詢成本增大。
(2)構造HashMap的時候如果我們指定了載入因子和初始容量的話就呼叫第一個構造方法,否則的話就是用預設的。預設初始容量為16,預設載入因子為0.75。通過追蹤程式碼,確保容量為2的n次冪,使capacity為大於initialCapacity的最小的2的n次冪。
(3)當我們往hashmap中put元素的時候,先根據key的hash值得到這個元素在陣列中的位置(即下標),然後就可以把這個元素放到對應的位置中了。如果這個元素所在的位子上已經存放有其他元素了,那麼在同一個位子上的元素將以連結串列的形式存放,新加入的放在鏈頭,最先加入的放在鏈尾。從hashmap中get元素時,首先計算key的hashcode,找到陣列中對應位置的某一元素,然後通過key的equals方法在對應位置的連結串列中找到需要的元素。


21、ConcurrentHashMap 的工作原理及程式碼實現

在hashMap的基礎上,ConcurrentHashMap將資料分為多個segment,預設16個,然後每次操作對一個segment加鎖,避免多執行緒鎖得機率,提高併發效率。

相關文章