2010年9月27日 星期一

HashMap, HashSet, HashTable 等等的 Hash Collection

Hashtable類
Hashtable繼承Map接口,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value
添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。
Hashtable通過initial capacity和load factor兩個參數調整性能。通常缺省的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。
使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是”one”,”two”,”three”:
Hashtable numbers = new Hashtable();
numbers.put(“one”, new Integer(1));
numbers.put(“two”, new Integer(2));
numbers.put(“three”, new Integer(3));
要取出一個數,比如2,用相應的key:
Integer n = (Integer)numbers.get(“two”);
System.out.println(“two = ” + n);
由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方 法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相 同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如 果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快哈希 表的操作。
如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時複寫equals方法和hashCode方法,而不要只寫其中一個。
Hashtable是同步的。

HashMap類
HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key。但是將HashMap視為Collection時(values()方法可返回Collection),其叠代子操作時間開銷和HashMap 的容量成比例。因此,如果叠代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。

WeakHashMap類
WeakHashMap是一種改進的HashMap,它對key實行“弱引用”,如果一個key不再被外部所引用,那麽該key可以被GC回收。



HashSet請參考對Set的描述

Set是一種不包含重複的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。
Set的構造函數有一個約束條件,傳入的Collection參數不能包含重複的元素。  
請註意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題。
兩個通用Set實現是HashSet 和TreeSet。要決定用哪一個,那是非常簡單明了的。 HashSet 要快得多 (對大多數操作是常數時間之於對數時間(constant time vs. log time)), 但不提供排序保證。如果你需要使用 SortedSet 中的操作,或者按順序叠代對你來說是重要的,那麽請使用 TreeSet。 否則,使用 HashSet。 在大多數時間都不使用 HashSet ,對你來說是個公平的賭博。

關於 HashSet,有一件事應該牢記,即就條目數和容量之和來講,叠代是線性的。因此,如果叠代性能很重要,那就應該慎重選擇一個適當的初始容量。容量選得 太大,既浪費空間,也浪費時間。 默認的初試容量是101, 一般來講,它比你所需要的要多。可以使用 int 構造函數來指定初始容量。要分配 HashSet 的初始容量為17:

Set s= new HashSet(17);

HashSets 另有一個稱作 裝載因數(load factor) 的"調整參數(tuning parameter)" 。如果你非常在乎你的 HashSet 的空間的使用,請閱讀 HashSet 文本以獲取詳細信息。否則,就使用默認值吧。如果你接受默認裝載因數,但你確實又想指定初始容量,那麽,選一個大約是你期望你的 Set 將增長到的容量的兩倍的數。如果你的猜測不著邊,它也可以增長,或只是浪費一點空間。但都沒有大問題。如果你知道有關正確尺寸的一個最佳值,用它吧;如果 不知道,那就使用一個舊的值,或使用一個偶數值。它真的不是非常重要。這些事情只能使 HashSet 稍稍變好一點點。

TreeSet 沒有調整參數。除 clone 之外,HashSet 和 TreeSet 都僅有那些由它們各自的接口所要求的操作 (Set 和 TreeSet),而沒有任何別的操作。



******************************* 我 是 分 隔 線 *******************************

http://www.pakzilla.com/2009/08/24/hashmap-vs-hashtable-vs-hashset/

Hashtable

Hashtable is basically a datastructure to retain values of key-value pair.

  • It didn’t allow null for both key and value. You will get NullPointerException if you add null value.
  • It is synchronized. So it comes with its cost. Only one thread can access in one time
Hashtable;
cityTable = new Hashtable();
cityTable.put(1, "Lahore");
cityTable.put(2, "Karachi");
cityTable.put(3, null); /* NullPointerEcxeption at runtime*/

System.out.println(cityTable.get(1));
System.out.println(cityTable.get(2));
System.out.println(cityTable.get(3));

HashMap

Like Hashtable it also accepts key value pair.

  • It allows null for both key and value
  • It is unsynchronized. So come up with better performance
HashMap productMap = new HashMap();
productMap.put(1, "Keys");
productMap.put(2, null);

HashSet

HashSet does not allow duplicate values. It provides add method rather put method. You also use its contain method to check whether the object is already available in HashSet. HashSet can be used where you want to maintain a unique list.

HashSet stateSet = new HashSet();
stateSet.add ("CA");
stateSet.add ("WI");
stateSet.add ("NY");

if (stateSet.contains("PB")) /* if CA, it will not add but shows following message*/
System.out.println("Already found");
else
stateSet.add("PB");

沒有留言:

張貼留言