public HashSet() {
map = new HashMap<E,Object>();
}
public boolean add(E o) {
return map.put(o, PRESENT)==null;
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
public boolean contains(Object o) {
return map.containsKey(o);
}
從代碼可見,HashSet在底層借用HashMap,使用一個Object類型的啞元值作為HashSet中元素在底層HashMap存儲中的映射值.它抓住了HashMap的鍵不允許重復的特性.對于add()中調用底層映射的put(),將欲添加的元素和一個PRESENT啞元值放入底層map.如果底層Map返回null,說明原來的集合中并不存在該鍵.對于Map接口的put()返回null時有兩種解釋,一是原來的Map中不包含該鍵;另一種可能是原來的Map中已經存儲了該健,但該鍵映射到null.而在HashSet中的add()和remove()等中的返回null只有一種解釋,即原來的集合不包含該元素.這是因為HashSet的底層的映射中存儲的都是一個名為PRESENT的Object類型的對象,不可能是null.
2.2 TreeSet
Set接口有一個子接口:SortedSet,提供了集合元素的順序存儲,其中元素保持升序排列.為了在加入一個元素到SortedSet實現時能對這些元素排序,元素類型必須實現Comarable接口,或者建立SortedSet時使用Comparator.否則程序在運行時將拋出ClassCastException.
3.使用Set的注意事項
如果Set中存儲了可變對象,當這些對象出現重復元素,從而從根本上違反了Set的約定,Set的行為也變得不確定.所以,在Set中存儲可變對象時,一定要十分小心.同樣,對于Map中的key也一樣,因為Map中的key也是不允許重復的.
//DupEleSet.java
class DupEleSet{
public static void main(String [] args)
{
Calendar cld=new Calendar.getInstance();
cld.set(2003,0,1);
Date d1 = cld.getTime();
cld.set(2005,10,2);
Date d2 = cld.getTime();
Set s = new HashSet();
s.add(d1);
s.add(d2);
System.out.println("before modify:"+s);
d1.setTime(d2.getTime());
System.out.println("after modified:"+s);
}
}
上面的程序輸出:
before modify:[Wed Jan 01 21:54:19 cst 2003,Thu Nov 02 21:54:19 cst 2000]
after modifyied:[Wed Jan 01 21:54:19 cst 2000,Thu Nov 02 21:54:19 cst 2000]