整個Java集合框架圖以下所示。線比較多,但各個接口及實現類之間的關係仍是比較清楚的。算法
(1)長度區別。數組長度不可變,集合長度可變。數組
(2)內容區別。數組能夠存儲基本數據類型和對象引用,集合只能存儲對象引用。安全
(3)數組只能存儲同一類型的元素,集合能夠存儲不一樣類型的元素。數據結構
Java 集合框架主要包括兩種類型的容器,一種是集合(Collection),存儲一個元素集合,另外一種是圖(Map),存儲鍵/值對映射。多線程
繼承關係以下圖所示,經常使用的實現類有ArrayList,LinkedList,HashSet,LinkedHashSet。框架
Collection集合的方法以下圖所示:函數
Map保存的每項數據都是鍵值對(key-value),Map中的key是不可重複的,key用於標識集合裏的每項數據。性能
其中,HashMap和TreeMap是常常用到的實現類。ui
(1)List和Set的區別spa
此外,
List和Set都繼承自Collection接口,Map則不是 。
Set:檢索元素效率低下,刪除和插入效率高,插入和刪除不會引發元素位置改變。
List:和數組相似,List能夠動態增加,查找元素效率高,插入刪除元素效率低,由於會引發其餘元素位置改變。
(2)List
經常使用實現類:
(1)ArrayList:底層數據結構是數組,地址連續,查詢快,增刪慢,線程不安全,效率高,能夠存儲重複元素 。
(2)LinkedList 底層數據結構是鏈表,地址不連續,查詢慢,增刪快,線程不安全,效率高,能夠存儲重複元素 。
(3)Vector:底層數據結構是數組,查詢快,增刪慢,線程安全,效率低,能夠存儲重複元素 。
List適用場景分析:
當須要對數據進行屢次訪問的狀況下選用ArrayList,當須要對數據進行屢次增長刪除修改時採用LinkedList。
ArrayList和Vector都是用數組實現的,主要有這麼三個區別:
(1).Vector是多線程安全的,線程安全就是說多線程訪問同一代碼,不會產生不肯定的結果。而ArrayList不是,這個能夠從源碼中看出,Vector類中的方法不少有synchronized進行修飾,這樣就致使了Vector在效率上沒法與ArrayList相比;
(2)兩個都是採用的線性連續空間存儲元素,可是當空間不足的時候,兩個類的增長方式是不一樣。
*(3)*Vector能夠設置增加因子,而ArrayList不能夠。
*(4)*Vector是一種老的動態數組,是線程同步的,效率很低,通常不同意使用。
(3)Set
3.1 HashSet底層數據結構採用哈希表實現,元素無序且惟一,線程不安全,效率高,能夠存儲null元素,元素的惟一性是靠所存儲元素類型是否重寫hashCode()和equals()方法來保證的,若是沒有重寫這兩個方法,則沒法保證元素的惟一性。
具體實現惟一性的比較過程:存儲元素首先會使用hash()算法函數生成一個int類型hashCode散列值,而後已經的所存儲的元素的hashCode值比較,若是hashCode不相等,則所存儲的兩個對象必定不相等,此時存儲當前的新的hashCode值處的元素對象;若是hashCode相等,存儲元素的對象仍是不必定相等,此時會調用equals()方法判斷兩個對象的內容是否相等,若是內容相等,那麼就是同一個對象,無需存儲;若是比較的內容不相等,那麼就是不一樣的對象,就該存儲了,此時就要採用哈希的解決地址衝突算法,在當前hashCode值處相似一個新的鏈表, 在同一個hashCode值的後面存儲存儲不一樣的對象,這樣就保證了元素的惟一性。
Set的實現類的集合對象中不可以有重複元素,HashSet也同樣他是使用了一種標識來肯定元素的不重複,HashSet用一種算法來保證HashSet中的元素是不重複的, HashSet採用哈希算法,底層用數組存儲數據。默認初始化容量16,加載因子0.75。
Object類中的hashCode()的方法是全部子類都會繼承這個方法,這個方法會用Hash算法算出一個Hash(哈希)碼值返回,HashSet會用Hash碼值去和數組長度取模, 模(這個模就是對象要存放在數組中的位置)相同時纔會判斷數組中的元素和要加入的對象的內容是否相同,若是不一樣纔會添加進去。
Hash算法是一種散列算法。
Set hs=new HashSet();
hs.add(o);
|
o.hashCode();
|
o%當前總容量 (0–15)
|
| 不發生衝突
是否發生衝突—————–直接存放
|
| 發生衝突
| 假(不相等)
o1.equals(o2)——————-找一個空位添加
|
| 是(相等)
不添加
覆蓋hashCode()方法的原則:
一、必定要讓那些咱們認爲相同的對象返回相同的hashCode值
二、儘可能讓那些咱們認爲不一樣的對象返回不一樣的hashCode值,不然,就會增長衝突的機率。
三、儘可能的讓hashCode值散列開(兩值用異或運算可以使結果的範圍更廣)
HashSet 的實現比較簡單,相關HashSet的操做,基本上都是直接調用底層HashMap的相關方法來完成,咱們應該爲保存到HashSet中的對象覆蓋hashCode()和equals(),由於再將對象加入到HashSet中時,會首先調用hashCode方法計算出對象的hash值,接着根據此hash值調用HashMap中的hash方法,獲得的值& (length-1)獲得該對象在hashMap的transient Entry[] table中的保存位置的索引,接着找到數組中該索引位置保存的對象,並調用equals方法比較這兩個對象是否相等,若是相等則不添加,注意:因此要存入HashSet的集合對象中的自定義類必須覆蓋hashCode(),equals()兩個方法,才能保證集合中元素不重複。在覆蓋equals()和hashCode()方法時, 要使相同對象的hashCode()方法返回相同值,覆蓋equals()方法再判斷其內容。爲了保證效率,因此在覆蓋hashCode()方法時, 也要儘可能使不一樣對象儘可能返回不一樣的Hash碼值。
若是數組中的元素和要加入的對象的hashCode()返回了相同的Hash值(相同對象),纔會用equals()方法來判斷兩個對象的內容是否相同。
3.2 LinkedHashSet底層數據結構採用鏈表和哈希表共同實現,鏈表保證了元素的順序與存儲順序一致,哈希表保證了元素的惟一性。線程不安全,效率高。
3.3 TreeSet底層數據結構採用二叉樹來實現,元素惟一且已經排好序;惟一性一樣須要重寫hashCode和equals()方法,二叉樹結構保證了元素的有序性。根據構造方法不一樣,分爲天然排序(無參構造)和比較器排序(有參構造),天然排序要求元素必須實現Compareable接口,並重寫裏面的compareTo()方法,元素經過比較返回的int值來判斷排序序列,返回0說明兩個對象相同,不須要存儲;比較器排鬚要在TreeSet初始化是時候傳入一個實現Comparator接口的比較器對象,或者採用匿名內部類的方式new一個Comparator對象,重寫裏面的compare()方法。
set適用場景分析
HashSet是基於Hash算法實現的,其性能一般都優於TreeSet。爲快速查找而設計的Set,咱們一般都應該使用HashSet,在咱們須要排序的功能時,咱們才使用TreeSet。
Map 沒有繼承 Collection 接口, Map 提供 key 到 value 的映射,你能夠經過「鍵」查找「值」。一個 Map 中不能包含相同的 key ,每一個 key 只能映射一個 value 。 Map 接口提供 3 種集合的視圖, Map 的內容能夠被看成一組 key 集合,一組 value 集合,或者一組 key-value 映射。
(1)Map的主要方法
(2)HashMap和HashTable的比較
(2)TreeMap:
適用場景分析:
HashMap和HashTable:HashMap去掉了HashTable的contains方法,可是加上了containsValue()和containsKey()方法。
HashTable同步的,而HashMap是非同步的,效率上比HashTable要高。HashMap容許空鍵值,而HashTable不容許。
HashMap:適用於Map中插入、刪除和定位元素。
Treemap:適用於按天然順序或自定義順序遍歷鍵(key)。
5.線程安全集合類與非線程安全集合類 LinkedList、ArrayList、HashSet是非線程安全的,Vector是線程安全的;
HashMap是非線程安全的,HashTable是線程安全的;
StringBuilder是非線程安全的,StringBuffer是線程安全的。
參考書目及博客:略。