在Java?2的Collections框架中,主要包括兩個(gè)接口及其擴(kuò)展和實(shí)現(xiàn)類:Collection接口和Map接口。兩者的區(qū)別在于前者存儲(chǔ)一組對(duì)象,后者則存儲(chǔ)一些關(guān)鍵字/值對(duì)。
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接口提供了方便易用的方法,通過這些方法可以查詢、查看、修改當(dāng)前Map的內(nèi)容。注意對(duì)于Map接口的keySet()方法返回一個(gè)Set,Set是Collection接口的一個(gè)擴(kuò)展,包含不重復(fù)的一組對(duì)象。因?yàn)镸ap中的key是不可重復(fù)的,所以得到所有key的keySet()方法返回一個(gè)Set對(duì)象。Map接口本身還包含了一個(gè)Map.Entry接口,一個(gè)Map.Entry就是Map中的一個(gè)關(guān)鍵字/值對(duì)。Map接口中的entrySet()方法就返回了一個(gè)集合對(duì)象,其中每一個(gè)元素都實(shí)現(xiàn)了Map.Entry接口。Map接口的get(Object?key),put(Object?key,Object?value),和remove(Object?key)方法都有同一個(gè)問題。他們的返回類型都是Object,當(dāng)返回null時(shí),可以猜測(cè)為調(diào)用那個(gè)方法前那個(gè)key不存在。但是只有在null不允許作為Map的值時(shí)可以這樣猜測(cè)。所有Map接口的通用實(shí)現(xiàn)都允許null作為key或者value,這就說當(dāng)返回一個(gè)null值,就可以意味著很多事情。只是因?yàn)橥ㄓ脤?shí)現(xiàn)允許null值,你不能下那個(gè)映射有null值的結(jié)論。如果你確知沒有null值,那返回null值就意味著調(diào)用那個(gè)方法前,映射里并沒有那個(gè)鍵。否則,你必須調(diào)用containsKey(Object?key)來看看那個(gè)Key是否存在。
java.util.Hashtable實(shí)現(xiàn)了Map接口,在Hashtable中使用key對(duì)象的hashCode()作為對(duì)應(yīng)的對(duì)象的相對(duì)存儲(chǔ)地址,以便實(shí)現(xiàn)根據(jù)關(guān)鍵字快速查找對(duì)象的功能。所以只有一個(gè)實(shí)現(xiàn)了hashCode()和equals()方法的對(duì)象才可作為Hashtable的key。null值不能作為關(guān)鍵字或值。
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集合框架推出之前的一個(gè)老的工具類,在新的Java?2集合框架下,已經(jīng)被HashMap取代。Hashtable和HashMap的區(qū)別主要是前者是同步的,后者是快速失敗機(jī)制保證不會(huì)出現(xiàn)多線程并發(fā)錯(cuò)誤(Fast-Fail)。在初始化一個(gè)Hashtable時(shí),可以指定兩個(gè)參數(shù):初始容量、負(fù)荷,這兩個(gè)參數(shù)強(qiáng)烈的影響著Hashtable的性能。容量是指對(duì)象的個(gè)數(shù),負(fù)荷是指散列表中的實(shí)際存儲(chǔ)的對(duì)象個(gè)數(shù)和容量的比率。如果初始容量太小,那么Hashtable需要不斷的擴(kuò)容并rehash(),而這是很耗時(shí)的;如果初始容量太大,又會(huì)造成空間的浪費(fèi)。負(fù)荷則相反,負(fù)荷太小會(huì)造成空間浪費(fèi),負(fù)荷太大又會(huì)耗時(shí)(因?yàn)檫@會(huì)造成較多的關(guān)鍵字的散列碼重復(fù),Hashtable使用一個(gè)鏈接表來存儲(chǔ)這些重復(fù)散列碼的對(duì)象)。容量的缺省值是11,負(fù)荷的缺省值是0.75,一般情況下你都可以使用缺省值來生成一個(gè)Hashtable。另外,在Hashtable中的大部分的方法都是同步的。
HashMap基本實(shí)現(xiàn)了Map接口的全部方法。方法的簽名大家看上面的Map接口。這兒主要說說幾個(gè)Map接口中的方法。
按照集合框架的實(shí)現(xiàn),哈希表是單鏈表作為元素的數(shù)組,有著同樣索引值的兩個(gè)或更多入口被一起鏈結(jié)到單鏈表中。哈希表聲明如下:
????private?Entry[]?table;
組件類型Entry是Map.Entry接口的實(shí)現(xiàn),Map.Entry聲明于Map接口內(nèi)。下邊是Map.Entry接口的簡化實(shí)現(xiàn):
????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的標(biāo)準(zhǔn)實(shí)現(xiàn)是TreeMap,實(shí)現(xiàn)了一個(gè)排序的Map。這兒不再做說明。本站翻譯的《Java?規(guī)則》(Java?Rules)中對(duì)Java2的集合框架有深入的研究。本文限于篇幅,只及皮毛。有興趣的朋友,請(qǐng)參考Java2源碼中的集合實(shí)現(xiàn)代碼和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接口提供了方便易用的方法,通過這些方法可以查詢、查看、修改當(dāng)前Map的內(nèi)容。注意對(duì)于Map接口的keySet()方法返回一個(gè)Set,Set是Collection接口的一個(gè)擴(kuò)展,包含不重復(fù)的一組對(duì)象。因?yàn)镸ap中的key是不可重復(fù)的,所以得到所有key的keySet()方法返回一個(gè)Set對(duì)象。Map接口本身還包含了一個(gè)Map.Entry接口,一個(gè)Map.Entry就是Map中的一個(gè)關(guān)鍵字/值對(duì)。Map接口中的entrySet()方法就返回了一個(gè)集合對(duì)象,其中每一個(gè)元素都實(shí)現(xiàn)了Map.Entry接口。Map接口的get(Object?key),put(Object?key,Object?value),和remove(Object?key)方法都有同一個(gè)問題。他們的返回類型都是Object,當(dāng)返回null時(shí),可以猜測(cè)為調(diào)用那個(gè)方法前那個(gè)key不存在。但是只有在null不允許作為Map的值時(shí)可以這樣猜測(cè)。所有Map接口的通用實(shí)現(xiàn)都允許null作為key或者value,這就說當(dāng)返回一個(gè)null值,就可以意味著很多事情。只是因?yàn)橥ㄓ脤?shí)現(xiàn)允許null值,你不能下那個(gè)映射有null值的結(jié)論。如果你確知沒有null值,那返回null值就意味著調(diào)用那個(gè)方法前,映射里并沒有那個(gè)鍵。否則,你必須調(diào)用containsKey(Object?key)來看看那個(gè)Key是否存在。
Hashtable
java.util.Hashtable實(shí)現(xiàn)了Map接口,在Hashtable中使用key對(duì)象的hashCode()作為對(duì)應(yīng)的對(duì)象的相對(duì)存儲(chǔ)地址,以便實(shí)現(xiàn)根據(jù)關(guān)鍵字快速查找對(duì)象的功能。所以只有一個(gè)實(shí)現(xiàn)了hashCode()和equals()方法的對(duì)象才可作為Hashtable的key。null值不能作為關(guān)鍵字或值。
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集合框架推出之前的一個(gè)老的工具類,在新的Java?2集合框架下,已經(jīng)被HashMap取代。Hashtable和HashMap的區(qū)別主要是前者是同步的,后者是快速失敗機(jī)制保證不會(huì)出現(xiàn)多線程并發(fā)錯(cuò)誤(Fast-Fail)。在初始化一個(gè)Hashtable時(shí),可以指定兩個(gè)參數(shù):初始容量、負(fù)荷,這兩個(gè)參數(shù)強(qiáng)烈的影響著Hashtable的性能。容量是指對(duì)象的個(gè)數(shù),負(fù)荷是指散列表中的實(shí)際存儲(chǔ)的對(duì)象個(gè)數(shù)和容量的比率。如果初始容量太小,那么Hashtable需要不斷的擴(kuò)容并rehash(),而這是很耗時(shí)的;如果初始容量太大,又會(huì)造成空間的浪費(fèi)。負(fù)荷則相反,負(fù)荷太小會(huì)造成空間浪費(fèi),負(fù)荷太大又會(huì)耗時(shí)(因?yàn)檫@會(huì)造成較多的關(guān)鍵字的散列碼重復(fù),Hashtable使用一個(gè)鏈接表來存儲(chǔ)這些重復(fù)散列碼的對(duì)象)。容量的缺省值是11,負(fù)荷的缺省值是0.75,一般情況下你都可以使用缺省值來生成一個(gè)Hashtable。另外,在Hashtable中的大部分的方法都是同步的。
HashMap
HashMap基本實(shí)現(xiàn)了Map接口的全部方法。方法的簽名大家看上面的Map接口。這兒主要說說幾個(gè)Map接口中的方法。
按照集合框架的實(shí)現(xiàn),哈希表是單鏈表作為元素的數(shù)組,有著同樣索引值的兩個(gè)或更多入口被一起鏈結(jié)到單鏈表中。哈希表聲明如下:
????private?Entry[]?table;
組件類型Entry是Map.Entry接口的實(shí)現(xiàn),Map.Entry聲明于Map接口內(nèi)。下邊是Map.Entry接口的簡化實(shí)現(xiàn):
????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的標(biāo)準(zhǔn)實(shí)現(xiàn)是TreeMap,實(shí)現(xiàn)了一個(gè)排序的Map。這兒不再做說明。本站翻譯的《Java?規(guī)則》(Java?Rules)中對(duì)Java2的集合框架有深入的研究。本文限于篇幅,只及皮毛。有興趣的朋友,請(qǐng)參考Java2源碼中的集合實(shí)現(xiàn)代碼和API?doc。