有時在做專案時需要對某種類型的物件集合進行排序,為此你可能會認為有必要實作我們自己的排序演算法,但這有點不必要,儘管了解一下也沒什麼壞處他們如何運作。例如,如果您有一個整數數組,則可以使用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]
int compare(T o1, T o2);
public record Movie( String name, List<String> actors, int budget, int year ) { }
// a < b -> -1 a.year() < b.year() -> -1
假設我們在 List
// a > b -> 1 a.budget() > b.budget() -> 1
如果您想按發行年份升序排列電影,您可以建立一個 Comparator
// 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]
在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中文網其他相關文章!