From Gossip@Openhome

Java Gossip: HashSet

HashSet實作Set介面,Set介面繼承Collection介面,Set容器中的物件都是唯一的,加入 Set容器中的物件都必須重新定義equals()方法,作為唯一性的識別,Set容器有自己的一套排序規則。

HashSet的排序規則是利用Hash Table,所以加入HashSet容器的物件還必須重新定義hashCode()方法,利用Hash的方式,可以讓您快速的找到容器中的物件,在比較兩個加入Set容器中的物件是否相同時,會先比較hashCode()方法傳回的值是否相同,如果相同,則再使用equals()方法比較,如果兩者都相同,則視為相同的物件。

事實上,在撰寫新的類別時,最好總是重新定義equals()與hashCode()方法,以符合Java的設計規範,您可以參考 Object 類別 中的介紹瞭解如何重新定義equals()與hashCode()。

來看一個例子:

  • HashSetDemo.java
package onlyfun.caterpillar;

import java.util.*;

public class HashSetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();

set.add("caterpillar");
set.add("justin");
set.add("momor");
set.add("justin");

Iterator iterator = set.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}

System.out.println();
}
}

執行結果:
 momor justin caterpillar

如上所示的,即使重覆加入了"justin"字串,HashSet中仍只有一個"justin"字串物件,另一個要注意的是,选代所有的值時,其順序 與您加入的順序是不一樣的,选代所有值時的順序是HashSet排序過後的順序。

LinkedHashSet是HashSet的子類,它在內部實作使用Hash Code進行排序,然而允許您在列舉時行為像是LinkedList,簡單的改寫上面的程式即可瞭解:

  • LinkedHashSetDemo.java
package onlyfun.caterpillar;

import java.util.*;

public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<String>();

set.add("caterpillar");
set.add("justin");
set.add("momor");
set.add("justin");

Iterator iterator = set.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}

System.out.println();
}
}

執行結果:
 caterpillar justin momor

可以在執行結果中看到的,选代時的順序正是您加入值的順序。