TreeSet的底層是TreeMap的keySet(),而TreeMap是基於紅黑樹實現的,紅黑樹是一種平衡二叉查找樹,它能保證任何一個節點的左右子樹的高度差不會超過較矮的那棵的一倍。
TreeMap是按key排序的,所以TreeSet中的元素也是排好序的。顯然元素在插入TreeSet時compareTo()方法要被調用,所以TreeSet中的元素要實現Comparable接口。TreeSet作為一種Set,它不允許出現重復元素。TreeSet是用compareTo()來判斷重復元素的,而非equals(),看下面代碼。
1 import java.util.TreeSet; 2 3 import org.junit.Test; 4 5 public class TestTreeSet { 6 7 class Combine implements Comparable<Combine> { 8 private int p1; 9 private int p2; 10 11 public Combine(int p1, int p2) { 12 this.p1 = p1; 13 this.p2 = p2; 14 } 15 16 @Override 17 public int hashCode() { 18 return p1 * 31 + p2; 19 } 20 21 @Override 22 public boolean equals(Object obj) { 23 System.out.print("whether equal " + this + " and " + obj); 24 boolean rect = false; 25 if (obj instanceof Combine) { 26 System.out.println("whether equal " + this + " and " + obj); 27 Combine other = (Combine) obj; 28 rect = (this.p1 == other.getP1() && this.p2 == other.getP2()); 29 } 30 System.out.println(": " + rect); 31 return rect; 32 } 33 34 @Override 35 public int compareTo(Combine o) { 36 System.out.print("compare " + this + " and " + o); 37 // 排序時只考慮p1 38 if (this.p1 < o.p1) { 39 System.out.println(", return -1"); 40 return -1; 41 } else if (this.p1 > o.p1) { 42 System.out.println(", return 1"); 43 return 1; 44 } else { 45 System.out.println(", return 0"); 46 return 0; 47 } 48 } 49 50 @Override 51 public String toString() { 52 return "(" + p1 + "," + p2 + ")"; 53 } 54 55 public int getP1() { 56 return p1; 57 } 58 59 public void setP1(int p1) { 60 this.p1 = p1; 61 } 62 63 public int getP2() { 64 return p2; 65 } 66 67 public void setP2(int p2) { 68 this.p2 = p2; 69 } 70 71 } 72 73 @Test 74 public void test() { 75 Combine c1 = new Combine(1, 2); 76 Combine c2 = new Combine(1, 2); 77 Combine c3 = new Combine(1, 3); 78 Combine c4 = new Combine(5, 2); 79 80 TreeSet<Combine> set = new TreeSet<Combine>(); 81 set.add(c1); 82 set.add(c2); 83 set.add(c3); 84 set.add(c4); 85 while (!set.isEmpty()) { //按順序輸出TreeSet中的元素 86 Combine combine = set.pollFirst(); 87 System.out.println(combine.getP1() + "\t" + combine.getP2()); 88 } 89 } 90 }
輸出:
compare (1,2) and (1,2), return 0
compare (1,2) and (1,2), return 0
compare (1,3) and (1,2), return 0
compare (5,2) and (1,2), return 1
1 2
5 2
我們看到不論compareTo()返回的是不是相等,equals()方法都沒有被調用。