目錄
1.前言
2.Comaprable接口
2.1 使用細節
2.2 案例演示
3.Comparator接口
3.1 為什么需要Comparator接口
3.2 使用細節
3.3 案例演示
4.Comparable、Comparator對比
1.前言
Java 中的對象,正常情況下,只能進行比較:== ?或 ?!= 。不能使用 > 或 < 。但是在實際開發場景中,有時候需要對多個對象進行排序,言外之意,就是需要比較對象的大小。這便引出了?Comparable、Comparator 兩個接口
2.Comaprable接口
Comparable 位于 java.lang.Comaprable,其源碼如下:
package java.lang;
import java.util.*;
public interface Comparable<T> {public int compareTo(T o);
}
2.1 使用細節
① 實現 Comparable?接口的類必須實現 int compareTo(T o)?方法,兩個對象可以通過 int compareTo(T o) 方法的返回值來比較大小:
? ? ? ? (1)當前對象 this 大于形參對象 o,則返回正整數
????????(2)當前對象 this 小于形參對象 o,則返回負整數
????????(3)當前對象 this 等于形參對象 o,則返回 0
②?實現 Comparable 接口的對象列表或數組可以通過 Collections.sort 或 Arrays.sort 進行自動排序,無需指定 Collection.sort(...)、Arrays.sort(...) 方法的第二個比較器參數,底層會根據類中實現的?int compareTo(T o)? 作為排序邏輯
③ String、八大包裝類都 implements 了該接口,并實現了 int compareTo(T o) 方法,都是從小到大排列的
String:按照字符串中字符的 ASCII?值進行比較
Character:按照字符的 ASCII?值來進行比較
數值類型對應的包裝類以及 BigInteger、BigDecimal :按照它們對應的數值大小進行比較
Boolean:true 對應的包裝類實例大于 false 對應的包裝類實例
Date、Time等:后面的日期時間比前面的日期時間大
2.2 案例演示
案例1 :根據學生的年齡對學生類型數組進行升序排序?
import java.util.Arrays;
import java.util.Comparator;
public class demo {public static void main(String[] args) {Student s1 = new Student("小馬", 100);Student s2 = new Student("蔡徐坤", 5);Student s3 = new Student("ftt", 90);Student[] arr1 = {s1,s2,s3};Student[] arr2 = {s1,s2,s3};System.out.println("排序前,所有學生:");Arrays.stream(arr1).forEach(student -> System.out.println(student));System.out.println("----------------------");//方式1:使用冒泡排序System.out.println("按照年齡排序:");for (int i = 1; i < arr1.length; i++) {for (int j = 0; j < arr1.length-i; j++) {if(arr1[j].compareTo(arr1[j+1])>0){Student temp = arr1[j];arr1[j] = arr1[j+1];arr1[j+1] = temp;}}}Arrays.stream(arr1).forEach(student -> System.out.println(student));System.out.println("----------------------");//方式2:使用Arrays.sort排序,因為在Student類已實現Comparable接口,所以無需指定比較器Arrays.sort(arr2);Arrays.stream(arr2).forEach(student -> System.out.println(student));}
}class Student implements Comparable<Student> {public String name;public int age;public Student(){}public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}//按學生年齡升序排序@Overridepublic int compareTo(Student anotherStudent) {if(this.age > anotherStudent.age){return 1;}else if(this.age < anotherStudent.age){return -1;}else{return 0;}}
}
?案例1運行結果:
案例2?:對字符數組進行排序
import java.util.Arrays;
public class demo {public static void main(String[] args) {Character[] arr = {'b','a','c','d'};System.out.println("排序前的字符數組:"+Arrays.toString(arr));Arrays.sort(arr);//Arrays底層會將Character類中實現的 int compareTo(T o) 方法作為排序邏輯System.out.println("排序后的字符數組:"+Arrays.toString(arr));}
}
?案例2運行結果:?
3.Comparator接口
Comparator 接口位于 java.until.Comparator 下,其中關于 int compareTo(...) 接口的源碼如下:
package java.util;public interface Comparator<T>{int compare(T o1,T o2);
}
3.1 為什么需要Comparator接口
場景 ① :當只有第三方的類時(即只有 .class 字節碼文件,沒有 .java 源文件,無法修改代碼),且這些類沒有實現 java.lang.Comparable 接口
場景 ② :類中提前實現了 Comparable 接口,指定了兩個對象比較大小的規則,但此時如果不想按照它預定義的方法比較大小,但是又不能隨意修改源碼,因為會影響其他地方的使用,怎么辦呢?
因此,基于?①、② ,Java?增加了一個 java.util.Comparator 接口來解決問題
3.2 使用細節
① 通常是用一個單獨的其他的類來實現 Comparator 接口
②?實現 Comparator 的類必須實現 int compareTo (T o1,T o2) 方法,兩個對象可以通過 int compareTo (T o1,T o2) 方法的返回值來比較大小:
? ? ? ? (1)?o1?大于?o2,則返回正整數
????????(2)?o1?小于?o2,則返回負整數
????????(3)?o1?等于?o2,則返回 0
③?在使用 Collection.sort 或 Arrays.sort 實現排序功能時,可以將實現了 Comparator 接口的類的實例傳遞給 Collection.sort 或 Arrays.sort,作為排序邏輯的比較器
3.3 案例演示
案例
import java.util.Arrays;
import java.util.Comparator;
public class demo {public static void main(String[] args) {//定義比較器實例StudentScoreComparator sc = new StudentScoreComparator();Student s1 = new Student("小馬", 22,98);Student s2 = new Student("jack", 55,90);Student s3 = new Student("mary", 30,67);Student[] arr1 = {s1,s2,s3};Student[] arr2 = {s1,s2,s3};System.out.println("按分數排序前,所有學生:");Arrays.stream(arr1).forEach(student -> System.out.println(student));System.out.println("----------------------");//方式1:使用冒泡排序System.out.println("按照分數排序:");for (int i = 1; i < arr1.length; i++) {for (int j = 0; j < arr1.length-i; j++) {if(sc.compare(arr1[j],arr1[j+1]) > 0) {Student temp = arr1[j];arr1[j] = arr1[j+1];arr1[j+1] = temp;}}}Arrays.stream(arr1).forEach(student -> System.out.println(student));System.out.println("----------------------");//方式2:使用Arrays.sort排序,指定StudentScoreComparator為比較器,按學生的分數排序Arrays.sort(arr2,sc);Arrays.stream(arr2).forEach(student -> System.out.println(student));}
}//定制比較器類,按學生的分數升序排序
class StudentScoreComparator implements Comparator<Student>{@Overridepublic int compare(Student s1, Student s2) {if(s1.score > s2.score){return 1;}else if(s1.score < s2.score){return -1;}else{return 0;}}
}class Student implements Comparable<Student> {public String name;public int age;public int score;public Student(){}public Student(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}//按學生年齡升序排序@Overridepublic int compareTo(Student anotherStudent) {if(this.age > anotherStudent.age){return 1;}else if(this.age < anotherStudent.age){return -1;}else{return 0;}}
}
案例1運行結果:?
4.Comparable、Comparator對比
Comparable | Comparator | |
---|---|---|
實現位置 | 類內部實現 | 外部獨立實現 |
排序規則數量 | 只能定義一種排序規則 | 可根據業務求定義多種排序規則 |
侵入性 | 需要修改原類代碼 | 不需要修改原類代碼 |
方法 | int compareTo (T o) | int compare (T o1, T o2) |
使用場景 | 默認排序,如 Arrays.sort(arr) | 靈活排序,如 Arrays.sort(arr,comparator) |