TreeSet基于TreeMap,它很有意思,當你執行add()方法的時候,集合會自動排序,不需要手工執行Collections.sort()進行排序,代碼更加簡潔(Clean),今天使用過程發現它暗藏機關,與大家分享。
使用TreeSet有兩種方法:
一、元素實作Comparable接口,然後直接通過add方法添加元素即可。
二、建立一個Comparator,并在構造TreeSet的時候傳入,如下:
//我這裡Job為待添加元素
Set<Job> jobs = new TreeSet<Job>(new JobComparator());
我要實作的需求很簡單,根據Job的優先級字段(Priority)進行排序,Job類代碼如下:
public class Job implements Comparable<SortJob> {
private String jobName;
private Integer priority;
public SortJob() {
}
public SortJob(String jobName, Integer priority) {
this.jobName = jobName;
this.priority = priority;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public Integer getPriority() {
return priority;
}
public void setPriority(Integer priority) {
this.priority = priority;
}
@Override
public int compareTo(SortJob o) {
return priority.compareTo(o.getPriority());
}
}
測試代碼如下:
@Test
public void sortJob() {
Set<SortJob> jobs = new TreeSet<SortJob>();
jobs.add(new SortJob("001", 1));
jobs.add(new SortJob("002", 1));
jobs.add(new SortJob("003", 1));
assertEquals(3, jobs.size()); // ①
jobs.clear();
jobs.add(new SortJob("001", 1));
jobs.add(new SortJob("002", 3));
jobs.add(new SortJob("003", 2));
List<SortJob> listJobs = new ArrayList<SortJob>(jobs);
assertEquals("001", listJobs.get(0).getJobName());
assertEquals("003", listJobs.get(1).getJobName());
assertEquals("002", listJobs.get(2).getJobName());
}
測試并沒有通過,在行①,這裡實際集合size為1,出了什麼問題呢?
soga,原來TreeSet的add方法會先調用Job的compareTo方法判斷元素是否重複,因為Priority全部為1,是以TreeSet認為後兩個Job是重複的,這樣的結果顯然不是我們想要的,重新實作compareTo方法如下:
@Override
public int compareTo(SortJob o) {
int compare1 = priority.compareTo(o.getPriority());
return compare1 == 0 ? this.jobName.compareTo(o.jobName) : compare1;
}
再次運作測試,OK了。
總結:
- TreeSet通過集合元素的compareTo方法判斷元素是否重複,實作compareTo方法既要考慮排序,又要考慮對象是否重複
- 發現這個陷阱後,發現Collections.sort()還是很不錯的選擇,隻需要考慮排序就可以了。
--heipark