首頁 >Java >java教程 >Java 中的比較器是如何運作的?

Java 中的比較器是如何運作的?

Linda Hamilton
Linda Hamilton原創
2024-11-05 16:52:02651瀏覽

¿Cómo funciona Comparator en Java?

介紹

有時在做專案時需要對某種類型的物件集合進行排序,為此你可能會認為有必要實作我們自己的排序演算法,但這有點不必要,儘管了解一下也沒什麼壞處他們如何運作。例如,如果您有一個整數數組,則可以使用Arrays.sort() 方法,該方法接受基元數組並按升序對其進行排序,從而利用無需將結果分配給新變量,因為該方法修改了原始數組。

int[] numbers = {9, 8, 5, 3, 1, 2, 4, 6, 7};
Arrays.sort(numbers);
System.out.println(Arrays.toString(numbers));

// Output
[1, 2, 3, 4, 5, 6, 7, 8, 9]

當您有自訂物件的集合(例如Movie 類型的記錄)時,這也適用,但如果我們看到Arrays.sort() 方法,它不接受這種類型的物件數組,因此它必須使用sort() 方法接受T 類型的物件和Comparator 類型的物件作為參數超級T>這是一個函數式介面。這個介面非常重要,因為 Java 中的許多其他方法都使用它以自訂方式比較物件。例如,List 物件的 Collections.sort() 方法或 sort() 方法,甚至 Streams 也接受 Comparator 來對元素進行排序。

什麼是比較器?

函數式介面Comparator(函數式它可以寫成lambda表達式)是一個允許你比較兩個T類型物件的接口,因此它用於比較整數、字串、自訂物件等此介面有幾個靜態和預設方法,但重要的是compare() 方法,它是比較兩個物件必須實作的方法。 Compare() 接收兩個 T 類型的物件並傳回一個整數。方法簽名如下:

int compare(T o1, T o2);

如果o1小於o2,則該方法傳回負數;如果相等,則傳回零;如果o1大於o2,則方法傳回正數,通常分別回傳-1、0或1。

一個物件小於、等於或大於另一個物件意味著什麼?

讓我們分析一下compare()方法傳回的內容,因為物件的排序取決於此,重要的是要考慮該方法返回的含義是相對的,也就是說,如果您想要升序或降序排列。這取決於具體情況以及如何實施。讓我們為每個範例考慮以下記錄

int[] numbers = {9, 8, 5, 3, 1, 2, 4, 6, 7};
Arrays.sort(numbers);
System.out.println(Arrays.toString(numbers));

// Output
[1, 2, 3, 4, 5, 6, 7, 8, 9]
  • 如果第一個參數小於第二個參數,則傳回負數。例如,要按發行年份對電影進行排序,當電影 a 小於電影 b 時,可以回傳 -1:
int compare(T o1, T o2);
  • 如果第一個參數大於第二個參數,則傳回正數。例如,要按預算對電影進行排序,當電影 a 大於電影 b 時,可以返回 1:
public record Movie(
        String name,
        List<String> actors,
        int budget,
        int year
) {
}
  • 如果第一個參數等於第二個參數,則傳回零。例如,要按演員數量對電影進行排序,當電影 a 等於電影 b 時,可以返回 0:
// a < b -> -1
a.year() < b.year() -> -1

使用比較器

假設我們在 List 類型的物件中有以下影片:

// a > b -> 1
a.budget() > b.budget() -> 1

如果您想按發行年份升序排列電影,您可以建立一個 Comparator 類型的物件並重寫compare()方法,然後將此物件傳遞給清單的sort()方法:

// a == b -> 0
a.actors().size() == b.actors().size() -> 0

它也可以在 sort() 方法中實作為匿名類別:

Movie movie1 = new Movie("The Godfather", Arrays.asList("Marlon Brando", "Al Pacino"), 6000000, 1972);
Movie movie2 = new Movie("The Godfather: Part II", Arrays.asList("Al Pacino", "Robert De Niro"), 13000000, 1974);
Movie movie3 = new Movie("The Shawshank Redemption", Arrays.asList("Tim Robbins", "Morgan Freeman"), 25000000, 1994);
Movie movie4 = new Movie("The Dark Knight", Arrays.asList("Christian Bale", "Heath Ledger"), 185000000, 2008);

List<Movie> movies = Arrays.asList(movie1, movie2, movie3, movie4);

或更簡潔地直接在 sort() 方法中使用 lambda 表達式:

Comparator<Movie> comparatorByYear = new Comparator<Movie>() {
    @Override
    public int compare(Movie o1, Movie o2) {
        return o1.year() - o2.year();
    }
};

movies.sort(comparatorByYear);

任何這些實作都會按發布年份對清單進行升序排序。如果要按降序排序,可以更改 lambda 表達式中參數的順序,或在減法中加入負號:

movies.sort(new Comparator<Movie>() {
    @Override
    public int compare(Movie o1, Movie o2) {
        return o1.year() - o2.year();
    }
});

如何對自訂物件清單進行排序的一些其他範例是:

  • 依演員數量升序排列電影(從少到多):
movies.sort((p1, p2) -> p1.year() - p2.year());
  • 依預算降序對電影進行排序(從最高預算到最低預算):
movies.sort((p1, p2) -> p2.year() - p1.year());
// o
movies.sort((p1, p2) -> - (p1.year() - p2.year()));
  • 依名稱以升序對電影進行排序:
movies.sort((p1, p2) -> p1.actors().size() - p2.actors().size());

在其他範例中,我們可能會遇到需要依降序對整數清單進行排序的情況,

movies.sort((p1, p2) -> p2.budget() - p1.budget());
// o 
movies.sort((p1, p2) -> - (p1.budget() - p2.budget()));

為此,您也可以使用靜態方法 Comparator.reverseOrder() 傳回一個按降序對元素進行排序的比較器,以及使用 Comparator.naturalOrder() 按升序對元素進行排序。

int[] numbers = {9, 8, 5, 3, 1, 2, 4, 6, 7};
Arrays.sort(numbers);
System.out.println(Arrays.toString(numbers));

// Output
[1, 2, 3, 4, 5, 6, 7, 8, 9]

使用 Integer.compare()

在Java 中已經有一些方法允許我們以有效的方式執行這種類型的比較,例如Integer.compare() ,它比較兩個整數,如果第一個參數小於第二個參數零,則傳回負數如果第一個參數大於第二個參數,則相等且為正數。如果我們分析這個方法的工作原理,我們可以看到它與上面解釋的類似,並且傳回的正是Comparator介面的compare()方法所需要的。 Integer.compare() 的實作如下:

int compare(T o1, T o2);

因此,如果您想按發行年份升序對影片進行排序,可以使用 Integer.compare():

public record Movie(
        String name,
        List<String> actors,
        int budget,
        int year
) {
}

使用參考方法

有時可以使用引用方法來執行與先前不同的比較,例如,按升序對整數清單進行排序:

// a < b -> -1
a.year() < b.year() -> -1

Integer 不是唯一具有compareTo() 方法的類,例如String 有一個compareTo() 方法,可以按字典順序比較兩個字串,因此它可以用於對字串列表進行排序,甚至可以將CharSequence 與其一起使用Compare() 方法(技術上表示字元序列)。

// a > b -> 1
a.budget() > b.budget() -> 1

回到電影的例子,如果你想按照上映年份升序對電影進行排序,可以使用compareingInt()方法作為參考方法:

// a == b -> 0
a.actors().size() == b.actors().size() -> 0

或根據 String 類型屬性進行比較,在本例中為電影名稱:

Movie movie1 = new Movie("The Godfather", Arrays.asList("Marlon Brando", "Al Pacino"), 6000000, 1972);
Movie movie2 = new Movie("The Godfather: Part II", Arrays.asList("Al Pacino", "Robert De Niro"), 13000000, 1974);
Movie movie3 = new Movie("The Shawshank Redemption", Arrays.asList("Tim Robbins", "Morgan Freeman"), 25000000, 1994);
Movie movie4 = new Movie("The Dark Knight", Arrays.asList("Christian Bale", "Heath Ledger"), 185000000, 2008);

List<Movie> movies = Arrays.asList(movie1, movie2, movie3, movie4);

按多個屬性排序

有時你可能需要按多個屬性對物件清單進行排序,例如,如果你想按發行年份升序對電影進行排序,按預算降序排序,你可以使用thenComparing() 方法,該方法接收一個比較器,負責按多個屬性排序。例如,如果有兩部電影a和b,上映年份相同,則按預算排序。

Comparator<Movie> comparatorByYear = new Comparator<Movie>() {
    @Override
    public int compare(Movie o1, Movie o2) {
        return o1.year() - o2.year();
    }
};

movies.sort(comparatorByYear);

結論

比較器在Java中很多時候都很有用,因為它們可以讓你以個人化的方式比較對象,不僅如此,它們還可以用在許多Java集合方法中,甚至可以有多個比較器來排序以不同的方式。無論哪種方式,您都可以查閱 IDE 中的 Comparator 文件或官方 Java 文檔,以了解可以使用哪些方法以及如何實作它們。

以上是Java 中的比較器是如何運作的?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn