排序器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)
接口