21個Java Collections面試問答

Java Collections框架是Java編程語言的核心API之一。

這是Java面試問題的重要主題之一。在這裏,我列出了一些重要的Java集合面試問題和解答,以幫助您進行面試。這直接來自我14年以上的Java編程經驗。

1、Java 8中與Collections相關的功能是什麼?

Java 8對 Collection API 進行了重大更改。一些更改是:

  1. Java Stream API 用於集合類,以支持順序處理和並行處理
  2. Iterable 接口中的默認方法forEach(),可用於迭代集合。與 lambda 表達式一起使用時,它非常有用,因爲其參數 Consumer 是函數接口。
  3. Collections API 改進,如在Iterator接口中的forEachRemaining(Consumer action),MapreplaceAll()compute()merge()方法。

2、什麼是 Java Collections Framework?列出 Collections 框架的一些好處?

每個編程語言都使用集合,和最初的Java版本包含幾個集合類:VectorStackHashtableArray。但是從較高的範圍和用法來看,Java 1.2提出了Collections Framework,該框架將所有collections接口,實現和算法分組。

Java的集合通過使用泛型和併發集合類進行線程安全操作已經走了很長一段路。它還包括在Java的併發包中的阻塞接口及其實現。

Collections 框架的一些好處是;

  • 通過使用核心集合類而不是實現我們自己的集合類來減少開發工作。
  • 通過使用通過良好測試的集合框架類,可以提高代碼質量。
  • 通過使用JDK附帶的集合類,減少了代碼維護工作。
  • 可重用性和互操作性

3、集合框架中泛型的好處是什麼?

Java 1.5帶有泛型,所有集合接口和實現都大量使用它。泛型允許我們提供集合可以包含的Object的類型,因此,如果您嘗試添加其他類型的任何元素,則引發編譯時錯誤。

這樣可以避免在運行時發生ClassCastException,因爲您將在編譯時收到錯誤。由於我們不需要使用強制轉換和_實例化_運算符,因此泛型也使代碼更乾淨。

4、Java Collections Framework的基本接口是什麼?

Collection 表示集合層次結構的根。Collection表示一組元素的對象。Java平臺不提供此接口的任何直接實現。

Set是一個不能包含重複元素的集合。此接口對數學集合的抽象進行建模,並表示集合,例如紙牌集合。

List是一個有序的集合,可以包含重複的元素。您可以從其索引訪問任何元素。該列表更像是具有動態長度的數組。

一個Map是鍵映射到值的對象。映射不能包含重複的鍵:每個鍵最多可以映射到一個值。

其他一些接口QueueDequeueIteratorSortedSetSortedMapListIterator

5、爲什麼Collection不實現Cloneable和Serializable接口?

Collection接口指定爲一組元素對象。元素的維護方式取決於Collection的具體實現。例如,某些Collection實現(例如List)允許重複元素,而其他實現(例如Set)則不允許重複元素。

許多Collection實現都有Cloneable方法。但是,將其包含在Collection的所有實現中沒有意義。這是因爲Collection是抽象表示。重要的是。
在處理實際實現時,克隆或序列化的語義及其含義都會發揮作用。因此具體的實現應決定如何克隆或序列化它,甚至可以對其進行克隆或序列化。
因此,在所有實現中強制進行克隆和序列化的靈活性較差,限制也更大。具體實現應決定是否可以克隆或序列化。

6、爲什麼Map接口沒有實現Collection接口?

儘管Map接口及其實現是Collections Framework的一部分,但Map不是集合,集合也不是Map。因此,Map擴展Collection是沒有意義的,反之亦然。

如果Map擴展了Collection接口,那麼元素在哪裏?該映射包含key-value對,並且提供了一些方法來檢索鍵或值的列表作爲Collection,但它不適合“元素組”範式。

7、什麼是迭代器?

迭代器接口提供了對任何Collection進行迭代的方法。我們可以使用_iterator()_方法從Collection中獲取迭代器實例。在Java Collections Framework中,迭代器代替了枚舉。迭代器允許調用者在迭代過程中從基礎集合中刪除元素。Java Collection迭代器提供了遍歷集合元素的通用方法,並實現了Iterator Design Pattern

8、Enumeration和Iterator接口之間有什麼區別?

枚舉的速度是Iterator的兩倍,並且使用的內存更少。枚舉是非常基本的,適合基本需求。但是,與Enumeration相比,Iterator安全得多,因爲它始終拒絕其他線程修改被其迭代的集合對象。

在Java Collections Framework中,迭代器代替了枚舉。迭代器允許調用者從基礎集合中刪除Enumeration無法實現的元素。迭代器方法名稱已得到改進,以使其功能更清晰。

9、爲什麼沒有像Iterator.add()這樣的方法將元素添加到集合中?

考慮到Iterator的約定不保證迭代順序,原因尚不清楚。但是請注意,ListIterator確實提供了add操作,因爲它確實保證了迭代的順序。

10、爲什麼Iterator沒有不移動光標就直接獲取下一個元素的方法?

可以在當前Iterator接口的頂部實現它,但是由於很少使用它,因此將它包含在每個人都必須實現的接口中沒有意義。

11、Iterator和ListIterator有什麼區別?

  • 我們可以使用Iterator遍歷Set和List集合,而ListIterator只能與Lists一起使用。
  • Iterator只能向前移動,而ListIterator可以用於兩個方向。
  • ListIterator繼承自Iterator接口,並具有其他功能,例如添加元素,替換元素,獲取上一個和下一個元素的索引位置。

12、有哪些不同的方法可以遍歷列表?

我們可以通過兩種不同的方式遍歷列表-使用迭代器和使用for-each循環。

List <String> strList = new ArrayList<>();

for(String obj:strList){
	System.out.println(obj);
}

Iterator<String> it= strList.iterator();
while(it.hasNext()){
	String obj = it.next();
	System.out.println(obj);
}

使用迭代器更加線程安全,因爲它可以確保如果基礎列表元素被修改,它將拋出異常ConcurrentModificationException

13、您對Iterator fail-fast屬性有什麼瞭解?

每當我們嘗試獲取下一個元素時,迭代器fail-fast屬性都會檢查基礎集合的結構是否有任何修改。如果找到任何修改,則拋出ConcurrentModificationException。除了並行併發類(例如ConcurrentHashMap和CopyOnWriteArrayList)之外,Collection類中Iterator的所有實現在設計上都是fail-fast的。

14、fail-fast和fail-safe之間有何區別?

Iterato fail-safe屬性可與基礎集合的克隆一起使用,因此不受集合中任何修改的影響。按照設計,java.util包中的所有集合類都是fail-fast的,而其中的集合類java.util.concurrent是fail-safe的。
fail-fast迭代器會拋出ConcurrentModificationException,而fail-safe迭代器絕不會拋出ConcurrentModificationException。

15、如何在迭代集合時避免ConcurrentModificationException?

我們可以使用併發集合類來避免ConcurrentModificationException在集合上進行迭代,例如使用CopyOnWriteArrayList而不是ArrayList。

16、爲什麼沒有Iterator接口的具體實現?

Iterator接口聲明瞭用於迭代集合的方法,但是其實現是Collection實現類的責任。每個返回迭代器以進行遍歷的集合類都有其自己的Iterator實現嵌套類。

這使集合類可以選擇迭代器是fail-fast還是fail-safe的。例如,ArrayList迭代器是fail-fast的,而CopyOnWriteArrayList迭代器是fail-safe的。

17、什麼是UnsupportedOperationException?

UnsupportedOperationException是用於指示不支持該操作的異常。它廣泛用於在JDK類,在集合框架java.util.Collections.UnmodifiableCollection拋出該異常所有addremove操作。

18、HashMap如何在Java中工作?

HashMap在Map.Entry靜態嵌套類實現中存儲鍵值對。HashMap使用哈希算法,並在putget方法中使用hashCode()和equals()方法。

當我們put通過傳遞鍵值對來調用方法時,HashMap使用帶有哈希值的Key hashCode()來查找存儲鍵值對的索引。該條目存儲在LinkedList中,因此,如果已經存在一個條目,則使用equals()方法檢查傳遞的鍵是否已存在,如果是,它將覆蓋該值,否則它將創建一個新條目並存儲此鍵值條目。

當我們get通過傳遞Key來調用method時,它再次使用hashCode()在數組中找到索引,然後使用equals()方法找到正確的Entry並返回其值。下圖將清楚地解釋這些細節。

有關HashMap的其他重要信息是容量,負載因子,閾值大小調整。HashMap的初始默認容量爲16,負載係數爲0.75。閾值是容量乘以負載因子,並且如果Map大小大於閾值,則每當我們嘗試添加條目時,HashMap都會將Map的內容重新映射爲容量更大的新數組。容量始終是2的乘方,因此,如果您知道需要存儲大量的鍵值對,例如在緩存數據庫中的數據時,最好使用正確的容量和負載因子來初始化HashMap。 。

19、hashCode()和equals()方法的重要性是什麼?

HashMap使用Key對象的hashCode()和equals()方法來確定放置鍵值對的索引。當我們嘗試從HashMap中獲取價值時,也會使用這些方法。如果這些方法的實現不正確,則兩個不同的Key可能會產生相同的hashCode()和equals()輸出,在這種情況下,HashMap不會考慮將它們存儲在不同的位置,而是將其覆蓋並覆蓋它們。

同樣,所有不存儲重複數據的集合類都使用hashCode()和equals()查找重複項,因此正確實現它們非常重要。equals()和hashCode()的實現應遵循以下規則。

  • 如果o1.equals(o2),那麼o1.hashCode() == o2.hashCode()應該永遠如此true
  • 如果o1.hashCode() == o2.hashCode是真的,這並不意味着o1.equals(o2)true

20、我們可以使用任何類作爲Map鍵嗎?

我們可以將任何類用作Map Key,但是在使用它們之前應考慮以下幾點。

  • 如果該類重寫equals()方法,則它也應該重寫hashCode()方法。

  • 對於所有實例,該類應遵循與equals()和hashCode()關聯的規則。這些規則請參考前面的問題。

  • 如果equals()中未使用類字段,則不應在hashCode()方法中使用它。

  • 用戶定義的鍵類的最佳實踐是使其不可變,以便可以將hashCode()值緩存起來以提高性能。不可變的類還確保hashCode()和equals()將來不會更改,這將解決任何可變性問題。
    例如,假設我有一個MyKey用於HashMap鍵的類。

    //傳遞的mykey name參數用於equals()和hashcode()
    MyKey key = new MyKey("Pankaj"); //假定hashCode=1234
    myHashMap.put(key, "Value");
    
    // 下面的代碼將更改equals()和hashcode()的key
    // 但是它的位置不會改變
    key.setName("Amit"); //假定新的hashCode=7890
    
    //下面將返回null,因爲HashMap將嘗試查找鍵
    //與存儲在同一索引中,但由於密鑰發生了變化,
    //不匹配,返回空。
    myHashMap.get(new MyKey("Pankaj")); 
    

    這就是爲什麼String和Integer大多用作HashMap鍵的原因。

21、Map接口提供哪些不同的Collection視圖?

Map接口提供了三個集合視圖:

  1. Set keySet():返回此映射中包含的鍵的Set視圖。該集合由Map支持,因此對Map的更改會反映在集合中,反之亦然。如果在對集合進行迭代時修改了映射(通過迭代器的remove操作除外),則迭代的結果不確定。該集合支持元素刪除,該元素通過迭代器remove,Set.remove,removeAll,retainAll和clear操作從映射中刪除相應的映射。它不支持add或addAll操作。
  2. Collection values():返回此映射中包含的值的Collection視圖。集合由Map支持,因此對Map的更改會反映在集合中,反之亦然。如果在對集合進行迭代時修改了映射(通過迭代器的remove操作除外),則迭代結果不確定。集合支持元素刪除,該元素通過迭代器remove,Collection.remove,removeAll,retainAll和clear操作從映射中刪除相應的映射。它不支持add或addAll操作。
  3. Set <Map.Entry <K,V >> entrySet():返回此映射中包含的映射的Set視圖。該集合由Map支持,因此對Map的更改會反映在集合中,反之亦然。如果在對集合進行迭代時修改了映射(通過迭代器的remove操作或迭代器返回的映射條目上的setValue操作除外),則迭代的結果不確定。該集合支持元素刪除,該元素通過迭代器remove,Set.remove,removeAll,retainAll和clear操作從映射中刪除相應的映射。它不支持add或addAll操作。

“不積跬步,無以至千里”,希望未來的你能:有夢爲馬 隨處可棲!加油,少年!

關注公衆號:「Java 知己」,每天更新Java知識哦,期待你的到來!

  • 發送「Group」,與 10 萬程序員一起進步。
  • 發送「面試」,領取BATJ面試資料、面試視頻攻略。
  • 發送「玩轉算法」,領取《玩轉算法》系列視頻教程。
  • 千萬不要發送「1024」…

每日福利

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