Java集合框架常見面試題

1、簡述List、Set和Map三者的區別

  • list(對付順序的好幫手):List接口存儲一組不唯一(可以有多個元素引用相同的對象),有序的對象
  • set(注重獨一無二的性質):不允許重複的集合。不會有多個元素引用相同的對象。
  • map(用key來搜索的專家):使用鍵值對存儲。Map會維護與key有關聯的值。兩個key可以引用相同的對象,但key不能重複,典型的key是String類型,但也可以是任何對象。

2、ArrayList和LinkedList區別

  1. 是否保證線程安全:ArrayList和LinkedList是線程不同步的,就是說不保證線程安全。
  2. 底層數據結構:ArrayList底層使用的是Object數組;LinkedList底層使用的是雙向鏈表數據結構JDK1.6之前爲循環鏈表,JDK1.7取消了循環。注意雙向鏈表和雙向循環鏈表的區別,下面有介紹到!)
  3. 插入和刪除是否受到元素位置的影響:①ArrayList採用數組存儲,所以插入和刪除元素的時間複雜度受元素位置的影響。比如:執行add(E e)方法的時候,ArrayList會默認在指定的元素追加到此列表的末尾,這種情況時間複雜度就是O(1)。但是如果要在指定的位置i插入和刪除元素的話(add(int index, E elment))時間複雜度就爲O(n-i)。因爲在進行上述操作的時候集合中第i個和第i個之後的(n-1)個元素都要執行向後移一位的操作。②LinkedList採用鏈表存儲,所以對於add(E e)方法的插入,刪除元素時間複雜度不受元素位置的影響,近似O(1),如果是要在指定位置i插入和刪除元素的話((add(int index,E element))時間複雜度近似爲O(n))因爲需要先移動到指定位置再插入。
  4. 是否支持快速隨機訪問:LinkedList不支持高效的隨機訪問,而ArrayList支持,快速隨機訪問就是通過元素的序號快速獲取元素對象(對應於get(int index))方法。
  5. 內存空間佔用:ArrayList的空間浪費主要體現在list列表的結尾會預留一定的容量空間,而LinkedList的空間花費則體現在它的每一個元素都需要消耗比ArrayList更多的空間(因爲要存放直接後繼和直接前驅以及數據)。

雙向鏈表和雙向循環鏈表:

雙向鏈表: 包含兩個指針,一個prev指向前一個節點,一個next指向後一個節點。

雙向循環鏈表: 最後一個節點的 next 指向head,而 head 的prev指向最後一個節點,構成一個環。

3、ArrayList與Vector區別?爲什麼要用ArrayList代替Vector?

Vector的所有方法都是同步的。可以由兩個線程安全地訪問一個Vector對象、但是一個線程訪問Vector的話代碼要在同步操作上耗費大量的時間。
ArrayList不是同步的,所以在不需要保證線程安全時建議使用ArrayList。

4、HashMap和HashTable的區別

  1. 線程是否安全:HashMap是非線程安全的,HashTable是線程安全的;HashTable內部的方法基本經過synchronized修飾。(如果你要保證線程安全就使用ConcurrentHashMap);
  2. 效率:因爲線程是安全的,HashMap要比HashTable效率更高一點。另外,HashTable基本被淘汰,建議不要在代碼中使用;
  3. 對Null key和Null value的支持:HashMap中,null可以作爲鍵,這樣的鍵只有一個,可以有一個或多個鍵對應的值爲null。但是在HashTable中put進的鍵值只要有一個null,直接拋出NullPointException;
  4. 初始容量大小和每次擴充容量大小的不同:①創建時如果不指定容量初始值,HashTable默認的初始大小爲11,之後每次擴充,容量變爲原來的2n+1。HashMap默認的初始大小爲16,之後每次擴充,容量變爲原來的2倍。②創建時如果給定了容量初始值,那麼HashTable會直接使用你給定的大小,而HashMap會將其擴充爲2冪次方大小。也就是說HashMap總是使用2的冪作爲哈希表大小。
  5. 底層數據結構:JDK1.8以後的HashMap在解決哈希衝突時有了較大的變化,當鏈表大於閾值(默認爲8)時,將鏈表轉化爲紅黑樹,以減少搜索時間。HashTable沒有這樣的機制。

5、HashMap 和 HashSet區別

如果你看過 HashSet 源碼的話就應該知道:HashSet 底層就是基於 HashMap 實現的。(HashSet 的源碼非常非常少,因爲除了 clone() 、writeObject()、readObject()是 HashSet 自己不得不實現之外,其他方法都是直接調用 HashMap 中的方法。

HashMap HashSet
實現了Map接口 實現Set接口
存儲鍵值對 僅存儲對象
調用 put()向map中添加元素 調用 add()方法向Set中添加元素
HashMap使用鍵(Key)計算Hashcode HashSet使用成員對象來計算hashcode值,對於兩個對象來說hashcode可能相同,所以equals()方法用來判斷對象的相等性,

6、HashSet如何檢查重複

當你把對象加入HashSet時,HashSet會先計算對象的hashcode值來判斷對象加入的位置,同時也會與其他加入的對象的hashcode值作比較,如果沒有相符的hashcode,HashSet會假設對象沒有重複出現。但是如果發現有相同hashcode值的對象,這時會調用equals()方法來檢查hashcode相等的對象是否真的相同。如果兩者相同,HashSet就不會讓加入操作成功。(摘自我的Java啓蒙書《Head fist java》第二版)

hashCode()與equals()的相關規定

  1. 如果兩個對象相等,則hashcode一定也是相同的
  2. 兩個對象相等,對兩個equals方法返回true
  3. 兩個對象有相同的hashcode值,它們也不一定是相等的
  4. 綜上,equals方法被覆蓋過,則hashCode方法也必須被覆蓋
  5. hashCode()的默認行爲是對堆上的對象產生獨特值。如果沒有重寫hashCode(),則該class的兩個對象無論如何都不會相等(即使這兩個對象指向相同的數據)。

==與equals的區別

  1. ==是判斷兩個變量或實例是不是指向同一個內存空間 equals是判斷兩個變量或實例所指向的內存空間的值是不是相同
  2. ==是指對內存地址進行比較 equals()是對字符串的內容進行比較
  3. ==指引用是否相同 equals()指的是值是否相同

7、comparable和comparator的區別

  • comparable接口實際上是java.lang包。它有一個compareTo(Object obj)方法用來排序
  • comparator接口實際上是java.util包它有一個compare(Object obj1, Object obj2)方法用來排序

一般我們需要對一個幾個使用自定義排序時,就要重寫compare方法或compareTo方法,當我們需要對某一個集合使用兩種排序方式。比如一個song對象中的歌手和歌名分別採用一種排序方式的話,我們可以重寫compareTo方法和使用自制的Comparator方法或者以兩個Comparator來實現歌名排序和歌星名排序,第二種代表我們只能使用兩個參數版的Collections.sort().

8、集合框架底層數據結構總結

Collection
1.list

  • ArrayList:Object數組
  • Vector:Object數組
  • LinkList:雙向列表(JDK1.6之前爲鏈表循環,JDK1.7取消了循環)

2.Set

  • HashSet(無序,唯一):基於HashMap實現的,底層採用HashMap來保存元素
  • LinkHashSet:LinkHashSet繼承與HashSet,並且內部是通過LinkHashMap實現的。
  • TreeSet(有序,唯一):紅黑樹(自平衡的排序二叉樹)

Map

  • HashMap:JDK1.8之前HashMap由數組+鏈表組成,數組是HashMap的主體,鏈表則是爲了解決哈希衝突而存在的。JDK1.8以後在解決哈希衝突時有了較大的變化,當鏈表長度大於閾值(默認爲8時),將鏈表轉化爲紅黑樹,以減少搜索時間
  • LinkHashMap:LinkHashMap繼承自HashMap,所以它的底層任然是基於拉鍊式散列結構,也就是數組和鏈表或紅黑樹組成。另外,LinkHashMap在上面結構的基礎上,增加了一條雙向鏈表,使得上面的結構可以保持鍵值對的插入順序。同時通過對鏈表的同時操作,實現了訪問順序相關邏輯。
  • Hashtable: 數組+鏈表組成的,數組是 HashMap 的主體,鏈表則是主要爲了解決哈希衝突而存在的
  • TreeMap: 紅黑樹(自平衡的排序二叉樹)

9、如何選用集合

主要根據集合的特點來選用,比如我們需要根據鍵值獲取元素值就選用Map接口下的集合,需要排序時選擇TreeMap,不需要排序時就現在HashMap,需要保證線程安全時就選用ConcurrentHashMap。當我們只需要存放元素數據時,就選擇實現Collection接口的集合,需要保證元素唯一時選擇實現Set接口的集合比如TreeSet或HashSet,不需要就選擇實現List接口
比如ArrayList或LinkList,然後再根據實現這些接口的集合的特點來選用。

 

 

 
 
 
 
 
 
 
 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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