1. 程式人生 > >Java五個最常用的集合類之間的區別和聯絡

Java五個最常用的集合類之間的區別和聯絡

常用的集合類有一下幾種:

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類時要注意,如果發生衝突,就會出現遍歷整個陣列的情況,這樣就使得效率非常的低。