常用的集合類有一下幾種:
List結構的集合類:ArrayList類,LinkedList類,Vector類,Stack類
Map結構的集合類:HashMap類,Hashtable類
Set結構的集合類:HashSet類,TreeSet類
Queue結構的集合:Queue接口
HashMap和Hashtable的差別:
HashMap和Hashtable都是java的集合類,都可以用來存放java對象,這是他們的相同點
以下是他們的差別:
1.曆史原因:
Hashtable是基于陳舊的Dictionary類的,HashMap是java 1.2引進的Map接口的一個現實。
2.同步性:
Hashtable是同步的,這個類中的一些方法保證了Hashtable中的對象是線程安全的,而HashMap則是異步的,是以HashMap中的對象并不是線程安全的,因為同步的要求會影響執行的效率,是以如果你不需要線程安全的結合那麼使用HashMap是一個很好的選擇,這樣可以避免由于同步帶來的不必要的性能開銷,進而提高效率,我們一般所編寫的程式都是異步的,但如果是伺服器端的代碼除外。
3.值:
HashMap可以讓你将空值作為一個表的條目的key或value
Hashtable是不能放入空值(null)的
ArrayList和Vector的差別:
ArrayList與Vector都是java的集合類,都是用來存放java對象,這是他們的相同點,
差別:
1.同步性:
Vector是同步的,這個類的一些方法保證了Vector中的對象的線程安全的,而ArrayList則是異步的,是以ArrayList中的對象并不 是線程安全的,因為同步要求會影響執行的效率,是以你不需要線程安全的集合那麼使用ArrayList是一個很好的選擇,這樣可以避免由于同步帶來的不必 要的性能開銷。
2.資料增長:
從内部實作的機制來講,ArrayList和Vector都是使用數組(Array)來控制集合中的對象,當你向兩種類型中增加元素的時候,如果元素的數目超過了内部數組目前的長度他們都需要擴充内部數組的長度,Vector預設情況下自動增長原來一倍的數組長度,ArrayList是原來的50%,是以最後你獲得的這個集合所占的空間總是比你實際需要的要大,是以如果你要在集合中儲存大量的資料,那麼使用Vector有一些優勢,因為你可以通過設定集合的初始大小來避免不必要的資源開銷。
總結:
1)如果要求線程安全,使用Vector,Hashtable
2)如果不要求線程安全,使用ArrayList,LinkedList,HashMap
3)如果要求鍵值對,則使用HashMap,Hashtable
4)如果資料量很大,又要求線程安全考慮Vector
1.ArrayList: 元素單個,效率高,多用于查詢
2.Vector: 元素單個,線程安全,多用于查詢
3.LinkedList:元素單個,多用于插入和删除
4.HashMap: 元素成對,元素可為空
5.HashTable: 元素成對,線程安全,元素不可為空
ArrayList
底層是Object數組,是以ArrayList具有數組的查詢速度快的優點以及增删速度慢的缺點。
而在LinkedList的底層是一種雙向循環連結清單。在此連結清單上每一個資料節點都由三部分組成:前指針(指向前面的節點的位置),資料,後指針(指向後面的節點的位置)。最後一個節點的後指針指向第一個節點的前指針,形成一個循環。
雙向循環連結清單的查詢效率低但是增删效率高。
ArrayList和LinkedList在用法上沒有差別,但是在功能上還是有差別的。
LinkedList
經常用在增删操作較多而查詢操作很少的情況下:隊列和堆棧。
隊列:先進先出的資料結構。
棧:後進先出的資料結構。
注意:使用棧的時候一定不能提供方法讓不是最後一個元素的元素獲得出棧的機會。
Vector
(與ArrayList相似,差別是Vector是重量級的元件,使用使消耗的資源比較多。)
結論:在考慮并發的情況下用Vector(保證線程的安全)。
在不考慮并發的情況下用ArrayList(不能保證線程的安全)。
面試經驗(知識點):
java.util.stack(stack即為堆棧)的父類為Vector。可是stack的父類是最不應該為Vector的。因為Vector的底層是數組,且Vector有get方法(意味着它可能通路到并不屬于最後一個位置元素的其他元素,很不安全)。
對于堆棧和隊列隻能用push類和get類。
Stack類以後不要輕易使用。
實作棧一定要用LinkedList。
(在JAVA1.5中,collection有queue來實作隊列。)
Set-HashSet實作類:
周遊一個Set的方法隻有一個:疊代器(interator)。
HashSet中元素是無序的(這個無序指的是資料的添加順序和後來的排列順序不同),而且元素不可重複。
在Object中除了有finalize(),toString(),equals(),還有hashCode()。
HashSet底層用的也是數組。
當向數組中利用add(Object o)添加對象的時候,系統先找對象的hashCode:
int hc=o.hashCode(); 傳回的hashCode為整數值。
Int I=hc%n;(n為數組的長度),取得餘數後,利用餘數向數組中相應的位置添加資料,以n為6為例,如果I=0則放在數組a[0]位置,如果I=1,則 放在數組a[1]位置。如果equals()傳回的值為true,則說明資料重複。如果equals()傳回的值為false,則再找其他的位置進行比 較。這樣的機制就導緻兩個相同的對象有可能重複地添加到數組中,因為他們的hashCode不同。
如果我們能夠使兩個相同的對象具有相同hashcode,才能在equals()傳回為真。
在執行個體中,定義student對象時覆寫它的hashcode。
因為String類是自動覆寫的,是以當比較String類的對象的時候,就不會出現有兩個相同的string對象的情況。
現在,在大部分的JDK中,都已經要求覆寫了hashCode。
結論:如将自定義類用hashSet來添加對象,一定要覆寫hashcode()和equals(),覆寫的原則是保證當兩個對象hashcode傳回相同的整數,而且equals()傳回值為True。
如果偷懶,沒有設定equals(),就會造成傳回hashCode雖然結果相同,但在程式執行的過程中會多次地調用equals(),進而影響程式執行的效率。
我們要保證相同對象的傳回的hashCode一定相同,也要保證不相同的對象的hashCode盡可能不同(因為數組的邊界性,hashCode還是可能相同的)。
例子:
public int hashCode(){
return name.hashcode()+age;
}
這個例子保證了相同姓名和年齡的記錄傳回的hashCode是相同的。
使用hashSet的優點:
hashSet的底層是數組,其查詢效率非常高。而且在增加和删除的時候由于運用的hashCode的比較開确定添加元素的位置,是以不存在元素的偏移,是以效率也非常高。因為hashSet查詢和删除和增加元素的效率都非常高。
但是hashSet增删的高效率是通過花費大量的空間換來的:因為空間越大,取餘數相同的情況就越小。HashSet這種算法會建立許多無用的空間。
使用hashSet類時要注意,如果發生沖突,就會出現周遊整個數組的情況,這樣就使得效率非常的低。