Map<String, ?>只能是只讀模式,不能增加,因為增加的時候不知道該寫入什么型別的值;
Map<String, Object>可以讀和寫,只要是所有Object類的子類都可以,
常用的集合類有一下幾種:
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類時要注意,如果發生沖突,就會出現遍歷整個陣列的情況,這樣就使得效率非常的低,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/382174.html
標籤:Java
