Java 集合排序策略接口 Comparator

1. 前言

最近用到了集合排序(基于 Java 8)“战剑現(xiàn)在我能用 Stream 的就用 Stream 欣范,真香掠河!排序可以這么寫:

List<People> peoples = new ArrayList<>();
  // 中間省略
  // 按照年齡從小到大排序
peoples.sort(Comparator.comparing(People::getAge));

這里排序用到了一個關(guān)鍵接口 java.util.Comparator栈虚。排序比較作為業(yè)務(wù)中經(jīng)常出現(xiàn)的需求,我們有必要研究一下這個接口汁掠。

2. Comparator 概念

Comparator 是一個函數(shù)式接口略吨。它經(jīng)常用于沒有天然排序的集合進行排序,如 Collections.sortArrays.sort考阱〈渲遥或者對于某些有序數(shù)據(jù)結(jié)構(gòu)的排序規(guī)則進行聲明,如 TreeSet 乞榨、TreeMap 秽之。也就是該接口主要用來進行集合排序。

3. Comparator 中的方法

Comparator 作為一個函數(shù)式接口只有一個抽象方法,但是它有很多的默認(rèn)方法吃既,我們來認(rèn)識一下這些方法們考榨。

3.1 compare 抽象方法

作為Comparator 唯一的抽象方法,int compare(T o1,T o2) 比較兩個參數(shù)的大小鹦倚, 返回負(fù)整數(shù)河质,零,正整數(shù) 申鱼,分別代表 o1<o2愤诱、o1=o2o1>o2捐友,通常分別返回 -1淫半、01。偽表達式:

// 輸入兩個同類型的對象 匣砖,輸出一個比較結(jié)果的int數(shù)字
(x1,x2)-> int

實現(xiàn)該方法一定要注意以下事項:

  • 必須保證compare(x,y)compare(y,x) 的值的和必須為 0 科吭。
  • 必須保證比較的順序關(guān)系是可傳遞的,如果compare(x,y)>0 而且compare(y,z)>0compare(x,z)>0猴鲫。
  • 如果存在 compare(x,y)=0对人,則對于 z 而言,存在 compare(x, z)==compare(y, z)拂共。

然而并不 嚴(yán)格要求(compare(x, y)==0) == (x.equals(y))牺弄。一般說來,任何違背這個條件的 Comparator 實現(xiàn)都應(yīng)該明確指出這一事實情況宜狐。

3.2 comparing 系列方法

Java 8 開始势告,Comparator 提供了一系列的靜態(tài)方法,并通過函數(shù)式的風(fēng)格賦予 Comparator 更加強大和方便的功能抚恒,我們暫且稱它們?yōu)?comparing系列方法咱台。

   public static <T, U> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator)
    {
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2));
    }

該方法是該系列方法的基本方法。是不是看上去很難懂的樣子俭驮?我們來分析一下該方法回溺。它一共兩個參數(shù)都是函數(shù)式接口。

第一個參數(shù) Function<? super T, ? extends U> keyExtractor 表示輸入一個是 T 類型對象,輸出一個 U 類型的對象遗遵,舉個例子萍恕,輸入一個 People 對象返回其年齡 Integer 數(shù)值:

//   people -> people.getAge(); 轉(zhuǎn)換為下面方法引用
Function<People, Integer> getAge = People::getAge;

第二個參數(shù) keyComparator就很好理解了,表示使用的比較規(guī)則瓮恭。

c1,c2 按照 第一個參數(shù) keyExtractor 提供的規(guī)則進行提取特征雄坪,然后第二個參數(shù)keyComparator對這兩個特征進行比較。下面的式子其實可以概括為 3.1(x1,x2)-> int

(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2))

Comparator<T> & Serializable 為 Java 8 新特性:同時滿足這兩個類型約束

理解了這個方法后屯蹦,其它該系列的方法就好理解了,這里不再贅述绳姨。目前 comparing 系列方法使用更加廣泛登澜。我們舉一些例子:

List<People> peoples = new ArrayList<>();
//  ………………
// 按照年齡從低到高排序
peoples.sort(Comparator.comparing(People::getAge));
// 按照年齡從高到低排序
peoples.sort(Comparator.comparing(People::getAge, (x, y) -> -x.compareTo(y)));

同樣你可以使用 java.util.Collections 或者 Stream 提供的排序方法來使用Comparator

4. 小結(jié)

今天對 Comparator進行了簡單的分析飘庄,它用于構(gòu)建集合排序的規(guī)則脑蠕,在日常開發(fā)中非常有用。下一篇 我們將對另一個和它十分相似的接口 Comparable 進行分析和比較它們的不同跪削,敬請關(guān)注谴仙。

關(guān)注公眾號:碼農(nóng)小胖哥,獲取更多資訊

個人博客:https://felord.cn

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碾盐,一起剝皮案震驚了整個濱河市晃跺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毫玖,老刑警劉巖掀虎,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異付枫,居然都是意外死亡烹玉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門阐滩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來二打,“玉大人,你說我怎么就攤上這事掂榔〖绦В” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵衅疙,是天一觀的道長莲趣。 經(jīng)常有香客問我,道長饱溢,這世上最難降的妖魔是什么喧伞? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上潘鲫,老公的妹妹穿的比我還像新娘翁逞。我一直安慰自己,他們只是感情好溉仑,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布挖函。 她就那樣靜靜地躺著,像睡著了一般浊竟。 火紅的嫁衣襯著肌膚如雪怨喘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天振定,我揣著相機與錄音必怜,去河邊找鬼。 笑死后频,一個胖子當(dāng)著我的面吹牛梳庆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卑惜,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼膏执,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了露久?” 一聲冷哼從身側(cè)響起更米,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎抱环,沒想到半個月后壳快,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡镇草,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年眶痰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梯啤。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡竖伯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出因宇,到底是詐尸還是另有隱情七婴,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布察滑,位于F島的核電站打厘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏贺辰。R本人自食惡果不足惜户盯,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一嵌施、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧莽鸭,春花似錦吗伤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至礁阁,卻和暖如春巧号,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背氮兵。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工裂逐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人泣栈。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像弥姻,于是被迫代替她去往敵國和親南片。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354