21個Java Collections面試問答

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

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

一、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()方法。

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

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

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

Collections 框架的一些好處是;編程

  • 經過使用核心集合類而不是實現咱們本身的集合類來減小開發工做。
  • 經過使用經過良好測試的集合框架類,能夠提升代碼質量。
  • 經過使用JDK附帶的集合類,減小了代碼維護工做。
  • 可重用性和互操做性

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

Java 1.5帶有泛型,全部集合接口和實現都大量使用它。泛型容許咱們提供集合能夠包含的Object的類型,所以,若是您嘗試添加其餘類型的任何元素,則引起編譯時錯誤。數組

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

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

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

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

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

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

其餘一些接口QueueDequeueIteratorSortedSetSortedMapListIterator

五、爲何Collection不實現Cloneable和Serializable接口?

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

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

六、爲何Map接口沒有實現Collection接口?

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

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

七、什麼是迭代器?

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

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

枚舉的速度是Iterator的兩倍,而且使用的內存更少。枚舉是很是基本的,適合基本需求。可是,與Enumeration相比,Iterator安全得多,由於它始終拒絕其餘線程修改被其迭代的集合對象。

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

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

考慮到Iterator的約定不保證迭代順序,緣由尚不清楚。可是請注意,ListIterator確實提供了add操做,由於它確實保證了迭代的順序。

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

能夠在當前Iterator接口的頂部實現它,可是因爲不多使用它,所以將它包含在每一個人都必須實現的接口中沒有意義。

十一、Iterator和ListIterator有什麼區別?

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

十二、有哪些不一樣的方法能夠遍歷列表?

咱們能夠經過兩種不一樣的方式遍歷列表-使用迭代器和使用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

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

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

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

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

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

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

1六、爲何沒有Iterator接口的具體實現?

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

這使集合類能夠選擇迭代器是fail-fast仍是fail-safe的。例如,ArrayList迭代器是fail-fast的,而CopyOnWriteArrayList迭代器是fail-safe的。

1七、什麼是UnsupportedOperationException?

UnsupportedOperationException是用於指示不支持該操做的異常。它普遍用於在JDK類,在集合框架java.util.Collections.UnmodifiableCollection拋出該異常全部addremove操做。

1八、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。 。

1九、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鍵的緣由。

2一、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」...

每日福利

相關文章
相關標籤/搜索