Java集合總結【面試題+腦圖】,將知識點一網打盡!

Java3y發表於2018-04-16

前言

宣告,本文用的是jdk1.8

花了一個星期,把Java容器核心的知識過了一遍,感覺集合已經無所畏懼了!!(哈哈哈....),現在來總結一下吧~~

回顧目錄:

Java容器可分為兩大類:

  • Collection
    • List
      • ArrayList
      • LinkedList
      • Vector(瞭解,已過時)
    • Set
      • HashSet
        • LinkedHashSet
      • TreeSet
  • Map
    • HashMap
      • LinkedHashMap
    • TreeMap
    • ConcurrentHashMap
    • Hashtable(瞭解,,已過時)

著重標出的那些就是我們用得最多的容器。

其實,我也不知道要怎麼總結好,因為之前寫每一篇的時候都總結過了。現在又把他們重新羅列出來好像有點水,所以,我決定去回答一些Java容器的面試題!

當然了,我的答案未必就是正確的。如果有錯誤的地方大家多多包含,希望不吝在評論區留言指正~~

一、ArrayList和Vector的區別

共同點:

  • 這兩個類都實現了List介面,它們都是有序的集合(儲存有序),底層是陣列。我們可以按位置索引號取出某個元素,允許元素重複和為null

區別:

  • 同步性:
    • ArrayList是非同步的
    • Vector是同步的
    • 即便需要同步的時候,我們可以使用Collections工具類來構建出同步的ArrayList而不用Vector
  • 擴容大小:
    • Vector增長原來的一倍,ArrayList增長原來的0.5倍

二、HashMap和Hashtable的區別

共同點:

  • 從儲存結構和實現來講基本上都是相同的,都是實現Map介面~

區別:

  • 同步性:
  • 是否允許為null:
    • HashMap允許為null
    • Hashtable不允許為null
  • contains方法
    • 這知識點是在牛客網刷到的,沒想到這種題還會有(我不太喜歡)....
    • Hashtable有contains方法
    • HashMap把Hashtable的contains方法去掉了,改成了containsValue和containsKey
  • 繼承不同:
    • HashMap<K,V> extends AbstractMap<K,V>
    • public class Hashtable<K,V> extends Dictionary<K,V>

三、List和Map的區別

共同點:

  • 都是Java常用的容器,都是介面(ps:寫出來感覺好像和沒寫一樣.....)

不同點:

  • 儲存結構不同
    • List是儲存單列的集合
    • Map儲存的是key-value鍵值對的集合
  • 元素是否可重複
    • List允許元素重複
    • Map不允許key重複
  • 是否有序
    • List集合是有序的(儲存有序)
    • Map集合是無序的(儲存無序)

四、Set裡的元素是不能重複的,那麼用什麼方法來區分重複與否呢? 是用==還是equals()?

我們知道Set集合實際大都使用的是Map集合的put方法來新增元素

以HashSet為例,HashSet裡的元素不能重複,在原始碼(HashMap)是這樣體現的:

	
	// 1. 如果key 相等  
    if (p.hash == hash &&
        ((k = p.key) == key || (key != null && key.equals(k))))
        e = p;
	// 2. 修改對應的value
	   if (e != null) { // existing mapping for key
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
       }
複製程式碼

新增元素的時候,如果key(也對應的Set集合的元素)相等,那麼則修改value值。而在Set集合中,value值僅僅是一個Object物件罷了(該物件對Set本身而言是無用的)。

也就是說:Set集合如果新增的元素相同時,是根本沒有插入的(僅修改了一個無用的value值)!從原始碼(HashMap)中也看出來,==和equals()方法都有使用

五、Collection和Collections的區別

  1. Collection是集合的上級介面,繼承它的有Set和List介面
  2. Collections是集合的工具類,提供了一系列的靜態方法對集合的搜尋、查詢、同步等操作

六、說出ArrayList,LinkedList的儲存效能和特性

ArrayList的底層是陣列,LinkedList的底層是雙向連結串列。

  • ArrayList它支援以角標位置進行索引出對應的元素(隨機訪問),而LinkedList則需要遍歷整個連結串列來獲取對應的元素。因此一般來說ArrayList的訪問速度是要比LinkedList要快的
  • ArrayList由於是陣列,對於刪除和修改而言消耗是比較大(複製和移動陣列實現),LinkedList是雙向連結串列刪除和修改只需要修改對應的指標即可,消耗是很小的。因此一般來說LinkedList的增刪速度是要比ArrayList要快的

6.1擴充套件:

ArrayList的增刪未必就是比LinkedList要慢。

  • 如果增刪都是在末尾來操作【每次呼叫的都是remove()和add()】,此時ArrayList就不需要移動和複製陣列來進行操作了。如果資料量有百萬級的時,速度是會比LinkedList要快的。(我測試過)
  • 如果刪除操作的位置是在中間。由於LinkedList的消耗主要是在遍歷上,ArrayList的消耗主要是在移動和複製上(底層呼叫的是arraycopy()方法,是native方法)。
    • LinkedList的遍歷速度是要慢於ArrayList的複製移動速度的
    • 如果資料量有百萬級的時,還是ArrayList要快。(我測試過)

七、Enumeration和Iterator介面的區別

這個我在前面的文章中也沒有詳細去講它們,只是大概知道的是:Iterator替代了Enumeration,Enumeration是一箇舊的迭代器了。

與Enumeration相比,Iterator更加安全,因為當一個集合正在被遍歷的時候,它會阻止其它執行緒去修改集合

  • 我們在做練習的時候,迭代時會不會經常出錯,丟擲ConcurrentModificationException異常,說我們在遍歷的時候還在修改元素。
  • 這其實就是fail-fast機制~具體可參考博文:blog.csdn.net/panweiwei19…

區別有三點:

  • Iterator的方法名比Enumeration更科學
  • Iterator有fail-fast機制,比Enumeration更安全
  • Iterator能夠刪除元素,Enumeration並不能刪除元素

八、ListIterator有什麼特點

  • ListIterator繼承了Iterator介面,它用於遍歷List集合的元素
  • ListIterator可以實現雙向遍歷,新增元素,設定元素

看一下原始碼的方法就知道了:

Java集合總結【面試題+腦圖】,將知識點一網打盡!

九、併發集合類是什麼?

Java1.5併發包(java.util.concurrent)包含執行緒安全集合類,允許在迭代時修改集合

  • Utils包下的集合迭代器被設計為fail-fast的,會丟擲ConcurrentModificationException。但java.util.concurrent的並不會,感謝評論區提醒~
  • 一部分類為:
    • CopyOnWriteArrayList
    • ConcurrentHashMap
    • CopyOnWriteArraySet

十、Java中HashMap的key值要是為類物件則該類需要滿足什麼條件?

需要同時重寫該類的hashCode()方法和它的equals()方法

  • 從原始碼可以得知,在插入元素的時候是先算出該物件的hashCode。如果hashcode相等話的。那麼表明該物件是儲存在同一個位置上的。
  • 如果呼叫equals()方法,兩個key相同,則替換元素
  • 如果呼叫equals()方法,兩個key不相同,則說明該hashCode僅僅是碰巧相同,此時是雜湊衝突,將新增的元素放在桶子上

一般來說,我們會認為:只要兩個物件的成員變數的值是相等的,那麼我們就認為這兩個物件是相等的!因為,Object底層比較的是兩個物件的地址,而對我們開發來說這樣的意義並不大~這也就為什麼我們要重寫equals()方法

重寫了equals()方法,就要重寫hashCode()的方法。因為equals()認定了這兩個物件相同,而同一個物件呼叫hashCode()方法時,是應該返回相同的值的!

十一、與Java集合框架相關的有哪些最好的實踐

  1. 根據需要確定集合的型別。如果是單列的集合,我們考慮用Collection下的子介面ArrayList和Set。如果是對映,我們就考慮使用Map~
  2. 確定完我們的集合型別,我們接下來確定使用該集合型別下的哪個子類~我認為可以簡單分成幾個步驟:
    • 是否需要同步
      • 去找執行緒安全的集合類使用
    • 迭代時是否需要有序(插入順序有序)
      • 去找Linked雙向列表結構的
    • 是否需要排序(自然順序或者手動排序)
      • 去找Tree紅黑樹型別的(JDK1.8)
  3. 估算存放集合的資料量有多大,無論是List還是Map,它們實現動態增長,都是有效能消耗的。在初始集合的時候給出一個合理的容量會減少動態增長時的消耗~
  4. 使用泛型,避免在執行時出現ClassCastException
  5. 儘可能使用Collections工具類,或者獲取只讀、同步或空的集合,而非編寫自己的實現。它將會提供程式碼重用性,它有著更好的穩定性和可維護性

十二、ArrayList集合加入1萬條資料,應該怎麼提高效率

ArrayList的預設初始容量為10,要插入大量資料的時候需要不斷擴容,而擴容是非常影響效能的。因此,現在明確了10萬條資料了,我們可以直接在初始化的時候就設定ArrayList的容量

這樣就可以提高效率了~

十三、總結

2018年4月15日17:14:03,上面找了一些面試題答了一下,感覺不夠過癮呀。很多我覺得比較重要的知識點我都沒有找到對應的面試題(可能我搜尋的能力太水了?)。

將這篇文章作為集合的總結篇,但覺得沒什麼好寫就回答一些面試題去了,找了一會面試題又覺得不夠系統。而這篇總結我又不想複製前面的章節總結到這裡來。於是我決定畫一個腦圖來結束這篇文章

2018年4月15日19:31:33 畫完啦!!!!!

Java集合總結【面試題+腦圖】,將知識點一網打盡!

需要更多腦圖的同學可關注公眾號:Java3y,回覆【腦圖】即可~

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y。謝謝支援了!希望能多介紹給其他有需要的朋友

文章的目錄導航zhongfucheng.bitcron.com/post/shou-j…

目前初步打算寫多執行緒,你們覺得怎麼樣呢?可以在評論區留言~

相關文章