TreeSet有趣問題之add方法原理
阿新 • • 發佈:2019-01-31
先看如下程式碼
class Worker implements Comparable<Worker> { private int age; private String name; public Worker(int age, String name) { this.setAge(age); this.setName(name); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Worker other = (Worker) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public int compareTo(Worker worker) { return new Integer(getAge()).compareTo(new Integer(worker.getAge())); } ...//setter/getter方法 }
public static void main(String[] args) {
<span style="white-space:pre"> </span>TreeSet<Worker> set = new TreeSet<Worker>();
set.add(new Worker(21, "測試人員1"));
set.add(new Worker(22,"測試人員2"));
set.add(new Worker(21, "測試人員3"));
System.out.println(set.size());
}
輸出的結果是幾呢?
按照寫程式碼者的原意應該是想set裡面有三個worker,按照年齡排序的.
可是執行出來的結果卻是2,再細檢視會發現測試人員1沒有了,只有2和3.
這是為什麼呢?檢視原始碼,發現TreeSet的add方法定義如下:
public boolean add(E paramE)
{
return this.m.put(paramE, PRESENT) == null;
}
其中this.m為TreeMap,其put方法定義如下:
如上紅色程式碼,原來在TreeSet的add方法中根本就沒有使用equals方法來判斷兩個元素是否相等,而是直接使用compareTo方法來確定新增元素在集合中的位置.public V put(K paramK, V paramV) { Entry localEntry1 = this.root; if (localEntry1 == null) { compare(paramK, paramK); this.root = new Entry(paramK, paramV, null); this.size = 1; this.modCount += 1; return null; } Comparator localComparator = this.comparator; Entry localEntry2; int i; if (localComparator != null) { do { <span style="color:#ff0000;">localEntry2 = localEntry1; i = localComparator.compare(paramK, localEntry1.key); if (i < 0) { localEntry1 = localEntry1.left; } else if (i > 0) { localEntry1 = localEntry1.right; } else { return localEntry1.setValue(paramV); }</span> } while (localEntry1 != null); } else { if (paramK == null) { throw new NullPointerException(); } localObject = (Comparable)paramK; do { <span style="color:#ff0000;">localEntry2 = localEntry1; i = ((Comparable)localObject).compareTo(localEntry1.key); if (i < 0) { localEntry1 = localEntry1.left; } else if (i > 0) { localEntry1 = localEntry1.right; } else { return localEntry1.setValue(paramV); }</span> } while (localEntry1 != null); } Object localObject = new Entry(paramK, paramV, localEntry2); if (i < 0) { localEntry2.left = ((Entry)localObject); } else { localEntry2.right = ((Entry)localObject); } fixAfterInsertion((Entry)localObject); this.size += 1; this.modCount += 1; return null; }
若要實現我們想要的結果,Worker中的compareTo方法應該做修改為
@Override
public int compareTo(Worker worker) {
int index = getName().compareTo(worker.getName());
if(index != 0){
index = new Integer(getAge()).compareTo(new Integer(worker.getAge()));
}
return index;
}
如此就能得到我們想要的結果了
結論:TreeSet中確定集合中兩元素相等不是使用equals方法,而是使用compareTo方法.