在Java?2的Collections框架中,主要包括兩個接口及其擴展和實現類:Collection接口和Map接口。兩者的區別在于前者存儲一組對象,后者則存儲一些關鍵字/值對。
public?interface?java.util.Map?{
????//Altering?Methods
??????public?Object?put(Object?key,?Object?value);????
??????public?Object?remove(Object?key);??????????????
??????public?void?putAll(java.util.Map);?????????????
??????public?void?clear();???
????//Querying?Methods
??????public?Object?get(Object?key);???????????
??????public?int?size();?????????????????????
??????public?boolean?isEmpty();??????????????????
??????public?boolean?containsKey(Object);??????????
??????public?boolean?containsValue(Object);??????????
??????public?boolean?equals(Object);?????????????????
????//Viewing?Methods
??????public?java.util.Set?keySet();??????????????????//Gets?keys
??????public?java.util.Collection?values();???????????//Gets?values
??????public?java.util.Set?entrySet();????????????????//Gets?mappings
??????public?static?interface?java.util.Map.Entry?{???//a?map-entry?(single?key/value?pair)
?????????public?Object?getKey();????????????????????//returns?current?entry?key
?????????public?Object?getValue();??????????????????//returns?current?entry?value
????????public?Object?setValue(Object?value);??????
??public?boolean?equals(Object);?????????????
??public?int?hashCode();?????????????????????????}
}
Map接口提供了方便易用的方法,通過這些方法可以查詢、查看、修改當前Map的內容。注意對于Map接口的keySet()方法返回一個Set,Set是Collection接口的一個擴展,包含不重復的一組對象。因為Map中的key是不可重復的,所以得到所有key的keySet()方法返回一個Set對象。Map接口本身還包含了一個Map.Entry接口,一個Map.Entry就是Map中的一個關鍵字/值對。Map接口中的entrySet()方法就返回了一個集合對象,其中每一個元素都實現了Map.Entry接口。Map接口的get(Object?key),put(Object?key,Object?value),和remove(Object?key)方法都有同一個問題。他們的返回類型都是Object,當返回null時,可以猜測為調用那個方法前那個key不存在。但是只有在null不允許作為Map的值時可以這樣猜測。所有Map接口的通用實現都允許null作為key或者value,這就說當返回一個null值,就可以意味著很多事情。只是因為通用實現允許null值,你不能下那個映射有null值的結論。如果你確知沒有null值,那返回null值就意味著調用那個方法前,映射里并沒有那個鍵。否則,你必須調用containsKey(Object?key)來看看那個Key是否存在。
java.util.Hashtable實現了Map接口,在Hashtable中使用key對象的hashCode()作為對應的對象的相對存儲地址,以便實現根據關鍵字快速查找對象的功能。所以只有一個實現了hashCode()和equals()方法的對象才可作為Hashtable的key。null值不能作為關鍵字或值。
public?class?java.util.Hashtable?extends?Dictionary?implements?Cloneable,?Map,?Serializable?{
?????//Hashtable?constructors
?????//construct?a?default?Hashtable?with?default?capacity?and?load?of?0.75
?????public?Hashtable();?????????????????????
?????//construct?a?Hashtable?with?passed?capacity?and?default?load?of?0.75?
?????public?Hashtable?(int?initialCapacity);?
?????//construct?Hashtable?with?passed?capacity?and?load?
?????public?Hashtable(int?initialCapacity,?float?load);?
?????//construct?Hashtable?with?passed?mapping?
?????public?Hashtable(Map);??????????????????
?????
?????//Hashtable?specific?methods
?????//checks?if?Object?is?in?Hashtable?
?????public?boolean?contains(Object);????????
?????//returns?Enumeration?of?elements?in?Hashtable?
?????public?Enumeration?elements();??????????
?????//returns?Enumeration?of?keys?in?hashtable
?????public?Enumeration?keys();??????????????
?????//creates?shallow?copy?of?Hashtable(structure?copied,?but?not?key/values)
?????public?Object?clone();??????????????????
?????//prints?out?key/value?pairs?of?Hashtable?elements
?????public?String?toString();???????????????
?????//reorganizes?all?elements?in?Hashtable,?and?increases?Hashtable?capacity?
?????protected?void?rehash();????????????????
?????
?????//get?Value?from?passed?in?key?
?????public?Object?get(Object);??????????????
?????//insert?key/value?pair
?????public?Object?put(Object?key,?Object?value);??????
}
Hashtable是Java?2集合框架推出之前的一個老的工具類,在新的Java?2集合框架下,已經被HashMap取代。Hashtable和HashMap的區別主要是前者是同步的,后者是快速失敗機制保證不會出現多線程并發錯誤(Fast-Fail)。在初始化一個Hashtable時,可以指定兩個參數:初始容量、負荷,這兩個參數強烈的影響著Hashtable的性能。容量是指對象的個數,負荷是指散列表中的實際存儲的對象個數和容量的比率。如果初始容量太小,那么Hashtable需要不斷的擴容并rehash(),而這是很耗時的;如果初始容量太大,又會造成空間的浪費。負荷則相反,負荷太小會造成空間浪費,負荷太大又會耗時(因為這會造成較多的關鍵字的散列碼重復,Hashtable使用一個鏈接表來存儲這些重復散列碼的對象)。容量的缺省值是11,負荷的缺省值是0.75,一般情況下你都可以使用缺省值來生成一個Hashtable。另外,在Hashtable中的大部分的方法都是同步的。
HashMap基本實現了Map接口的全部方法。方法的簽名大家看上面的Map接口。這兒主要說說幾個Map接口中的方法。
按照集合框架的實現,哈希表是單鏈表作為元素的數組,有著同樣索引值的兩個或更多入口被一起鏈結到單鏈表中。哈希表聲明如下:
????private?Entry[]?table;
組件類型Entry是Map.Entry接口的實現,Map.Entry聲明于Map接口內。下邊是Map.Entry接口的簡化實現:
????private?static?class?Entry?implements?Map.Entry{
????????int?hashCode;
????????Object?key;
????????Object?value;
????????Entry?next;
????????Entry(int?hashCode,Object?key,Object?value,Entry?next){
????????????This.hashCode=hashCode;
????????????This.key=key;
????????????This.value=value;
????????????This.next=next;
}
public?Object?getKey(){
????return?key;
}
public?Object?getValue(){
????return?value;
}
public?Object?setValue(Object?value){
????Object?oldValue=this.value;
????This.value=value;
????Return?oldValue;
}
}
SortedMap是Map接口的子接口,SortedMap的標準實現是TreeMap,實現了一個排序的Map。這兒不再做說明。本站翻譯的《Java?規則》(Java?Rules)中對Java2的集合框架有深入的研究。本文限于篇幅,只及皮毛。有興趣的朋友,請參考Java2源碼中的集合實現代碼和API?doc。
public?interface?java.util.Map?{
????//Altering?Methods
??????public?Object?put(Object?key,?Object?value);????
??????public?Object?remove(Object?key);??????????????
??????public?void?putAll(java.util.Map);?????????????
??????public?void?clear();???
????//Querying?Methods
??????public?Object?get(Object?key);???????????
??????public?int?size();?????????????????????
??????public?boolean?isEmpty();??????????????????
??????public?boolean?containsKey(Object);??????????
??????public?boolean?containsValue(Object);??????????
??????public?boolean?equals(Object);?????????????????
????//Viewing?Methods
??????public?java.util.Set?keySet();??????????????????//Gets?keys
??????public?java.util.Collection?values();???????????//Gets?values
??????public?java.util.Set?entrySet();????????????????//Gets?mappings
??????public?static?interface?java.util.Map.Entry?{???//a?map-entry?(single?key/value?pair)
?????????public?Object?getKey();????????????????????//returns?current?entry?key
?????????public?Object?getValue();??????????????????//returns?current?entry?value
????????public?Object?setValue(Object?value);??????
??public?boolean?equals(Object);?????????????
??public?int?hashCode();?????????????????????????}
}
Map接口提供了方便易用的方法,通過這些方法可以查詢、查看、修改當前Map的內容。注意對于Map接口的keySet()方法返回一個Set,Set是Collection接口的一個擴展,包含不重復的一組對象。因為Map中的key是不可重復的,所以得到所有key的keySet()方法返回一個Set對象。Map接口本身還包含了一個Map.Entry接口,一個Map.Entry就是Map中的一個關鍵字/值對。Map接口中的entrySet()方法就返回了一個集合對象,其中每一個元素都實現了Map.Entry接口。Map接口的get(Object?key),put(Object?key,Object?value),和remove(Object?key)方法都有同一個問題。他們的返回類型都是Object,當返回null時,可以猜測為調用那個方法前那個key不存在。但是只有在null不允許作為Map的值時可以這樣猜測。所有Map接口的通用實現都允許null作為key或者value,這就說當返回一個null值,就可以意味著很多事情。只是因為通用實現允許null值,你不能下那個映射有null值的結論。如果你確知沒有null值,那返回null值就意味著調用那個方法前,映射里并沒有那個鍵。否則,你必須調用containsKey(Object?key)來看看那個Key是否存在。
Hashtable
java.util.Hashtable實現了Map接口,在Hashtable中使用key對象的hashCode()作為對應的對象的相對存儲地址,以便實現根據關鍵字快速查找對象的功能。所以只有一個實現了hashCode()和equals()方法的對象才可作為Hashtable的key。null值不能作為關鍵字或值。
public?class?java.util.Hashtable?extends?Dictionary?implements?Cloneable,?Map,?Serializable?{
?????//Hashtable?constructors
?????//construct?a?default?Hashtable?with?default?capacity?and?load?of?0.75
?????public?Hashtable();?????????????????????
?????//construct?a?Hashtable?with?passed?capacity?and?default?load?of?0.75?
?????public?Hashtable?(int?initialCapacity);?
?????//construct?Hashtable?with?passed?capacity?and?load?
?????public?Hashtable(int?initialCapacity,?float?load);?
?????//construct?Hashtable?with?passed?mapping?
?????public?Hashtable(Map);??????????????????
?????
?????//Hashtable?specific?methods
?????//checks?if?Object?is?in?Hashtable?
?????public?boolean?contains(Object);????????
?????//returns?Enumeration?of?elements?in?Hashtable?
?????public?Enumeration?elements();??????????
?????//returns?Enumeration?of?keys?in?hashtable
?????public?Enumeration?keys();??????????????
?????//creates?shallow?copy?of?Hashtable(structure?copied,?but?not?key/values)
?????public?Object?clone();??????????????????
?????//prints?out?key/value?pairs?of?Hashtable?elements
?????public?String?toString();???????????????
?????//reorganizes?all?elements?in?Hashtable,?and?increases?Hashtable?capacity?
?????protected?void?rehash();????????????????
?????
?????//get?Value?from?passed?in?key?
?????public?Object?get(Object);??????????????
?????//insert?key/value?pair
?????public?Object?put(Object?key,?Object?value);??????
}
Hashtable是Java?2集合框架推出之前的一個老的工具類,在新的Java?2集合框架下,已經被HashMap取代。Hashtable和HashMap的區別主要是前者是同步的,后者是快速失敗機制保證不會出現多線程并發錯誤(Fast-Fail)。在初始化一個Hashtable時,可以指定兩個參數:初始容量、負荷,這兩個參數強烈的影響著Hashtable的性能。容量是指對象的個數,負荷是指散列表中的實際存儲的對象個數和容量的比率。如果初始容量太小,那么Hashtable需要不斷的擴容并rehash(),而這是很耗時的;如果初始容量太大,又會造成空間的浪費。負荷則相反,負荷太小會造成空間浪費,負荷太大又會耗時(因為這會造成較多的關鍵字的散列碼重復,Hashtable使用一個鏈接表來存儲這些重復散列碼的對象)。容量的缺省值是11,負荷的缺省值是0.75,一般情況下你都可以使用缺省值來生成一個Hashtable。另外,在Hashtable中的大部分的方法都是同步的。
HashMap
HashMap基本實現了Map接口的全部方法。方法的簽名大家看上面的Map接口。這兒主要說說幾個Map接口中的方法。
按照集合框架的實現,哈希表是單鏈表作為元素的數組,有著同樣索引值的兩個或更多入口被一起鏈結到單鏈表中。哈希表聲明如下:
????private?Entry[]?table;
組件類型Entry是Map.Entry接口的實現,Map.Entry聲明于Map接口內。下邊是Map.Entry接口的簡化實現:
????private?static?class?Entry?implements?Map.Entry{
????????int?hashCode;
????????Object?key;
????????Object?value;
????????Entry?next;
????????Entry(int?hashCode,Object?key,Object?value,Entry?next){
????????????This.hashCode=hashCode;
????????????This.key=key;
????????????This.value=value;
????????????This.next=next;
}
public?Object?getKey(){
????return?key;
}
public?Object?getValue(){
????return?value;
}
public?Object?setValue(Object?value){
????Object?oldValue=this.value;
????This.value=value;
????Return?oldValue;
}
}
SortedMap是Map接口的子接口,SortedMap的標準實現是TreeMap,實現了一個排序的Map。這兒不再做說明。本站翻譯的《Java?規則》(Java?Rules)中對Java2的集合框架有深入的研究。本文限于篇幅,只及皮毛。有興趣的朋友,請參考Java2源碼中的集合實現代碼和API?doc。