Java?中的排序Comparable?與?Comparator?的使用與區(qū)別對(duì)比解析
1. 背景
在 Java 中,如果我們希望自定義類能夠進(jìn)行排序(例如在集合、數(shù)組中排序),就需要定義對(duì)象的比較規(guī)則。
Java 提供了兩種方式:
Comparable<T>接口 → 在類內(nèi)部實(shí)現(xiàn),定義對(duì)象的“自然順序”。Comparator<T>接口 → 在類外部定義比較器,可以靈活指定不同的排序規(guī)則。
2.Comparable接口
Java 中很多常用類都實(shí)現(xiàn)了 Comparable 接口,例如 String、Integer。
public class CompareToDemo {
public static void main(String[] args) {
// String 按字典序比較
System.out.println("apple".compareTo("banana")); // -1
System.out.println("dog".compareTo("dog")); // 0
System.out.println("zoo".compareTo("apple")); // 正數(shù)
// Integer 按數(shù)值大小比較
Integer a = 10, b = 20;
System.out.println(a.compareTo(b)); // -1
System.out.println(b.compareTo(a)); // 1
System.out.println(a.compareTo(10));// 0
}
}2.1 定義
public interface Comparable<T> {
int compareTo(T o);
}
2.2 返回值含義
- 負(fù)數(shù):當(dāng)前對(duì)象 < 參數(shù)對(duì)象
- 0:當(dāng)前對(duì)象 == 參數(shù)對(duì)象
- 正數(shù):當(dāng)前對(duì)象 > 參數(shù)對(duì)象
2.3 使用場(chǎng)景
當(dāng)一個(gè)類本身就有固定的“自然排序規(guī)則”,可以直接實(shí)現(xiàn) Comparable。
3.Comparator接口
3.1 定義
public interface Comparator<T> {
int compare(T o1, T o2);
}3.2 返回值含義
與 Comparable 相同:
- 負(fù)數(shù) → o1 < o2
- 0 → o1 == o2
- 正數(shù) → o1 > o2
3.3 使用場(chǎng)景
當(dāng)我們不想修改類本身,或者需要定義多種排序規(guī)則時(shí),使用 Comparator 更靈活。
4.ComparablevsComparator區(qū)別表
| 特性 | Comparable | Comparator |
|---|---|---|
| 方法 | int compareTo(T o) | int compare(T o1, T o2) |
| 定義位置 | 類 內(nèi)部(實(shí)現(xiàn)接口) | 類 外部(單獨(dú)寫比較器) |
| 排序規(guī)則數(shù)量 | 一種(自然順序) | 多種(可定義多個(gè) Comparator) |
| 修改類代碼需求 | 需要修改類本身 | 不需要修改類本身 |
| 常見使用場(chǎng)景 | Collections.sort(list) | Collections.sort(list, comparator) |
5. Comparable 與 Comparator的使用示例:對(duì)List<Student>按age排序
5.1 使用Comparable
class Student implements Comparable<Student> {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 定義“自然順序”:按年齡升序
@Override
public int compareTo(Student other) {
return Integer.compare(this.age, other.age);
}
@Override
public String toString() {
return name + "(" + age + ")";
}
}
public class ComparableDemo {
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student("Alice", 22));
list.add(new Student("Bob", 18));
list.add(new Student("Charlie", 20));
// 使用 Comparable 定義的 compareTo 方法排序
Collections.sort(list);
System.out.println(list);
// 輸出: [Bob(18), Charlie(20), Alice(22)]
}
}5.2 使用Comparator
如果我們不想修改 Student 類,或者想要不同的排序規(guī)則,可以使用 Comparator。
方式一:匿名內(nèi)部類
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return Integer.compare(s1.getAge(), s2.getAge());
}
});
方式二:Lambda 表達(dá)式(Java 8+推薦)
list.sort((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()));
方式三:方法引用(更簡(jiǎn)潔)
list.sort(Comparator.comparing(Student::getAge));
?? 輸出結(jié)果同樣是:
[Bob(18), Charlie(20), Alice(22)]
6. 多條件排序(進(jìn)階)
6.1使用Comparator實(shí)現(xiàn)多條件排序
使用 Comparator 時(shí),可以輕松實(shí)現(xiàn)多條件排序。
例如:先按年齡升序,再按名字字母序升序
//方式一、方法引用 + 鏈?zhǔn)?Comparator
list.sort(
Comparator.comparing(Student::getAge)
.thenComparing(Student::getName)
);
//方式二、匿名內(nèi)部類寫法
list.sort(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 先按年齡排序
int result = Integer.compare(s1.getAge(), s2.getAge());
// 如果年齡相同,則按姓名排序
if (result == 0) {
result = s1.getName().compareTo(s2.getName());
}
return result;
}
});
//方式三、Lambda 表達(dá)式寫法(Java 8+ 推薦)
list.sort((s1, s2) -> {
int result = Integer.compare(s1.getAge(), s2.getAge());
if (result == 0) {
result = s1.getName().compareTo(s2.getName());
}
return result;
});6.2 那是不是不能使用Comparable完成多條件呢?
1??Comparable的特點(diǎn)
Comparable是 自然排序(對(duì)象自己規(guī)定的排序規(guī)則)。- 一個(gè)類 只能實(shí)現(xiàn)一次
compareTo方法,也就是說(shuō)只能有一種排序邏輯。 - 例子:
public class Student implements Comparable<Student> {
private int age;
private String name;
@Override
public int compareTo(Student other) {
// 先按年齡,再按姓名
int result = Integer.compare(this.age, other.age);
if (result == 0) {
result = this.name.compareTo(other.name);
}
return result;
}
}?? 這樣就能實(shí)現(xiàn) 多條件排序,但限制是 Student 這個(gè)類就被固定死了,始終用這一套排序規(guī)則(先按年齡升序,再按名字字母序升序),如果后續(xù)想先按照名字字母就要改這個(gè)compareTo方法。
2??Comparator的特點(diǎn)
Comparator是 外部比較器,不修改實(shí)體類本身。- 可以定義多個(gè)不同的排序規(guī)則,根據(jù)需要隨時(shí)切換。
- 例子(用的上面使用
Comparator實(shí)現(xiàn)多條件排序的方式一):
Comparator<Student> byAgeThenName =
Comparator.comparing(Student::getAge)
.thenComparing(Student::getName);
Comparator<Student> byNameThenAge =
Comparator.comparing(Student::getName)
.thenComparing(Student::getAge);?? 這樣一個(gè)類(Student)就可以有 多種排序方式,靈活性更高。
3?? 多條件的對(duì)比
- Comparable:類內(nèi)部定義,固定一種排序邏輯(可以寫多條件,但只能有這一種)。
- Comparator:類外部定義,可以有多種排序邏輯,靈活組合,推薦用于多條件排序。
?? 這樣就能實(shí)現(xiàn) 多條件排序,但限制是 Student 這個(gè)類就被固定死了,始終用這一套排序規(guī)則。
? 多條件排序,Comparable 也能實(shí)現(xiàn)(在 compareTo 里寫多條件邏輯)。
? 但是 Comparable 只能有這一種排序方式,靈活性差。
?? 真正業(yè)務(wù)里,一般 多條件排序都會(huì)用 Comparator。
7. 總結(jié)
Comparable:讓類具備自然排序能力,適合“唯一固定規(guī)則”的場(chǎng)景。Comparator:外部比較器,適合需要定義多種排序規(guī)則的場(chǎng)景。- 對(duì)于
List<Student>: - 如果
Student類實(shí)現(xiàn)了Comparable,直接用Collections.sort(list)。 - 如果不想改
Student類,可以用Comparator方式排序。
- 對(duì)于
- 推薦使用
Comparator.comparing(...)+ Lambda/方法引用,更簡(jiǎn)潔靈活。
到此這篇關(guān)于java--Java 中的排序:Comparable 與 Comparator 的使用與區(qū)別的文章就介紹到這了,更多相關(guān)java Comparable 與 Comparator使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java中Comparator與Comparable排序的區(qū)別詳解
- Java排序之Comparable和Comparator比較器詳解
- Java去重排序之Comparable與Comparator的使用及說(shuō)明
- java中實(shí)現(xiàn)對(duì)象排序的兩種方法(Comparable,Comparator)
- java?集合工具類Collections及Comparable和Comparator排序詳解
- Java元素排序Comparable與Comparator的區(qū)別
- java中元素排序Comparable和Comparator的區(qū)別
- 對(duì)比Java中的Comparable排序接口和Comparator比較器接口
相關(guān)文章
Spring Security 圖片驗(yàn)證碼功能的實(shí)例代碼
spring security是一系列的過濾器鏈,所以在這里驗(yàn)證碼也聲明為過濾器,加在過濾器鏈的 登錄過濾器之前,然后自定義一個(gè)異常類,來(lái)響應(yīng)驗(yàn)證碼的錯(cuò)誤信息.這篇文章主要介紹了Spring Security 圖片驗(yàn)證碼,需要的朋友可以參考下2018-03-03
SpringBoot+Vue跨域配置(CORS)問題得解決過程
在使用 Spring Boot 和 Vue 開發(fā)前后端分離的項(xiàng)目時(shí),跨域資源共享(CORS)問題是一個(gè)常見的挑戰(zhàn),接下來(lái),我將分享我是如何一步步解決這個(gè)問題的,包括中間的一些試錯(cuò)過程,希望能夠幫助到正在經(jīng)歷類似問題的你2024-08-08
springboot整合nacos,如何讀取nacos配置文件
這篇文章主要介紹了springboot整合nacos,如何讀取nacos配置文件問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
SpringBoot獲取HttpServletRequest的3種方式總結(jié)
這篇文章主要給大家介紹了關(guān)于SpringBoot獲取HttpServletRequest的3種方式,在Spring boot項(xiàng)目中經(jīng)常要用到Servlet的常用對(duì)象如HttpServletRequest request,HttpServletResponse response,HttpSession session,需要的朋友可以參考下2023-08-08
Java數(shù)據(jù)結(jié)構(gòu)之選擇排序算法的實(shí)現(xiàn)與優(yōu)化
選擇排序:(Selection?sort)是一種簡(jiǎn)單直觀的排序算法,也是一種不穩(wěn)定的排序方法。本文主要為大家介紹一下選擇排序的實(shí)現(xiàn)與優(yōu)化,希望對(duì)大家有所幫助2023-01-01

