排序器Ordering是Guava流暢風格比較器Comparator的實現,它能夠用來爲構建複雜的比較器,以完成集合排序的功能。java
從實現上說,Ordering 實例就是一個特殊的 Comparator 實例。Ordering把不少基於Comparator 的靜態方法(如 Collections.max)包裝爲本身的實例方法(非靜態方法),而且提供了鏈式調用方法,來定製和加強現有的比較器。算法
比較器指的是集合存儲的元素的特性,若是元素是可比較的則能夠進行相應的排序,不然不行。可是在Java中有Comparable接口和Comparator接口,具體有什麼區別呢?app
對於Comparable接口來講,它每每是進行比較類須要實現的接口,它僅包含一個有compareTo()方法,只有一個參數,返回值爲int,返回值大於0表示對象大於參數對象;小於0表示對象小於參數對象;等於0表示二者相等。ide
Ordering類的聲明:google
@GwtCompatible public abstract class Ordering<T> extends Object implements Comparator<T>
方法類型 | 方法名 | 描述 |
---|---|---|
Ordering<Object> | natural() | 對可排序類型作天然排序,如數字按大小,日期按前後排序 |
按對象的字符串形式作字典排序[lexicographical ordering] | usingToString() | 返回由它們的字符串表示的天然順序,toString()比較對象進行排序。 |
Ordering<Object> | arbitrary() | 返回一個任意順序對全部對象,其中compare(a, b) == 0 意味着a == b(身份平等)。 |
Ordering<Object> | allEqual() | 返回一個排序,它把全部的值相等,說明「沒有順序。」經過這個順序以任何穩定的排序算法的結果,在改變沒有順序元素。 |
Ordering<T> | explicit(List<T> valuesInOrder) | 返回根據它們出現的定列表中的順序比較對象進行排序。 |
Ordering<T> | explicit(T leastValue, T... remainingValuesInOrder) | 返回根據它們所賦予本方法的順序進行比較的對象進行排序。 |
Ordering<U> | compound(Comparator<? super U> secondaryComparator) | 返回首先使用排序這一點,但它排序中的「tie」,而後委託給secondaryComparator事件。 |
Ordering<U> | compound(Iterable<? extends Comparator<? super T>> comparators) | 返回一個排序它嘗試每一個給定的比較器,以便直到一個非零結果找到,返回該結果,並返回零僅當全部比較器返回零。 |
Ordering<T> | from(Comparator<T> comparator) | 返回基於現有的比較實例進行排序。 |
Ordering<T> | from(Ordering<T> ordering) | 已取消使用 |
方法比較多,大概有40多個,這裏只提出幾個比較經常使用的。code
方法類型 | 方法名 | 描述 |
---|---|---|
Ordering<S> | reverse() | 獲取語義相反的排序器 |
Ordering<S> | nullsFirst() | 使用當前排序器,但額外把 null 值排到最前面。 |
Ordering<S> | nullsLast() | 使用當前排序器,但額外把 null 值排到最後面。 |
Ordering<U> | compound(Comparator) | 合成另外一個比較器,以處理當前排序器中的相等狀況。 |
Ordering<Iterable<S>> | lexicographical() | 基於處理類型 T 的排序器,返回該類型的可迭代對象 Iterable<T>的排序器。 |
Ordering<F> | onResultOf(Function) | 對集合中元素調用 Function,再按返回值用當前排序器排序。 |
實現自定義的排序器時,除了用上面的 from 方法,也能夠跳過實現 Comparator,而直接繼承 Ordering:對象
Ordering<String> byLengthOrdering = new Ordering<String>() { public int compare(String left, String right) { return Ints.compare(left.length(), right.length()); } };
import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.google.common.collect.Ordering; public class Guava { public static void main(String[] args) { List<Integer> numbers = new ArrayList<Integer>(); numbers.add(new Integer(5)); numbers.add(new Integer(2)); numbers.add(new Integer(15)); numbers.add(new Integer(51)); numbers.add(new Integer(53)); numbers.add(new Integer(35)); numbers.add(new Integer(45)); numbers.add(new Integer(32)); numbers.add(new Integer(43)); numbers.add(new Integer(16)); Ordering ordering = Ordering.natural(); System.out.println("Input List: "); System.out.println(numbers); /** * Input List: * [5, 2, 15, 51, 53, 35, 45, 32, 43, 16] * */ Collections.sort(numbers, ordering); System.out.println("Sorted List: "); System.out.println(numbers); /** *Sorted List: * [2, 5, 15, 16, 32, 35, 43, 45, 51, 53] * */ System.out.println("======================"); System.out.println("List is sorted: " + ordering.isOrdered(numbers)); // 根據此順序返回指定值中的最小值。若是有多個最小值,則返回第一個最小值。 System.out.println("Minimum: " + ordering.min(numbers)); // 根據這個順序返回指定值中的最大值。若是有多個最大值,則返回第一個值。 System.out.println("Maximum: " + ordering.max(numbers)); /** * List is sorted: true * Minimum: 2 * Maximum: 53 * */ Collections.sort(numbers, ordering.reverse()); System.out.println("Reverse: " + numbers); /** * Reverse: [53, 51, 45, 43, 35, 32, 16, 15, 5, 2] * */ numbers.add(null); System.out.println("Null added to Sorted List: "); System.out.println(numbers); /** * Null added to Sorted List: *[53, 51, 45, 43, 35, 32, 16, 15, 5, 2, null] * */ Collections.sort(numbers, ordering.nullsFirst()); System.out.println("Null first Sorted List: "); System.out.println(numbers); /** * Null first Sorted List: *[null, 2, 5, 15, 16, 32, 35, 43, 45, 51, 53] * */ System.out.println("======================"); List<String> names = new ArrayList<String>(); names.add("Ram"); names.add("Shyam"); names.add("Mohan"); names.add("Sohan"); names.add("Ramesh"); names.add("Suresh"); names.add("Naresh"); names.add("Mahesh"); names.add(null); names.add("Vikas"); names.add("Deepak"); System.out.println("Another List: "); System.out.println(names); /** * Another List: *[Ram, Shyam, Mohan, Sohan, Ramesh, Suresh, Naresh, Mahesh, null, Vikas, Deepak] * */ /** * 若是有null也加入排序計算 * Collections類中的sort方法能夠對實現了List接口的集合進行排序。這個方法假定列表元素實現了Comparable接口。 * */ Collections.sort(names, ordering.nullsFirst().reverse()); System.out.println("Null first then reverse sorted list: "); System.out.println(names); /** * Null first then reverse sorted list: *[Vikas, Suresh, Sohan, Shyam, Ramesh, Ram, Naresh, Mohan, Mahesh, Deepak, null] * */ }
import java.util.ArrayList; import java.util.List; import com.google.common.base.Function; import com.google.common.base.MoreObjects; import com.google.common.collect.Lists; import com.google.common.collect.Ordering; public class Guava { public static void main(String[] args) { List<People> peopleList = new ArrayList<People>() {{ add(new People("A", 33)); add(new People("B", 11)); add(new People("C", 18)); }}; List<People> po = Lists.newArrayList(); po.addAll(peopleList); Ordering<People> ordering = Ordering.natural().onResultOf(new Function<People, Comparable>() { @Override public Comparable apply(People people) { // 此處能夠根據集合中的參數排序 return people.getAge(); } }); for (People p : ordering.reverse().sortedCopy(po)) { System.out.println(MoreObjects.toStringHelper(p) .add("name", p.getName()) .add("age", p.getAge()) ); } } }
結果 People{name=A, age=33} People{name=C, age=18} People{name=B, age=11}
import java.util.ArrayList; import java.util.List; import com.google.common.base.Function; import com.google.common.base.MoreObjects; import com.google.common.collect.Lists; import com.google.common.collect.Ordering; public class Guava { public static void main(String[] args) { List<People> peopleList = new ArrayList<People>() {{ add(new People("A", 33)); add(new People("B", 11)); add(new People("C", 18)); }}; List<People> po = Lists.newArrayList(); po.addAll(peopleList); Ordering<People> ordering = Ordering.usingToString().reverse().onResultOf(new Function<People, Comparable>() { @Override public Comparable apply(People people) { return people.getName(); } }); for (People p : ordering.sortedCopy(peopleList)) { System.out.println(MoreObjects.toStringHelper(p) .add("name", p.getName()) .add("age", p.getAge()) ); } } }
結果: People{name=C, age=18} People{name=B, age=11} People{name=A, age=33}
當閱讀鏈式調用產生的排序器時,應該從後往前讀。上面的例子中,排序器首先調用 apply 方法獲取 people 值,並把剩下的元素按 people 進行排序。之因此要從後往前讀,是由於每次鏈式調用都是用後面的方法包裝了前面的排序器。排序
注:用 compound 方法包裝排序器時,就不該遵循從後往前讀的原則。爲了不理解上的混亂,請不要把 com pound 寫在一長串鏈式調用的中間,你能夠另起一行,在鏈中最早或最後調用 compound。超過必定長度的鏈式調用,也可能會帶來閱讀和理解上的難度。咱們建議按下面的代碼這樣,在一個鏈中最多使用三個方法。此外,你也能夠把 Function 分離成中間對象,讓鏈式調用更簡潔緊湊。繼承
Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(sortKeyFunction)
接口