給歲月以文明,而不是給文明以歲月。——《三體》
在上一篇文章(傳送門)中介紹了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
方法,它的入參是ToIntFunction
;thenComparingLong
方法,它的入參是ToLongFunction
。
歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。
總結
默認方法名稱 | 作用 | 入參 | 入參簽名 |
---|---|---|---|
reversed | 逆序 | 無 | 無 |
thenComparing | 比較器鏈 | Function | (T) -> R |
thenComparingInt | 比較器鏈 | ToIntFunction | (T) -> int |
thenComparingLong | 比較器鏈 | ToLongFunction | (T) -> long |
thenComparingDouble | 比較器鏈 | ToDoubleFunction | (T) -> double |
《死磕Lambda表達式》系列
- 死磕Lambda表達式(一):初識Lambda
- 死磕Lambda表達式(二):Lambda的使用
- 死磕Lambda表達式(三):更簡潔的Lambda
- 死磕Lambda表達式(四):常用的函數式接口
- 死磕Lambda表達式(五):Comparator復合
- 死磕Lambda表達式(六):Consumer、Predicate、Function復合
微信公眾號:萬貓學社
微信掃描二維碼
獲得更多Java技術干貨
