Tim家菜︰Java Collection API炒Mathematical Concept
首先寫一個簡單的 JavaBean Object,即要有 getter及 setter的,然後 implement Comparable(順便把toString()及equals()也override一下)︰
class Obj implements Comparable {
private int a;
private int b;
public Obj(int a, int b) { this.setA(a); this.setB(b); }
public int getA() { return a; }
public void setA(int a) { this.a = a; }
public int getB() { return b; }
public void setB(int b) { this.b = b; }
public int compareTo(Object o) { Obj obj = (Obj) o; return this.getA() + this.getB() - obj.getA() - obj.getB(); }
public String toString() { return this.getA() + "-" + this.getB(); }
public boolean equals(Object o) { return this.compareTo(o) == 0;}
}
嗯,以上是很差的Code Formatting,不過在這裏很難做出漂亮的Code Format,緊記別參考。
然後預備一個TreeSet去add幾個Obj︰
Obj obj1 = new Obj(0, 1);
Obj obj2 = new Obj(1, 2);
Obj obj3 = new Obj(2, 3);
SortedSet<Obj> set = new TreeSet();
set.add(obj1);
set.add(obj2);
set.add(obj3);
System.out.println(set);
Output將是︰[0-1, 1-2, 2-3]
來搞事了,簡單的加入這一句︰
obj1.setA(10);
再看看Output︰[10-1, 1-2, 2-3]
很有問題,對不對? obj1 明明比 obj2 跟 obj3 大,卻仍排在第一位。再看看吧︰
System.out.println(obj1.compareTo(obj2));
System.out.println(obj1.compareTo(obj3));
Output是8跟6,亦即 obj1 比 obj2 及 obj3 還要大,也就是說這個SortedSet其實並非Sorted,很不可靠。
Obj obj4 = new Obj(10, 1);
set.add(obj4);
System.out.println(set);
Output是[10-1, 1-2, 2-3, 10-1],更離譜了,看清楚,這個是Set,對不對?我們都知道在Set當中沒有一個element與另一個element相等的。然而明顯的這個set當中有兩個相同的element。不信的話把四個element都抽出來看看,obj1.equals(obj4)是true的。
其實很簡單,這是Java Collection API的implementation問題,要解決不難,有空再討論。
只是,這裏值得我們考慮的問題是,原來SortedSet可以不是Sorted,甚至根本不是Set!
試想,基於Seperation of Concern的Concept,假如與你合作的Team Member發神經,明明給你一個SortedSet,結果只給了你一個Collection,而你還以為這是SortedSet,真可謂死得人多!舉個例吧︰
public SortedSet<Data> getSortedData();
當你Team Member給你這樣的一個Prototype的時候,很正常的你會拿去直接用吧?謹慎一點的人會看看Implementation,可是這個例子中其實大家是很難看出在哪裏的Implementation是有問題的,你頂多也只會看看return的SortedSet是怎樣access的,斷不會把每一個element都拿出來trace一下吧,沒完沒了,倒不如自己寫好了。
也許自己寫一個method檢查一下還來得方便。但難道要每次都檢查一次嗎?不便評論,自行決定吧。(個人來說是不贊成的…)個人意見,與其在己方做多幾重功夫,倒不如做多一些教育工作︰別胡亂改變Collection裏的Object的fields。
不過在這之前,恐怕又要做另一項教育工作︰Collection裝的是Object reference,不是Object本體。也就是說,哪管你放進去拿出來,你搞的仍然是那個Object。
很簡單的Object-Oriented Reference Concept,大學一定有教。可惜……
Sample Code在這裏。大家可以自己試試看,也不止SortedSet的,還有HashSet、HashMap、SortedMap之類也有同類型的情況。