一、如何確定升序還是降序?
Java中在進行對象排序時,設計的排序器經常會對兩個對象按照一定的排序規則排序,可如何確定排序規則是升序還是降序呢?筆者整理了一個簡單的方法來確定排序規則。
o1和o2是需要表示排序的兩個對象,假定比較前的默認順序為 [o1, o2],是升序還是降序暫時不做考慮,完全根據返回值結果表示是否需要調整當前的排序順序,便能夠理解排序的真正邏輯,以確定是升序排序還是降序排序。
假設我們的比較器規則如下:o1對象作為比較的前者,o2對象作為排序的后者,即比較方式為 [o1 - o2]或者 [o1.compareTo(o2)]。
class ComparatorByAge implements Comparator {
// 根據年齡和姓名排序
@Override public int compare(Object o1, Object o2) { Person p1 = (Person) o1; Person p2 = (Person) o2; int tmp = p1.getAge() - p2.getAge(); return tmp == 0 ? p1.getName().compareTo(p2.getName()) : tmp; } }
升序規則:
- o1 > o2,返回正數,true,表示需要調整順序,升序。
- o1 < o2,返回負數,false,表示不需要調整順序,升序。
降序規則:
- o1 > o2,返回負數,false,表示不需要調整順序,降序。
- o1 < o2,返回正數,true,表示需要調整順序,降序。
不排序規則:
- o1 = o2,返回0,按當前順序即可,或者比較其他參數。
二、實際用例
Person 是定義的需要排序的對象,包括年齡和姓名兩個字段。

class Person implements Comparable{ private String name; private int age; // 重寫toString()方法,輸出對象時輸出格式為:name:age @Override public String toString() { return name+ ":" + age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person(String name, int age) { super(); this.name = name; this.age = age; } // Person自帶的排序規則 @Override public int compareTo(Object o) { Person p = (Person) o; // 根據年齡進行排序 int temp = this.age - p.age; return temp == 0 ? this.name.compareTo(p.name):temp; } }
排序規則一:定義升序排序器,先按年齡升序,再按姓名首字母升序。
- 比如 o1對象為 (zhangshan:20) ,o2 對象為 (wangwu:21) ,默認排序 [o1, o2],由於 o1.age < o2.age,比較結果返回負數,false,表示不需要調整規則,按年齡升序排序,最終排序結果為 [zhangshan:20, wangwu:21]。
- 比如 o1 對象為 (zhangshan:20) ,o2對象為 (lisi:20),默認排序 [o1,o2],由於 o1.age = o2.age,比較結果為0,不按年齡排序,進一步比較name,由於 o1.name > o2.name,返回 true,調整排序規則,即按字母升序排序,最終排序結果為 [lisi:20, zhangshan:20]。
/**
* 自定義升序排序器
* 升序:先按年齡升序,再按姓名首字母升序
*/
class ComparatorByAge implements Comparator {
// 根據年齡排序
@Override public int compare(Object o1, Object o2) { Person p1 = (Person) o1; Person p2 = (Person) o2; int tmp = p1.getAge() - p2.getAge(); return tmp == 0 ? p1.getName().compareTo(p2.getName()) : tmp; } }
排序規則二:定義降序排序器,先按年齡降序,再按姓名首字母降序。和升序的唯一區別就是返回結果的參數前添加了一個負號。
/**
* 自定義降序排序器
* 降序:先按年齡降序,再按姓名首字母降序
*/
class ComparatorByAge2 implements Comparator {
// 根據年齡排序
@Override public int compare(Object o1, Object o2) { Person p1 = (Person) o1; Person p2 = (Person) o2; int tmp = p1.getAge() - p2.getAge(); return tmp == 0 ? -(p1.getName().compareTo(p2.getName())) : -tmp; } }
排序 main() 方法,查看兩種排序器的排序結果。
public class TreeSetDemo { public static void main(String[] args) { TreeSet<Person> ts = new TreeSet(new ComparatorByAge()); ts.add(new Person("zhangsan", 20)); ts.add(new Person("wangwu", 21)); ts.add(new Person("lisi", 20)); ts.add(new Person("zhouqi", 29)); ts.add(new Person("zhaoliu", 28)); for (Person person : ts) { System.out.println(person); } /* 結果輸出 lisi:20 zhangsan:20 wangwu:21 zhaoliu:28 zhouqi:29 */ ts = new TreeSet(new ComparatorByAge2()); ts.add(new Person("zhangsan", 20)); ts.add(new Person("wangwu", 21)); ts.add(new Person("lisi", 20)); ts.add(new Person("zhouqi", 29)); ts.add(new Person("zhaoliu", 28)); for (Person person : ts) { System.out.println(person); } /* 結果輸出 zhouqi:29 zhaoliu:28 wangwu:21 zhangsan:20 lisi:20 */ } }