1. 程式人生 > >java 集合面試題

java 集合面試題

  1. 下列說法正確的是() 
    A. LinkedList繼承自List B. AbstractSet繼承自Set C. HashSet繼承自AbstractSet D. WeakMap繼承自HashMap 
    這裡寫圖片描述
    答案:AC

解析:下面是一張下載的 Java 中的集合型別的繼承關係圖,一目瞭然。

collection

2 ArrayList list = new ArrayList(20);中的 list 擴充幾次? 
A. 0 
B. 1 
C. 2 
D. 3

答案:A

解析:這裡有點迷惑人,大家都知道預設 ArrayList 的長度是 10 個,所以如果你要往 list 裡新增 20 個元素肯定要擴充一次(擴充為原來的 1.5 倍),但是這裡顯示指明瞭需要多少空間,所以就一次性為你分配這麼多空間,也就是不需要擴充了。

3 . Java集合類框架的基本介面有哪些? 
Java 集合類提供了一套設計良好的支援對一組物件進行操作的介面和類。Java集合類裡面最基本的介面有:

Collection:代表一組物件,每一個物件都是它的子元素。

Set:不包含重複元素的 Collection。

List:有順序的 collection,並且可以包含重複元素。

Map:可以把鍵(key)對映到值(value)的物件,鍵不能重複。

4 . 為什麼集合類沒有實現 Cloneable 和 Serializable 介面? 
集合類介面指定了一組叫做元素的物件。集合類介面的每一種具體的實現類都可以選擇以它自己的方式對元素進行儲存和排序。有的集合類允許重複的鍵,有些不允許。

5 . 什麼是迭代器(Iterator)? 
Iterator 介面提供了很多對集合元素進行迭代的方法。每一個集合類都包含了可以返回迭代器例項的 迭代方法。迭代器可以在迭代的過程中刪除底層集合的元素。

克隆(cloning)或者是序列化(serialization)的語義和含義是跟具體的實現相關的。因此,應該由集合類的具體實現來決定如何被克隆或者是序列化。

6 . Iterator和ListIterator的區別是什麼? 
下面列出了他們的區別:

Iterator 可用來遍歷 Set 和 List 集合,但是 ListIterator 只能用來遍歷 List 。

Iterator 對集合只能是前向遍歷,ListIterator 既可以前向也可以後向。

ListIterator 實現了 Iterator 介面,幷包含其他的功能,比如:增加元素,替換元素,獲取前一個和後一個元素的索引,等等。

7 . 快速失敗(fail-fast)和安全失敗(fail-safe)的區別是什麼? 
Iterator 的安全失敗是基於對底層集合做拷貝,因此,它不受源集合上修改的影響。java.util 包下面的所有的集合類都是快速失敗的,而 java.util.concurrent 包下面的所有的類都是安全失敗的。快速失敗的迭代器會丟擲 ConcurrentModificationException 異常,而安全失敗的迭代器永遠不會丟擲這樣的異常。

8 . Java 中的 HashMap 的工作原理是什麼? 
Java 中的 HashMap 是以鍵值對(key-value)的形式儲存元素的。HashMap 需要一個hash函式,它使用 hashCode()和 equals()方法來向集合/從集合新增和檢索元素。當呼叫 put()方法的時候,HashMap會計算 key 的 hash 值,然後把鍵值對儲存在集合中合適的索引上。如果 key 已經存在了,value 會被更新成新值。HashMap 的一些重要的特性是它的容量(capacity),負載因子(load factor)和擴容極限(threshold resizing)。

9 . hashCode() 和 equals() 方法的重要性體現在什麼地方? 
Java 中的 HashMap 使用 hashCode() 和 equals() 方法來確定鍵值對的索引,當根據鍵獲取值的時候也會用到這兩個方法。如果沒有正確的實現這兩個方法,兩個不同的鍵可能會有相同的 hash 值,因此,可能會被集合認為是相等的。而且,這兩個方法也用來發現重複元素。所以這兩個方法的實現對 HashMap 的精確性和正確性是至關重要的。

10 . HashMap 和 Hashtable 有什麼區別? 
HashMap 和 Hashtable 都實現了 Map 介面,因此很多特性非常相似。但是,他們有以下不同點: HashMap 允許鍵和值是 null,而 Hashtable 不允許鍵或者值是 null。

Hashtable 是同步的,而 HashMap 不是。因此, HashMap 更適合於單執行緒環境,而 Hashtable 適合於多執行緒環境。

HashMap 提供了可供應用迭代的鍵的集合,因此,HashMap 是快速失敗的。另一方面,Hashtable 提供了對鍵的列舉(Enumeration)。

一般認為 Hashtable 是一個遺留的類。

11 . 陣列(Array)和列表(ArrayList)有什麼區別?什麼時候應該使用 Array 而不是 ArrayList? 
下面列出了 Array 和 ArrayList 的不同點:

Array 可以包含基本型別和物件型別,ArrayList 只能包含物件型別。

Array 大小是固定的,ArrayList 的大小是動態變化的。

ArrayList 提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。 對於基本型別資料,集合使用自動裝箱來減少編碼工作量。但是,當處理固定大小的基本資料型別的時候,這種方式相對比較慢。

12 . ArrayList 和 LinkedList 有什麼區別? 
ArrayList 和 LinkedList 都實現了 List 介面,他們有以下的不同點:

ArrayList 是基於索引的資料介面,它的底層是陣列。它可以以O(1)時間複雜度對元素進行隨機訪問。與此對應,LinkedList 是以元素列表的形式儲存它的資料,每一個元素都和它的前一個和後一個元素連結在一起,在這種情況下,查詢某個元素的時間複雜度是O(n)。

相對於 ArrayList,LinkedList 的插入,新增,刪除操作速度更快,因為當元素被新增到集合任意位置的時候,不需要像陣列那樣重新計算大小或者是更新索引。

LinkedList 比 ArrayList 更佔記憶體,因為 LinkedList 為每一個節點儲存了兩個引用,一個指向前一個元素,一個指向下一個元素。

也可以參考 ArrayList vs. LinkedList。

13 . Comparable 和Comparator 介面是幹什麼的?列出它們的區別。 
Java 提供了只包含一個 compareTo() 方法的 Comparable 介面。這個方法可以個給兩個物件排序。具體來說,它返回負數,0,正數來表明輸入物件小於,等於,大於已經存在的物件。

Java 提供了包含 compare() 和 equals() 兩個方法的 Comparator 介面。compare() 方法用來給兩個輸入引數排序,返回負數,0,正數表明第一個引數是小於,等於,大於第二個引數。equals() 方法需要一個物件作為引數,它用來決定輸入引數是否和 comparator 相等。只有當輸入引數也是一個 comparator 並且輸入引數和當前 comparator 的排序結果是相同的時候,這個方法才返回 true。

14 . Java集合類框架的最佳實踐有哪些? 
根據應用的需要正確選擇要使用的集合的型別對效能非常重要,比如:假如元素的大小是固定的,而且能事先知道,我們就應該用 Array 而不是 ArrayList。 有些集合類允許指定初始容量。因此,如果我們能估計出儲存的元素的數目,我們可以設定初始容量來避免重新計算 hash 值或者是擴容。

為了型別安全,可讀性和健壯性的原因總是要使用泛型。同時,使用泛型還可以避免執行時的 ClassCastException。

使用 JDK 提供的不變類(immutable class)作為Map的鍵可以避免為我們自己的類實現 hashCode() 和 equals() 方法。

程式設計的時候介面優於實現。

底層的集合實際上是空的情況下,返回長度是0的集合或者是陣列,不要返回 null。

15 . Enumeration 介面和 Iterator 介面的區別有哪些? 
Enumeration 速度是 Iterator 的2倍,同時佔用更少的記憶體。但是,Iterator 遠遠比 Enumeration 安全,因為其他執行緒不能夠修改正在被 iterator 遍歷的集合裡面的物件。同時,Iterator 允許呼叫者刪除底層集合裡面的元素,這對 Enumeration 來說是不可能的。

16 . HashSet 和 TreeSet 有什麼區別? 
HashSet 是由一個 hash 表來實現的,因此,它的元素是無序的。add(),remove(),contains()方法的時間複雜度是 O(1)。

另一方面,TreeSet 是由一個樹形的結構來實現的,它裡面的元素是有序的。因此,add(),remove(),contains() 方法的時間複雜度是 O(logn)。

17 . List、Set、Map 是否繼承自 Collection 介面? 
答:List、Set 是,Map 不是。Map 是鍵值對對映容器,與 List 和 Set 有明顯的區別,而 Set 儲存的零散的元素且不允許有重複元素(數學中的集合也是如此),List 是線性結構的容器,適用於按數值索引訪問元素的情形。

18 . 說出 ArrayList、Vector、LinkedList 的儲存效能和特性? 
答:ArrayList 和 Vector 都是使用陣列方式儲存資料,此陣列元素數大於實際儲存的資料以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及陣列元素移動等記憶體操作,所以索引資料快而插入資料慢,Vector 由於使用了 synchronized 方法(執行緒安全),通常效能上較 ArrayList 差,而 LinkedList 使用雙向連結串列實現儲存(將記憶體中零散的記憶體單元通過附加的引用關聯起來,形成一個可以按序號索引的線性結構,這種鏈式儲存方式與陣列的連續儲存方式相比,其實對記憶體的利用率更高),按序號索引資料需要進行前向或後向遍歷,但是插入資料時只需要記錄本項的前後項即可,所以插入速度較快。

Vector 屬於遺留容器(早期的 JDK 中使用的容器,除此之外 Hashtable、Dictionary、BitSet、Stack、Properties 都是遺留容器),現在已經不推薦使用,但是由於 ArrayList 和 LinkedListed 都是非執行緒安全的,如果需要多個執行緒操作同一個容器,那麼可以通過工具類 Collections 中的 synchronizedList 方法將其轉換成執行緒安全的容器後再使用(這其實是裝潢模式最好的例子,將已有物件傳入另一個類的構造器中建立新的物件來增加新功能)。

19 . List、Map、Set 三個介面儲存元素時各有什麼特點? 
答:

1)List 是有序的 Collection,使用此介面能夠精確的控制每個元素插入的位置。使用者能夠使用索引(元素在 List 中的位置,類似於陣列下標)來訪問 List 中的元素,這類似於 Java 的陣列。

2)Set 是一種不包含重複的元素的 Collection,即任意的兩個元素 e1 和 e2 都有e1.equals(e2)=false,Set 最多有一個 null 元素。

3)Map 介面 :請注意,Map 沒有繼承 Collection 介面,Map 提供 key 到 value 的對映

20 . 判斷下列語句是否正確,如果有錯誤,請指出錯誤所在? 
List a = new ArrayList();

a.add(5);

答:錯誤,預設封裝 int 型別。

  1. 你是怎麼理解 Java 泛型的? 
    答: 在 Java SE 1.5之前,沒有泛型的情況的下,通過對型別 Object 的引用來實現引數的“任意化”,“任意化”帶來的缺點是要做顯式的強制型別轉換,而這種轉換是要求開發者對實際引數型別可以預知的情況下進行的。對於強制型別轉換錯誤的情況,編譯器可能不提示錯誤,在執行的時候才出現異常,這是一個安全隱患。

泛型是 Java SE 1.5的新特性,泛型的本質是引數化型別,也就是說所操作的資料型別被指定為一個引數。這種引數型別可以用在類、介面和方法的建立中,分別稱為泛型類、泛型介面、泛型方法。

泛型的好處是在編譯的時候檢查型別安全,並且所有的強制轉換都是自動和隱式的,提高程式碼的重用率。