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.sort
或 Arrays.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=o2
、o1>o2
捐友,通常分別返回 -1
淫半、0
或 1
。偽表達式:
// 輸入兩個同類型的對象 匣砖,輸出一個比較結(jié)果的int數(shù)字
(x1,x2)-> int
實現(xiàn)該方法一定要注意以下事項:
- 必須保證
compare(x,y)
和compare(y,x)
的值的和必須為 0 科吭。 - 必須保證比較的順序關(guān)系是可傳遞的,如果
compare(x,y)>0
而且compare(y,z)>0
則compare(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)小胖哥,獲取更多資訊