鍍金池/ 教程/ Java/ 排序: Guava 強大的”流暢風(fēng)格比較器”
不可變集合
排序: Guava 強大的”流暢風(fēng)格比較器”
強大的集合工具類:java.util.Collections 中未包含的集合工具
新集合類型
常見 Object 方法
I/O
前置條件
字符串處理:分割,連接,填充
散列
原生類型
數(shù)學(xué)運算
使用和避免 null
Throwables:簡化異常和錯誤的傳播與檢查
google Guava 包的 ListenableFuture 解析
事件總線
緩存
函數(shù)式編程
區(qū)間
集合擴展工具類
Google-Guava Concurrent 包里的 Service 框架淺析
google Guava 包的 reflection 解析

排序: Guava 強大的”流暢風(fēng)格比較器”

排序器[Ordering]是 Guava 流暢風(fēng)格比較器[Comparator]的實現(xiàn),它可以用來為構(gòu)建復(fù)雜的比較器,以完成集合排序的功能。

從實現(xiàn)上說,Ordering 實例就是一個特殊的 Comparator 實例。Ordering 把很多基于 Comparator 的靜態(tài)方法(如 Collections.max)包裝為自己的實例方法(非靜態(tài)方法),并且提供了鏈式調(diào)用方法,來定制和增強現(xiàn)有的比較器。

創(chuàng)建排序器:常見的排序器可以由下面的靜態(tài)方法創(chuàng)建

方法 描述
natural() 對可排序類型做自然排序,如數(shù)字按大小,日期按先后排序
usingToString() 按對象的字符串形式做字典排序[lexicographical ordering]
from(Comparator) 把給定的 Comparator 轉(zhuǎn)化為排序器

實現(xiàn)自定義的排序器時,除了用上面的 from 方法,也可以跳過實現(xiàn) Comparator,而直接繼承 Ordering:


    Ordering<String> byLengthOrdering = new Ordering<String>() {
      public int compare(String left, String right) {
        return Ints.compare(left.length(), right.length());
      }
    };

鏈式調(diào)用方法:通過鏈式調(diào)用,可以由給定的排序器衍生出其它排序器

方法 描述
reverse() 獲取語義相反的排序器
nullsFirst() 使用當(dāng)前排序器,但額外把 null 值排到最前面。
nullsLast() 使用當(dāng)前排序器,但額外把 null 值排到最后面。
compound(Comparator) 合成另一個比較器,以處理當(dāng)前排序器中的相等情況。
lexicographical() 基于處理類型 T 的排序器,返回該類型的可迭代對象 Iterable<T>的排序器。
onResultOf(Function) 對集合中元素調(diào)用 Function,再按返回值用當(dāng)前排序器排序。

例如,你需要下面這個類的排序器。


    class Foo {
        @Nullable String sortedBy;
        int notSortedBy;
    }

考慮到排序器應(yīng)該能處理 sortedBy 為 null 的情況,我們可以使用下面的鏈式調(diào)用來合成排序器:


    Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(new Function<Foo, String>() {
      public String apply(Foo foo) {
        return foo.sortedBy;
      }
    });

當(dāng)閱讀鏈式調(diào)用產(chǎn)生的排序器時,應(yīng)該從后往前讀。上面的例子中,排序器首先調(diào)用 apply 方法獲取 sortedBy 值,并把 sortedBy 為 null 的元素都放到最前面,然后把剩下的元素按 sortedBy 進行自然排序。之所以要從后往前讀,是因為每次鏈式調(diào)用都是用后面的方法包裝了前面的排序器。

注:用 compound 方法包裝排序器時,就不應(yīng)遵循從后往前讀的原則。為了避免理解上的混亂,請不要把 compound 寫在一長串鏈式調(diào)用的中間,你可以另起一行,在鏈中最先或最后調(diào)用 compound。

超過一定長度的鏈式調(diào)用,也可能會帶來閱讀和理解上的難度。我們建議按下面的代碼這樣,在一個鏈中最多使用三個方法。此外,你也可以把 Function 分離成中間對象,讓鏈式調(diào)用更簡潔緊湊。


    Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(sortKeyFunction)

運用排序器:Guava 的排序器實現(xiàn)有若干操縱集合或元素值的方法

方法 描述 另請參見
greatestOf(Iterable iterable, int k) 獲取可迭代對象中最大的k個元素。 leastOf
isOrdered(Iterable) 判斷可迭代對象是否已按排序器排序:允許有排序值相等的元素。 isStrictlyOrdered
sortedCopy(Iterable) 判斷可迭代對象是否已嚴格按排序器排序:不允許排序值相等的元素。 immutableSortedCopy
min(E, E) 返回兩個參數(shù)中最小的那個。如果相等,則返回第一個參數(shù)。 max(E, E)
min(E, E, E, E...) 返回多個參數(shù)中最小的那個。如果有超過一個參數(shù)都最小,則返回第一個最小的參數(shù)。 max(E, E, E, E...)
min(Iterable) 返回迭代器中最小的元素。如果可迭代對象中沒有元素,則拋出 NoSuchElementException。 max(Iterable), min(Iterator), max(Iterator)