在數據庫中咱們可使用 order by
和 group by
輕鬆實現分組和排序的功能,那麼在Java中咱們又該如何實現呢?下面咱們一塊兒來研究一番java
Comparator
與 Comparable
Comparable
是一個排序接口,實現了該接口的類,表示該類支持排序功能,重寫 compareTo
方法可以使程序按照咱們的意願對數組或列表進行排序git
Comparator
是一個比較器接口,若是咱們須要對類進行排序,而該類並無實現 Comparable
接口,那麼咱們能夠經過實現 Comparator
接口來保持類的排序能力github
建立一個 Bean
類,咱們將對該類進行排序數據庫
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
/** * 班級名稱 */
private String className;
/** * 學生姓名 */
private String name;
/** * 分數 */
private Integer score;
}
複製代碼
準備一些數據,用於測試數組
final String classOne = "一班";
final String classTwo = "二班";
final String classThree = "三班";
List<Student> students = new ArrayList<>();
students.add(new Student(classOne, "李一", 43));
students.add(new Student(classOne, "王二", 75));
students.add(new Student(classOne, "張三", 91));
students.add(new Student(classTwo, "郭子", 59));
students.add(new Student(classTwo, "潘子", 88));
students.add(new Student(classTwo, "劉子", 97));
students.add(new Student(classThree, "陳六", 66));
students.add(new Student(classThree, "唐七", 77));
students.add(new Student(classThree, "周八", 89));
複製代碼
建立一個 Comparator
對象測試
若是咱們將第一參數與第二個參數進行比較,那麼表示這是一個升序序列(天然排序),不然表示一個降序序列。 固然這樣說並不徹底準確,主要仍是看返回的整數值是大於零、小於零仍是等於零,只有當大於零時對象 o2
纔會置於對象 o1
前面spa
// 按分數進行降序排序
Comparator<Student> comparator = (o1, o2) -> o2.getScore().compareTo(o1.getScore());
複製代碼
測試排序結果code
Collections.sort(students, comparator);
students.forEach(System.out::println);
複製代碼
打印結果,能夠看出列表是按分數進行排序的,接下來咱們將對班級名稱進行分組並按分數排序對象
Student(className=二班, name=劉子, score=97)
Student(className=一班, name=張三, score=91)
Student(className=三班, name=周八, score=89)
Student(className=二班, name=潘子, score=88)
Student(className=三班, name=唐七, score=77)
Student(className=一班, name=王二, score=75)
Student(className=三班, name=陳六, score=66)
Student(className=二班, name=郭子, score=59)
Student(className=一班, name=李一, score=43)
複製代碼
建立一個分組排序的 Comparator
對象排序
因爲咱們須要按班級名稱進行分組排序,因此咱們必須進行兩次計較,第一次比較是不是相同的班級名稱,若是不是直接返回比較的結果值便可,不然返回分數的比較結果
Comparator<Student> groupComparator = (o1, o2) -> {
int diff = o1.getClassName().compareTo(o2.getClassName());
return diff == 0 ? o2.getScore().compareTo(o1.getScore()) : diff;
};
複製代碼
測試排序結果
Collections.sort(students, groupComparator);
students.forEach(System.out::println);
複製代碼
打印結果,能夠看出確實時按班級分組排序的,可是若是咱們想要班級名稱也是按順序排的呢,怎麼作?
Student(className=一班, name=張三, score=91)
Student(className=一班, name=王二, score=75)
Student(className=一班, name=李一, score=43)
Student(className=三班, name=周八, score=89)
Student(className=三班, name=唐七, score=77)
Student(className=三班, name=陳六, score=66)
Student(className=二班, name=劉子, score=97)
Student(className=二班, name=潘子, score=88)
Student(className=二班, name=郭子, score=59)
複製代碼
如何讓分組的名稱按照咱們想要的順序出現?簡單,請看下面
定義一個分組順序
分組順序用來判斷該分組所在位置,這樣咱們就能夠自定義分組的位置,從而實現有序的分組
Map<String, Integer> groupOrder = new HashMap<>(4);
groupOrder.put(classOne, 1);
groupOrder.put(classTwo, 2);
groupOrder.put(classThree, 3);
複製代碼
建立一個有序的分組排序 Comparator
對象
經過自定義的班級順序來決定班級名稱出現的位置
Comparator<Student> orderlyGroupComparator = (o1, o2) -> {
int diff = groupOrder.get(o1.getClassName()).compareTo(groupOrder.get(o2.getClassName()));
return diff == 0 ? o2.getScore().compareTo(o1.getScore()) : diff;
};
複製代碼
測試排序結果
Collections.sort(students, orderlyGroupComparator);
students.forEach(System.out::println);
複製代碼
打印結果
Student(className=一班, name=張三, score=91)
Student(className=一班, name=王二, score=75)
Student(className=一班, name=李一, score=43)
Student(className=二班, name=劉子, score=97)
Student(className=二班, name=潘子, score=88)
Student(className=二班, name=郭子, score=59)
Student(className=三班, name=周八, score=89)
Student(className=三班, name=唐七, score=77)
Student(className=三班, name=陳六, score=66)
複製代碼
如今回過去看,原來分組排序如此的簡單呀,不過這徹底得益於 Comparator
的強大,你也徹底能夠選擇實現 Comparable
接口來達到相同的效果。
當有新的挑戰時,咱們必定要多思考:facepunch:
因爲本人水平有限,有不正確的地方,還望指正,謝謝