Java?中的排序Comparable?與?Comparator?的使用與區(qū)別對比解析
1. 背景
在 Java 中,如果我們希望自定義類能夠進行排序(例如在集合、數(shù)組中排序),就需要定義對象的比較規(guī)則。
Java 提供了兩種方式:
Comparable<T>接口 → 在類內(nèi)部實現(xiàn),定義對象的“自然順序”。Comparator<T>接口 → 在類外部定義比較器,可以靈活指定不同的排序規(guī)則。
2.Comparable接口
Java 中很多常用類都實現(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 返回值含義
- 負數(shù):當前對象 < 參數(shù)對象
- 0:當前對象 == 參數(shù)對象
- 正數(shù):當前對象 > 參數(shù)對象
2.3 使用場景
當一個類本身就有固定的“自然排序規(guī)則”,可以直接實現(xiàn) Comparable。
3.Comparator接口
3.1 定義
public interface Comparator<T> {
int compare(T o1, T o2);
}3.2 返回值含義
與 Comparable 相同:
- 負數(shù) → o1 < o2
- 0 → o1 == o2
- 正數(shù) → o1 > o2
3.3 使用場景
當我們不想修改類本身,或者需要定義多種排序規(guī)則時,使用 Comparator 更靈活。
4.ComparablevsComparator區(qū)別表
| 特性 | Comparable | Comparator |
|---|---|---|
| 方法 | int compareTo(T o) | int compare(T o1, T o2) |
| 定義位置 | 類 內(nèi)部(實現(xiàn)接口) | 類 外部(單獨寫比較器) |
| 排序規(guī)則數(shù)量 | 一種(自然順序) | 多種(可定義多個 Comparator) |
| 修改類代碼需求 | 需要修改類本身 | 不需要修改類本身 |
| 常見使用場景 | Collections.sort(list) | Collections.sort(list, comparator) |
5. Comparable 與 Comparator的使用示例:對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 表達式(Java 8+推薦)
list.sort((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()));
方式三:方法引用(更簡潔)
list.sort(Comparator.comparing(Student::getAge));
?? 輸出結(jié)果同樣是:
[Bob(18), Charlie(20), Alice(22)]
6. 多條件排序(進階)
6.1使用Comparator實現(xiàn)多條件排序
使用 Comparator 時,可以輕松實現(xià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 表達式寫法(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的特點
Comparable是 自然排序(對象自己規(guī)定的排序規(guī)則)。- 一個類 只能實現(xiàn)一次
compareTo方法,也就是說只能有一種排序邏輯。 - 例子:
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;
}
}?? 這樣就能實現(xiàn) 多條件排序,但限制是 Student 這個類就被固定死了,始終用這一套排序規(guī)則(先按年齡升序,再按名字字母序升序),如果后續(xù)想先按照名字字母就要改這個compareTo方法。
2??Comparator的特點
Comparator是 外部比較器,不修改實體類本身。- 可以定義多個不同的排序規(guī)則,根據(jù)需要隨時切換。
- 例子(用的上面使用
Comparator實現(xiàn)多條件排序的方式一):
Comparator<Student> byAgeThenName =
Comparator.comparing(Student::getAge)
.thenComparing(Student::getName);
Comparator<Student> byNameThenAge =
Comparator.comparing(Student::getName)
.thenComparing(Student::getAge);?? 這樣一個類(Student)就可以有 多種排序方式,靈活性更高。
3?? 多條件的對比
- Comparable:類內(nèi)部定義,固定一種排序邏輯(可以寫多條件,但只能有這一種)。
- Comparator:類外部定義,可以有多種排序邏輯,靈活組合,推薦用于多條件排序。
?? 這樣就能實現(xiàn) 多條件排序,但限制是 Student 這個類就被固定死了,始終用這一套排序規(guī)則。
? 多條件排序,Comparable 也能實現(xiàn)(在 compareTo 里寫多條件邏輯)。
? 但是 Comparable 只能有這一種排序方式,靈活性差。
?? 真正業(yè)務(wù)里,一般 多條件排序都會用 Comparator。
7. 總結(jié)
Comparable:讓類具備自然排序能力,適合“唯一固定規(guī)則”的場景。Comparator:外部比較器,適合需要定義多種排序規(guī)則的場景。- 對于
List<Student>: - 如果
Student類實現(xiàn)了Comparable,直接用Collections.sort(list)。 - 如果不想改
Student類,可以用Comparator方式排序。
- 對于
- 推薦使用
Comparator.comparing(...)+ Lambda/方法引用,更簡潔靈活。
到此這篇關(guān)于java--Java 中的排序:Comparable 與 Comparator 的使用與區(qū)別的文章就介紹到這了,更多相關(guān)java Comparable 與 Comparator使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java中Comparator與Comparable排序的區(qū)別詳解
- Java排序之Comparable和Comparator比較器詳解
- Java去重排序之Comparable與Comparator的使用及說明
- java中實現(xiàn)對象排序的兩種方法(Comparable,Comparator)
- java?集合工具類Collections及Comparable和Comparator排序詳解
- Java元素排序Comparable與Comparator的區(qū)別
- java中元素排序Comparable和Comparator的區(qū)別
- 對比Java中的Comparable排序接口和Comparator比較器接口
相關(guān)文章
Spring中網(wǎng)絡(luò)請求客戶端WebClient的使用詳解
作為替代,Spring 官方已在 Spring 5 中引入了 WebClient 作為非阻塞式 Reactive HTTP 客戶端,本文將通過樣例演示如何使用 WebClient,希望對大家有所幫助2024-04-04
Java基于HttpClient實現(xiàn)RPC的示例
HttpClient可以實現(xiàn)使用Java代碼完成標準HTTP請求及響應(yīng)。本文主要介紹了Java基于HttpClient實現(xiàn)RPC,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10
解析Oracle數(shù)據(jù)庫中的對象集合schema
這篇文章主要介紹了Oracle數(shù)據(jù)庫中的對象集合schema,是Oracle數(shù)據(jù)庫入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-11-11
IDEA?Error:java:無效的源發(fā)行版:13的解決過程
之前用idea運行時,也會出現(xiàn)這種情況,后面通過網(wǎng)上的資料解決了這個問題,下面這篇文章主要給大家介紹了關(guān)于IDEA?Error:java:無效的源發(fā)行版:13的解決過程,需要的朋友可以參考下2023-01-01
Java線程讓步_動力節(jié)點Java學(xué)院整理
yield()的作用是讓步。它能讓當前線程由“運行狀態(tài)”進入到“就緒狀態(tài)”,從而讓其它具有相同優(yōu)先級的等待線程獲取執(zhí)行權(quán)。下面通過本文給大家介紹Java線程讓步的相關(guān)知識,需要的朋友參考下吧2017-05-05
VSCode?配置?Spring?Boot?項目開發(fā)環(huán)境的全過程
兩三年前曾經(jīng)試過配置Java環(huán)境, 存在不少問題作罷. 最近搜了下相關(guān)的文章, 感覺VSCode對Java項目的支持比三年前完善了不少. 今天實際配置了一下環(huán)境, 把自己常用的功能過了一遍, 基本能跑通開發(fā)流程, 做個筆記,需要的朋友可以參考下2024-03-03

