看代碼,List和Set是繼承自Collection超級接口。
List:
List此接口的可以對列表中每個元素的插入位置進行精確的控制,可以根據(jù)索引訪問元素,并搜索列表中的元素。
1.可以允許重復(fù)的對象。
2.可以插入多個null元素。
3.是一個有序容器,保持了每個元素的插入順序,輸出的順序就是插入的順序。
4.常用的實現(xiàn)類有 ArrayList、LinkedList 和 Vector。ArrayList 最為流行,它提供了使用索引的隨意訪問,而 LinkedList 則對于經(jīng)常需要從 List 中添加或刪除元素的場合更為合適。
Set:
1.不允許重復(fù)對象
- 無序容器,你無法保證每個元素的存儲順序,TreeSet通過 Comparator 或者 Comparable 維護了一個排序順序。
- 只允許一個 null 元素
4.Set 接口最流行的幾個實現(xiàn)類是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 實現(xiàn)的 HashSet;TreeSet 還實現(xiàn)了 SortedSet 接口,因此 TreeSet 是一個根據(jù)其 compare() 和 compareTo() 的定義進行排序的有序容器。
Map:
1.Map不是collection的子接口或者實現(xiàn)類。Map是一個接口。
2.Map 的 每個 Entry 都持有兩個對象,也就是一個鍵一個值,Map 可能會持有相同的值對象但鍵對象必須是唯一的。
- TreeMap 也通過 Comparator 或者 Comparable 維護了一個排序順序。
- Map 里你可以擁有隨意個 null 值但最多只能有一個 null 鍵。
5.Map 接口最流行的幾個實現(xiàn)類是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用)
什么場景下使用List,Set,Map
如果你經(jīng)常會使用索引來對容器中的元素進行訪問,那么 List 是你的正確的選擇。如果你已經(jīng)知道索引了的話,那么 List 的實現(xiàn)類比如 ArrayList 可以提供更快速的訪問,如果經(jīng)常添加刪除元素的,那么肯定要選擇LinkedList。
如果你想容器中的元素能夠按照它們插入的次序進行有序存儲,那么還是 List,因為 List 是一個有序容器,它按照插入順序進行存儲。
如果你想保證插入元素的唯一性,也就是你不想有重復(fù)值的出現(xiàn),那么可以選擇一個 Set 的實現(xiàn)類,比如 HashSet、LinkedHashSet 或者 TreeSet。所有 Set 的實現(xiàn)類都遵循了統(tǒng)一約束比如唯一性,而且還提供了額外的特性比如 TreeSet 還是一個 SortedSet,所有存儲于 TreeSet 中的元素可以使用 Java 里的 Comparator 或者 Comparable 進行排序。LinkedHashSet 也按照元素的插入順序?qū)λ鼈冞M行存儲。
如果你以鍵和值的形式進行數(shù)據(jù)存儲那么 Map 是你正確的選擇。你可以根據(jù)你的后續(xù)需要從 Hashtable、HashMap、TreeMap 中進行選擇。
ArrayList和LinkedList區(qū)別:
1.ArrayList是實現(xiàn)了基于動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu)。
2.對于隨機訪問get和set,ArrayList覺得優(yōu)于LinkedList,因為LinkedList要移動指針。
3.對于新增和刪除操作add和remove,LinedList比較占優(yōu)勢,因為ArrayList要移動數(shù)據(jù)。
Vector和ArrayList 區(qū)別:
- Vector的方法都是同步的(Synchronized),是線程安全的(thread-safe),而ArrayList的方法不是,由于線程的同步必然要影響性能,因此,ArrayList的性能比Vector好。
2.當Vector或ArrayList中的元素超過它的初始大小時,Vector會將它的容量翻倍,而ArrayList只增加50%的大小,這樣,ArrayList就有利于節(jié)約內(nèi)存空間。
HashSet和TreeSet的區(qū)別:
1.TreeSet 是二叉樹實現(xiàn)的,Treeset中的數(shù)據(jù)是自動排好序的,不允許放入null值。
2.HashSet 是哈希表實現(xiàn)的,HashSet中的數(shù)據(jù)是無序的,可以放入null,但只能放入一個null,兩者中的值都不能重復(fù),就如數(shù)據(jù)庫中唯一約束。
3.HashSet要求放入的對象必須實現(xiàn)HashCode()方法,放入的對象,是以hashcode碼作為標識的,而具有相同內(nèi)容的 String對象,hashcode是一樣,所以放入的內(nèi)容不能重復(fù)。但是同一個類的對象可以放入不同的實例 。
HashSet與HashMap的區(qū)別:

TreeSet和TreeMap的關(guān)系
與HashSet完全類似,TreeSet里面絕大部分方法都市直接調(diào)用TreeMap方法來實現(xiàn)的。
相同點:
TreeMap和TreeSet都是非同步集合,因此他們不能在多線程之間共享,不過可以使用方法Collections.synchroinzedMap()來實現(xiàn)同步。
運行速度都要比Hash集合慢,他們內(nèi)部對元素的操作時間復(fù)雜度為O(logN),而HashMap/HashSet則為O(1)。
TreeMap和TreeSet都是有序的集合,也就是說他們存儲的值都是拍好序的。
不同點:
最主要的區(qū)別就是TreeSet和TreeMap分別實現(xiàn)Set和Map接口
TreeSet只存儲一個對象,而TreeMap存儲兩個對象Key和Value(僅僅key對象有序)
TreeSet中不能有重復(fù)對象,而TreeMap中value可以存在重復(fù)對象。
TreeMap的底層采用紅黑樹的實現(xiàn),完成數(shù)據(jù)有序的插入,排序。
HashMap和HashTable的區(qū)別:
HashMap是非線程安全的,Hashtable是線程安全的,所以Hashtable重量級一些,因為使用了synchronized關(guān)鍵字來保證線程安全。
HashMap允許key和value都為null,而Hashtable都不能為null。
Hashtable繼承自 JDK 1.0 的 Dictionary 虛擬類,而HashMap是 JDK 1.2 引進的 Map 接口的一個實現(xiàn)。
Hashtable和HashMap擴容的方法不一樣,Hashtable中數(shù)組默認大小11,擴容方式是 old*2+1。HashMap中數(shù)組的默認大小是16,而且一定是2的指數(shù),增加為原來的2倍。
兩者通過hash值散列到hash表的算法不一樣,Hashtable是古老的除留余數(shù)法,直接使用Object的hashcode,而后者是強制容量為2的冪,重新根據(jù)hashcode計算hash值,在使用hash和(hash表長度 – 1)進行與運算,也等價取膜,但更加高效,取得的位置更加分散,偶數(shù),奇數(shù)保證了都會分散到。前者就不能保證。
HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以當有其它線程改變了HashMap的結(jié)構(gòu)(增加或者移除元素),將會拋出ConcurrentModificationException,但迭代器本身的remove()方法移除元素則不會拋出ConcurrentModificationException異常