亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

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

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

Nov 05, 2024 pm 04:52 PM

?Cómo funciona Comparator en Java?

介紹

有時(shí)在做項(xiàng)目時(shí)需要對(duì)某種類型的對(duì)象集合進(jìn)行排序,為此你可能會(huì)認(rèn)為有必要實(shí)現(xiàn)我們自己的排序算法,但這有點(diǎn)不必要,盡管了解一下也沒什么壞處他們?nèi)绾喂ぷ鳌@?,如果您有一個(gè)整數(shù)數(shù)組,則可以使用 Arrays.sort() 方法,該方法接受基元數(shù)組并按升序?qū)ζ溥M(jìn)行排序,從而利用無需將結(jié)果分配給新變量,因?yàn)樵摲椒ㄐ薷牧嗽紨?shù)組。

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]

當(dāng)您有自定義對(duì)象的集合(例如 Movie 類型的記錄)時(shí),這也適用,但如果我們看到 Arrays.sort() 方法,它不接受這種類型的對(duì)象數(shù)組,因此它必須使用 sort() 方法接受 T 類型的對(duì)象和 Comparator 類型的對(duì)象作為參數(shù)超級(jí)T>這是一個(gè)函數(shù)式接口。這個(gè)接口非常重要,因?yàn)?Java 中的許多其他方法都使用它以自定義方式比較對(duì)象。例如,List 對(duì)象的 Collections.sort() 方法或 sort() 方法,甚至 Streams 也接受 Comparator 來對(duì)元素進(jìn)行排序。

什么是比較器?

函數(shù)式接口Comparator(函數(shù)式它可以寫成lambda表達(dá)式)是一個(gè)允許你比較兩個(gè)T類型對(duì)象的接口,因此它用于比較整數(shù)、字符串、自定義物體等該接口有幾個(gè)靜態(tài)和默認(rèn)方法,但重要的是compare() 方法,它是比較兩個(gè)對(duì)象必須實(shí)現(xiàn)的方法。 Compare() 接收兩個(gè) T 類型的對(duì)象并返回一個(gè)整數(shù)。方法簽名如下:

int compare(T o1, T o2);

如果o1小于o2,該方法返回負(fù)數(shù);如果相等,則返回零;如果o1大于o2,該方法返回正數(shù),通常分別返回-1、0或1。

一個(gè)對(duì)象小于、等于或大于另一個(gè)對(duì)象意味著什么?

讓我們分析一下compare()方法返回的內(nèi)容,因?yàn)閷?duì)象的排序取決于此,重要的是要考慮該方法返回的含義是相對(duì)的,也就是說,如果您想要升序或降序排列。這取決于具體情況以及如何實(shí)施。讓我們?yōu)槊總€(gè)示例考慮以下記錄

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]
  • 如果第一個(gè)參數(shù)小于第二個(gè)參數(shù),則返回負(fù)數(shù)。例如,要按發(fā)行年份對(duì)電影進(jìn)行排序,當(dāng)電影 a 小于電影 b 時(shí),可以返回 -1:
int compare(T o1, T o2);
  • 如果第一個(gè)參數(shù)大于第二個(gè)參數(shù),則返回正數(shù)。例如,要按預(yù)算對(duì)電影進(jìn)行排序,當(dāng)電影 a 大于電影 b 時(shí),可以返回 1:
public record Movie(
        String name,
        List<String> actors,
        int budget,
        int year
) {
}
  • 如果第一個(gè)參數(shù)等于第二個(gè)參數(shù),則返回零。例如,要按演員數(shù)量對(duì)電影進(jìn)行排序,當(dāng)電影 a 等于電影 b 時(shí),可以返回 0:
// a < b -> -1
a.year() < b.year() -> -1

使用比較器

假設(shè)我們?cè)?List 類型的對(duì)象中有以下電影:

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

如果您想按發(fā)行年份升序排列電影,您可以創(chuàng)建一個(gè) Comparator 類型的對(duì)象并重寫compare()方法,然后將此對(duì)象傳遞給列表的sort()方法:

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

它也可以在 sort() 方法中實(shí)現(xiàn)為匿名類:

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 表達(dá)式:

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

movies.sort(comparatorByYear);

任何這些實(shí)現(xiàn)??都會(huì)按發(fā)布年份對(duì)列表進(jìn)行升序排序。如果要按降序排序,可以更改 lambda 表達(dá)式中參數(shù)的順序,或者在減法中添加負(fù)號(hào):

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

如何對(duì)自定義對(duì)象列表進(jìn)行排序的一些其他示例是:

  • 按演員數(shù)量升序排列電影(從少到多):
movies.sort((p1, p2) -> p1.year() - p2.year());
  • 按預(yù)算降序?qū)﹄娪斑M(jìn)行排序(從最高預(yù)算到最低預(yù)算):
movies.sort((p1, p2) -> p2.year() - p1.year());
// o
movies.sort((p1, p2) -> - (p1.year() - p2.year()));
  • 按名稱升序?qū)﹄娪斑M(jìn)行排序:
movies.sort((p1, p2) -> p1.actors().size() - p2.actors().size());

在其他示例中,我們可能會(huì)遇到需要按降序?qū)φ麛?shù)列表進(jìn)行排序的情況,

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

為此,您還可以使用靜態(tài)方法 Comparator.reverseOrder() 返回一個(gè)按降序?qū)υ剡M(jìn)行排序的比較器,以及使用 Comparator.naturalOrder() 按升序?qū)υ剡M(jìn)行排序。

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 中已經(jīng)有一些方法允許我們以有效的方式執(zhí)行這種類型的比較,例如 Integer.compare() ,它比較兩個(gè)整數(shù),如果第一個(gè)參數(shù)小于第二個(gè)參數(shù)零,則返回負(fù)數(shù)如果第一個(gè)參數(shù)大于第二個(gè)參數(shù),則相等且為正數(shù)。如果我們分析這個(gè)方法的工作原理,我們可以看到它與上面解釋的類似,并且返回的正是Comparator接口的compare()方法所需要的。 Integer.compare() 的實(shí)現(xiàn)如下:

int compare(T o1, T o2);

因此,如果您想按發(fā)行年份升序?qū)﹄娪斑M(jìn)行排序,可以使用 Integer.compare():

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

使用參考方法

有時(shí)可以使用引用方法來執(zhí)行與以前不同的比較,例如,按升序?qū)φ麛?shù)列表進(jìn)行排序:

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

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

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

回到電影的例子,如果你想按照上映年份升序?qū)﹄娪斑M(jìn)行排序,可以使用compareingInt()方法作為參考方法:

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

或者根據(jù) String 類型屬性進(jìn)行比較,在本例中為電影名稱:

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);

按多個(gè)屬性排序

有時(shí)你可能需要按多個(gè)屬性對(duì)對(duì)象列表進(jìn)行排序,例如,如果你想按發(fā)行年份升序?qū)﹄娪斑M(jìn)行排序,按預(yù)算降序排序,你可以使用 thenComparing() 方法,該方法接收一個(gè)比較器,負(fù)責(zé)按多個(gè)屬性排序。例如,如果有兩部電影a和b,上映年份相同,則按預(yù)算排序。

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

movies.sort(comparatorByYear);

結(jié)論

比較器在Java中很多時(shí)候都很有用,因?yàn)樗鼈兛梢宰屇阋詡€(gè)性化的方式比較對(duì)象,不僅如此,它們還可以用在許多Java集合方法中,甚至可以有多個(gè)比較器來排序以不同的方式。無論哪種方式,您都可以查閱 IDE 中的 Comparator 文檔或官方 Java 文檔,了解可以使用哪些方法以及如何實(shí)現(xiàn)它們。

以上是Java 中的比較器是如何工作的?的詳細(xì)內(nèi)容。更多信息請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)代碼編輯軟件(SublimeText3)

熱門話題

Laravel 教程
1597
29
PHP教程
1488
72
現(xiàn)代爪哇的異步編程技術(shù) 現(xiàn)代爪哇的異步編程技術(shù) Jul 07, 2025 am 02:24 AM

Java支持異步編程的方式包括使用CompletableFuture、響應(yīng)式流(如ProjectReactor)以及Java19 中的虛擬線程。1.CompletableFuture通過鏈?zhǔn)秸{(diào)用提升代碼可讀性和維護(hù)性,支持任務(wù)編排和異常處理;2.ProjectReactor提供Mono和Flux類型實(shí)現(xiàn)響應(yīng)式編程,具備背壓機(jī)制和豐富的操作符;3.虛擬線程減少并發(fā)成本,適用于I/O密集型任務(wù),與傳統(tǒng)平臺(tái)線程相比更輕量且易于擴(kuò)展。每種方式均有適用場景,應(yīng)根據(jù)需求選擇合適工具并避免混合模型以保持簡潔性

在Java中使用枚舉的最佳實(shí)踐 在Java中使用枚舉的最佳實(shí)踐 Jul 07, 2025 am 02:35 AM

在Java中,枚舉(enum)適合表示固定常量集合,最佳實(shí)踐包括:1.用enum表示固定狀態(tài)或選項(xiàng),提升類型安全和可讀性;2.為枚舉添加屬性和方法以增強(qiáng)靈活性,如定義字段、構(gòu)造函數(shù)、輔助方法等;3.使用EnumMap和EnumSet提高性能和類型安全性,因其基于數(shù)組實(shí)現(xiàn)更高效;4.避免濫用enum,如動(dòng)態(tài)值、頻繁變更或復(fù)雜邏輯場景應(yīng)使用其他方式替代。正確使用enum能提升代碼質(zhì)量并減少錯(cuò)誤,但需注意其適用邊界。

了解Java Nio及其優(yōu)勢 了解Java Nio及其優(yōu)勢 Jul 08, 2025 am 02:55 AM

JavaNIO是Java1.4引入的新型IOAPI,1)面向緩沖區(qū)和通道,2)包含Buffer、Channel和Selector核心組件,3)支持非阻塞模式,4)相比傳統(tǒng)IO更高效處理并發(fā)連接。其優(yōu)勢體現(xiàn)在:1)非阻塞IO減少線程開銷,2)Buffer提升數(shù)據(jù)傳輸效率,3)Selector實(shí)現(xiàn)多路復(fù)用,4)內(nèi)存映射加快文件讀寫。使用時(shí)需注意:1)Buffer的flip/clear操作易混淆,2)非阻塞下需手動(dòng)處理不完整數(shù)據(jù),3)Selector注冊(cè)需及時(shí)取消,4)NIO并非適用于所有場景。

Java Classloader在內(nèi)部如何工作 Java Classloader在內(nèi)部如何工作 Jul 06, 2025 am 02:53 AM

Java的類加載機(jī)制通過ClassLoader實(shí)現(xiàn),其核心工作流程分為加載、鏈接和初始化三個(gè)階段。加載階段由ClassLoader動(dòng)態(tài)讀取類的字節(jié)碼并創(chuàng)建Class對(duì)象;鏈接包括驗(yàn)證類的正確性、為靜態(tài)變量分配內(nèi)存及解析符號(hào)引用;初始化則執(zhí)行靜態(tài)代碼塊和靜態(tài)變量賦值。類加載采用雙親委派模型,優(yōu)先委托父類加載器查找類,依次嘗試Bootstrap、Extension和ApplicationClassLoader,確保核心類庫安全且避免重復(fù)加載。開發(fā)者可自定義ClassLoader,如URLClassL

有效處理常見的Java例外 有效處理常見的Java例外 Jul 05, 2025 am 02:35 AM

Java異常處理的關(guān)鍵在于區(qū)分checked和unchecked異常并合理使用try-catch、finally及日志記錄。1.checked異常如IOException需強(qiáng)制處理,適用于可預(yù)期的外部問題;2.unchecked異常如NullPointerException通常由程序邏輯錯(cuò)誤引起,屬于運(yùn)行時(shí)錯(cuò)誤;3.捕獲異常時(shí)應(yīng)具體明確,避免籠統(tǒng)捕獲Exception;4.推薦使用try-with-resources自動(dòng)關(guān)閉資源,減少手動(dòng)清理代碼;5.異常處理中應(yīng)結(jié)合日志框架記錄詳細(xì)信息,便于后

Hashmap在Java內(nèi)部如何工作? Hashmap在Java內(nèi)部如何工作? Jul 15, 2025 am 03:10 AM

HashMap在Java中通過哈希表實(shí)現(xiàn)鍵值對(duì)存儲(chǔ),其核心在于快速定位數(shù)據(jù)位置。1.首先使用鍵的hashCode()方法生成哈希值,并通過位運(yùn)算轉(zhuǎn)換為數(shù)組索引;2.不同對(duì)象可能產(chǎn)生相同哈希值,導(dǎo)致沖突,此時(shí)以鏈表形式掛載節(jié)點(diǎn),JDK8后鏈表過長(默認(rèn)長度8)則轉(zhuǎn)為紅黑樹提升效率;3.使用自定義類作鍵時(shí)必須重寫equals()和hashCode()方法;4.HashMap動(dòng)態(tài)擴(kuò)容,當(dāng)元素?cái)?shù)超過容量乘以負(fù)載因子(默認(rèn)0.75)時(shí),擴(kuò)容并重新哈希;5.HashMap非線程安全,多線程下應(yīng)使用Concu

解釋:面向?qū)ο蟮木幊讨械腏ava多態(tài)性 解釋:面向?qū)ο蟮木幊讨械腏ava多態(tài)性 Jul 05, 2025 am 02:52 AM

多態(tài)是Java面向?qū)ο缶幊痰暮诵奶匦灾?,其核心在于“一個(gè)接口,多種實(shí)現(xiàn)”,它通過繼承、方法重寫和向上轉(zhuǎn)型實(shí)現(xiàn)統(tǒng)一接口處理不同對(duì)象的行為。1.多態(tài)允許父類引用指向子類對(duì)象,運(yùn)行時(shí)根據(jù)實(shí)際對(duì)象調(diào)用對(duì)應(yīng)方法;2.實(shí)現(xiàn)需滿足繼承關(guān)系、方法重寫和向上轉(zhuǎn)型三個(gè)條件;3.常用于統(tǒng)一處理不同子類對(duì)象、集合存儲(chǔ)及框架設(shè)計(jì)中;4.使用時(shí)只能調(diào)用父類定義的方法,子類新增方法需向下轉(zhuǎn)型訪問,并注意類型安全。

有效使用爪哇枚舉和最佳實(shí)踐 有效使用爪哇枚舉和最佳實(shí)踐 Jul 07, 2025 am 02:43 AM

Java枚舉不僅表示常量,還可封裝行為、攜帶數(shù)據(jù)、實(shí)現(xiàn)接口。1.枚舉是類,用于定義固定實(shí)例,如星期、狀態(tài),比字符串或整數(shù)更安全;2.可攜帶數(shù)據(jù)和方法,如通過構(gòu)造函數(shù)傳值并提供訪問方法;3.可使用switch處理不同邏輯,結(jié)構(gòu)清晰;4.可實(shí)現(xiàn)接口或抽象方法,使不同枚舉值具有差異化行為;5.注意避免濫用、硬編碼比較、依賴ordinal值,合理命名與序列化。

See all articles