From Gossip@Openhome

Java Gossip: TreeSet

TreeSet實作Set介面與SortedSet介面,提供相關的方法讓您有序的取出對應位置的物件,像是 first()、last()等方法,TreeSet是J2SE中唯一實作SortedSet介面的類別,它使用紅黑樹結構來對加入的物件進行排序。

看個簡單的例子:

  • TreeSetDemo.java
package onlyfun.caterpillar;

import java.util.*;

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

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

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

System.out.println();
}
}

由於加入的是String物件,執行結果會自動依字典順序進行排序的動作:
caterpillar justin momor

依字典順序排序String物件是TreeSet預設的,如果您對物件有自己的一套排序順序,您要實作一個 Comparator 物件,您要實作compare()方法,它必須傳回整數值,如果物件順序相同則傳回0,傳回正整數表示compare()方法的第一個物件大於第二個物件,反之則傳回負整數。

舉個實際的例子,假設您想要改變TreeSet依字典順序排列加入的物件為相反的順序:

  • CustomComparator.java
package onlyfun.caterpillar;

import java.util.Comparator;

public class CustomComparator<T> implements Comparator<T> {
    public int compare(T o1, T o2) {
        if (((T) o1).equals(o2))
            return 0;
        return ((Comparable<T>) o1).compareTo((T) o2) * -1;
    }
}

在自訂的Comparator中,如果兩個物件的順序相同會傳回0,這在TreeSet中表示兩個物件是同一個物件,TreeSet要求傳入的物件必須實 作java.lang.Comparable介面,範例中只是簡單的將原來compareTo()傳回的值乘以負一,如此在TreeSet中就可以簡單的 讓排列順序相反。

在建構TreeSet實例時一併指定自訂的Comparator,例如:

  • TreeSetDemo2.java
package onlyfun.caterpillar;
 
import java.util.*;
 
public class TreeSetDemo2 {
    public static void main(String[] args) {
        // 自訂Comparator
        Comparator<String> comparator =
                      new CustomComparator<String>();
        Set<String> set =
                      new TreeSet<String>(comparator);
       
        set.add("justin");
        set.add("caterpillar");
        set.add("momor");
       
        // 使用 enhanced for loop 顯示物件
        for(String name : set) {
            System.out.print(name + " ");
        }
        System.out.println();
    }
}

執行的結果是相反的:
momor justin caterpillar