Java集合框架及其面試重點

目錄

目錄

一、集合框架概述

二、面試重點

1、List接口

介紹Java的List,ArrayList與LinkedList的區別

Array(數組)和ArrayList有何區別?什麼時候更適合用Array?

List是線程安全的嗎?如果要線程安全要怎麼做?

怎麼給List排序?

通過Array.asList獲得的List有何特點,使用時應該注意什麼?

List和Array之間如何互相轉換?

ArrayList的刪除,需要注意List刪除後下標變化的坑(用Iterator的寫法)

什麼是fail-fast,什麼是fail-safe,有什麼區別嗎?

List的迭代方式有哪些?

在迭代一個集合的時候,如何避免ConcurrentModificationException?

2、set接口

HashSet是如何保證數據不可重複的?

HashSet 底層數據結構

LinkedHashSet 底層數據結構及其特點

TreeSet的底層數據結構及其特點

3、map接口

HashMap的底層數據結構

HashMap與HashTable的區別?

HashMap是否線程安全,體現在什麼地方?

HashMap的擴容操作是怎麼實現的?

爲什麼數組長度要保持爲2的冪次方?

HashMap是怎麼解決哈希衝突的?

HashMap爲什麼不直接使用hashCode()處理後的哈希值直接作爲table的下標?

HashMap在JDK1.7和JDK1.8中有哪些不同?

爲什麼HashMap中String、Integer這樣的包裝類適合作爲Key?我們能否使用任何類作爲Map的key?如果能需要注意哪些問題

HashMap和HashTable有何不同?

ConcurrentHashMap和Hashtable的區別?

ConcurrentHashMap在JDK1.7和JDK1.8中有哪些不同?

4、Queue接口

BlockingQueue的特點?

隊列和棧的區別?

5、Collection框架

Collection框架中實現比較要實現什麼接口

集合在遍歷過程中是否可以刪除元素,爲什麼迭代器就可以安全刪除元素

Enumeration和Iterator接口的區別?

併發集合類是什麼?

如何從給定集合那裏創建線程安全的集合?

Collection和Collections的區別

Iterator和Iterable接口的區別


一、集合框架概述

Java集合框架是一個很重要的內容,面試中也是屬於必考的部分,那麼首先,什麼是集合?什麼是集合框架呢?集合框架有什麼優點?

通常我們把具有相同性質的一類東西,匯聚成一個整體,就可以稱爲集合。集合框架是爲表示和操作集合而規定的一種統一的標準的體系結構。任何集合框架都包含三大塊內容:對外的接口、接口的實現和對集合運算的算法。

集合框架的優點:

(1)使用核心集合類降低開發成本,而非實現我們自己的集合類。

(2)隨着使用經過嚴格測試的集合框架類,代碼質量會得到提高。

(3)通過使用JDK附帶的集合類,可以降低代碼維護成本。

(4)複用性和可操作性。

 

集合框架常用實現類如下:

在集合框架中,主要可以分爲三個大類:list(列表)、set(集)、map(映射)

list是有序的,元素按照添加進list的順序排序,元素可以重複,訪問時可以根據元素的索引來訪問,使用Iterator時的遍歷順序和元素添加的順序一致;

set是無序的,因此使用迭代器(Iterator)的時候,不能保證元素的遍歷順序,但是可以保證所有元素被遍歷;此外,set中不允許出現重複的元素,訪問的時候只能通過元素本身來訪問(這也是元素不能重複的原因);

map保存的是<key,value>鍵值對,key不能重複,但是value可以重複,訪問時只能根據key來訪問value,使用Iterator時,對key進行遍歷,然後根據每個key訪問相應的value;

此外,還有queue接口和一些在併發中涉及到的集合。

 

二、面試重點

1、List接口

List接口是Collection接口的子接口,通常用於表示有序的數組(可以動態擴容),鏈表,隊列,棧等。其實現類主要有3個:ArrayList、LinkedList 和 Vector(線程安全)。

面試中主要涉及的問題有:

介紹Java的List,ArrayList與LinkedList的區別

ArrayList與LinkedList、Vector的區別

Array(數組)和ArrayList有何區別?什麼時候更適合用Array?

區別:

  • 數組的長度固定不變,而ArrayList是動態數組,在容量不夠是會進行1.5倍的擴容
  • 數組的元素可以是基本類型或者對象,但ArrayList只能是對象(直接放入的基本類型經過自動裝箱成爲包裝類對象)
  • 數組中所有元素類型必須是一樣的,但是ArrayList可以存儲Object對象,因此如果把泛型類型限制爲Object則可以存儲不同類型的元素
  • ArrayList比數組的方法更加豐富,還可以有自己的迭代器對象

使用場景:

  • 當集合長度固定,並且只需要對數組進行簡單的隨機讀寫,使用數組,因爲數組佔用內存更低;如果集合長度可變,並且需要有插入、刪除等操作,選擇ArrayList,因爲ArrayList集成了相關操作,並且可以自動擴容。當然如果插入和刪除的操作十分的頻繁還是使用LinkedList。
  • 當存儲的時基本數據類型,因爲ArrayList不支持基本數據類型,需要進行自動裝箱和拆箱,效率相對下降,因此儘量選擇數組。

List是線程安全的嗎?如果要線程安全要怎麼做?

實現list實現類的線程安全:

  • List接口下的實現類,只有Vector及其子類Stack時線程安全的,其他都是非線程安全的,因此可以使用Vector來代替ArrayList
  • 可以使用Collections.synchronizedList(List<T> list)方法包裝list的實現類即可,同樣的可以用Collections.synchronizedSet(Set<T> set)、Collections.synchronizedMap(Map<K,V> m)、Collections.synchronizedCollection(Collection<Object>)方法包裝集合框架的其他非線程安全實現類來實現線程安全的類。

兩種方法的區別:

  • 如果使用add方法,那麼他們的擴容機制不一樣(類似arraylist和Vector的區別)。

  • SynchronizedList可以通過Collections.synchronizedList(List<T> list,Object mutex)指定鎖定的對象。通過Collections的源代碼也可以看出Collections.synchronizedList返回的是內部類SynchronizedList,其中同步的實現是通過synchronized(mutex)同步代碼塊實現的,可以認爲Collections.synchronizedList鎖粒度是同步代碼塊。而Vector的鎖粒度是同步方法。

  • SynchronizedList有很好的擴展性和兼容功能。他可以將所有的list子類轉成線程安全的類。

  • 使用SynchronizedList的時候,進行遍歷時需要手動進行同步處理,這是因爲Collections.synchronizedList的迭代器iterator並沒有做同步處理,而是直接使用了list的iterator。

怎麼給List排序?

list、set、map的排序

通過Array.asList獲得的List有何特點,使用時應該注意什麼?

asList()方法返回的list的特點:

Array.asList()方法的作用是將數組轉換爲list集合,但是通過其源代碼可以發現,Array.asList()返回的是Arrays的一個內部類,該內部類只是實現了AbstractList接口,但是其後臺仍然是數組的數據結構,也就是說,得到的只是原來數組的視圖List,而沒有實現list集合的add和remove等修改方法,因此如果對他進行增刪操作會報UnsupportOperationException異常。

具體案例參考:https://www.cnblogs.com/hoobey/p/6661294.html

如何實現得到真的list:

用ArrayList的構造器可以將其轉變成爲一個真正的ArrayList

Integer[] a={1,2,3,4,5};
ArrayList al= new ArrayList(Arrays.asList(a));

需要注意的是,Array.asList()方法對基本數據類型的數組是無效的:如下代碼所示,對於基本數據類型,ArrayList中的元素只有一個,就是數組本身。

int[] a={1,2,3,4,5};
ArrayList al= new ArrayList(Arrays.asList(a));
System.out.println(al.size());
//返回:1

List和Array之間如何互相轉換?

  • 數組(Array)轉list:Array.asList()方法,同上
  • list轉數組(Array):list.toArray()方法

ArrayList的刪除,需要注意List刪除後下標變化的坑(用Iterator的寫法)

元素刪除的集中方法及其注意事項

什麼是fail-fast,什麼是fail-safe,有什麼區別嗎?

fail-fast 與 fail-safe 機制的原理與區別

List的迭代方式有哪些?

Collection集合實現類(list、set和queue)的集中迭代方式

在迭代一個集合的時候,如何避免ConcurrentModificationException?

什麼時候會出現ConcurrentModificationException異常:

首先,ConcurrentModificationException異常是當條件modCount != expectedModCount成立時產生的,而這個比較是在迭代器(Iterator)的checkForComodification()方法中出現的,而Iterator的next()和remove()都調用了該方法,而expectedModCount是在獲取迭代器的時候初始化的,也就是說,如果在調用Iterator的next()和remove()時modCount被修改,那麼checkForComodification()方法會拋出ConcurrentModificationException異常。那麼,什麼情況會導致modCount被修改呢?add()、remove()操作都會。(foreach循環底層也是使用迭代器因此也hi出現該異常)

因此,在使用迭代器(Iterator)的時候使用list.add()、list.clear()和list.remove()方法都會導致ConcurrentModificationException異常。

詳細代碼參考:https://www.jianshu.com/p/00be866fcb18

如何避免ConcurrentModificationException異常:

  • 如果是remove()操作,使用迭代器(Iterator)自己的reemove()方法;listIterator有add()和remove()方法;
  • 使用Collections.synchronizedCollection() 去同步集合, 但是這樣可能會影響效率,;
  • 使用concurrent包裏的CopyOnWriteArrayList,  因爲他的迭代器中沒有checkForComodification;

 

2、set接口

set也是Collection接口的子接口,常見實現類有HashSet和TreeSet 。set集合中不允許有重複的元素是因爲set集合用來比較兩個元素是否相等時使用的是equals()方法,而不是“==”運算符,因此只要兩個元素內容相同,就不能在一個set中共存,如果已經在set集合中存在了a元素,再使用add()方法添加a元素會返回false。

面試中主要涉及的問題有:

HashSet是如何保證數據不可重複的?

HashSet 底層數據結構

LinkedHashSet 底層數據結構及其特點

TreeSet的底層數據結構及其特點

 

3、map接口

map存儲的是<key,value>鍵值對,而每個值又可以是一個map,以此類推,可以實現多層的映射。map接口常見的實現類有HashMap,TreeMap,HashTable等。map的key和set一樣,不允許重複,但是value可以重複。從概念上來看,可以把List看做一種特殊的map,把List的索引當做key,把list的元素當做value,這樣就可以形成鍵值對,但是事實上List和map並沒有太多的關係。

面試中主要涉及的問題有:

HashMap的底層數據結構

HashMap與HashTable的區別?

HashMap是否線程安全,體現在什麼地方?

HashMap的擴容操作是怎麼實現的?

爲什麼數組長度要保持爲2的冪次方?

hashCode的計算及其相關難點解答

HashMap是怎麼解決哈希衝突的?

HashMap爲什麼不直接使用hashCode()處理後的哈希值直接作爲table的下標?

HashMap在JDK1.7和JDK1.8中有哪些不同?

爲什麼HashMap中String、Integer這樣的包裝類適合作爲Key?我們能否使用任何類作爲Map的key?如果能需要注意哪些問題

HashMap和HashTable有何不同?

ConcurrentHashMap和Hashtable的區別?

ConcurrentHashMap在JDK1.7和JDK1.8中有哪些不同?

 

4、Queue接口

BlockingQueue的特點?

隊列和棧的區別?

 

5、Collection框架

Collection框架中實現比較要實現什麼接口

集合在遍歷過程中是否可以刪除元素,爲什麼迭代器就可以安全刪除元素

Enumeration和Iterator接口的區別?

併發集合類是什麼?

如何從給定集合那裏創建線程安全的集合?

Collection和Collections的區別

Iterator和Iterable接口的區別

發佈了56 篇原創文章 · 獲贊 163 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章