死磕Lambda表達式(五):Comparator復合


給歲月以文明,而不是給文明以歲月。——《三體》

在上一篇文章(傳送門)中介紹了JDK為我們提供的常用函數式接口,JDK不僅提供的這些函數式接口,其中一些接口還為我們提供了實用的默認方法,這次我們來介紹一下Comparator復合。

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。

Comparator的使用

在之前文章的例子中,我們使用Comparator.comparing靜態方法構建了一個Comparator接口的實例,我們再來簡單介紹一下。先來看一下Mask類是怎么寫的:

package one.more.study;

/**
 * 口罩
 * @author 萬貓學社
 */
public class Mask {
    public Mask() {
    }
    
    public Mask(String brand, String type, double price) {
        this.brand = brand;
        this.type = type;
        this.price = price;
    }

    /**
     * 品牌
     */
    private String brand;
    /**
     * 類型
     */
    private String type;
    /**
     * 價格
     */
    private double price;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Mask{" +
                "brand='" + brand + '\'' +
                ", type='" + type + '\'' +
                ", price=" + price +
                '}';
    }
}

然后,根據口罩品牌對口罩列表進行正序排序:

List<Mask> maskList = new ArrayList<>();
maskList.add(new Mask("3M", "KN95",17.8));
maskList.add(new Mask("Honeywell", "KN95",18.8));
maskList.add(new Mask("3M", "FFP2",19.8));
maskList.add(new Mask("Honeywell", "N95",19.5));
maskList.sort(Comparator.comparing(Mask::getBrand));
for (Mask mask : maskList) {
    System.out.println(mask);
}

運行結果如下:

Mask{brand='3M', type='KN95', price=17.8}
Mask{brand='3M', type='FFP2', price=19.8}
Mask{brand='Honeywell', type='KN95', price=18.8}
Mask{brand='Honeywell', type='N95', price=19.5}

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。

逆序

需求改了,要求按照口罩品牌進行逆序排列,這是還需不需要再構建一個Comparator接口的實例呢?答案是不需要,Comparator接口有一個默認方法reversed可以使其逆序,把上面的例子稍微修改一下:

maskList.sort(Comparator.comparing(Mask::getBrand).reversed());

運行結果如下:

Mask{brand='Honeywell', type='KN95', price=18.8}
Mask{brand='Honeywell', type='N95', price=19.5}
Mask{brand='3M', type='KN95', price=17.8}
Mask{brand='3M', type='FFP2', price=19.8}

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。

比較器鏈

需求又改了,先按照口罩品牌逆序排序,如果口罩品牌一樣,再按照口罩類型正序排序。Comparator接口還有一個默認方法thenComparing就是做這個的,它的入參也是一個Function接口的實例,如果前一個比較器的比較結果相同,就當前的比較器再進行比較,我們再來修改一下上面的例子:

maskList.sort(Comparator.comparing(Mask::getBrand)
        .reversed()
        .thenComparing(Mask::getType));

運行結果如下:

Mask{brand='Honeywell', type='KN95', price=18.8}
Mask{brand='Honeywell', type='N95', price=19.5}
Mask{brand='3M', type='FFP2', price=19.8}
Mask{brand='3M', type='KN95', price=17.8}

需求又又改了,先按照口罩品牌逆序排序,如果口罩品牌一樣,再按照口罩價格正序排序。口罩價格是double類型,如果使用thenComparing會導致自動裝箱,造成資源的白白浪費。所以,推薦使用thenComparingDouble方法,它的入參是ToDoubleFunction,代碼修改如下:

maskList.sort(Comparator.comparing(Mask::getBrand)
        .reversed()
        .thenComparingDouble(Mask::getPrice));

運行結果如下:

Mask{brand='Honeywell', type='KN95', price=18.8}
Mask{brand='Honeywell', type='N95', price=19.5}
Mask{brand='3M', type='KN95', price=17.8}
Mask{brand='3M', type='FFP2', price=19.8}

類似這樣支持基礎數據類型的方法還有兩個:thenComparingInt方法,它的入參是ToIntFunctionthenComparingLong方法,它的入參是ToLongFunction

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。

總結

默認方法名稱 作用 入參 入參簽名
reversed 逆序
thenComparing 比較器鏈 Function (T) -> R
thenComparingInt 比較器鏈 ToIntFunction (T) -> int
thenComparingLong 比較器鏈 ToLongFunction (T) -> long
thenComparingDouble 比較器鏈 ToDoubleFunction (T) -> double

《死磕Lambda表達式》系列

微信公眾號:萬貓學社

微信掃描二維碼

獲得更多Java技術干貨


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM