Guava-Learning/src/main/java/ch01_basic/ordering at master · yxxcoder/Guava-Learning

排序器[Ordering]是Guava流畅风格比较器[Comparator]的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能

从实现上说,Ordering实例就是一个特殊的Comparator实例。Ordering把很多基于Comparator的静态方法(如Collections.max)包装为自己的实例方法(非静态方法),并且提供了链式调用方法,来定制和增强现有的比较器

1. 创建排序器

/**
 * 创建排序器
 * 常见的排序器可以由下面的静态方法创建
 */
public static void creationMethod(){

    // 对可排序类型做自然排序,如数字按大小,日期按先后排序
    Ordering<String> naturalOrdering = natural();
    // 按对象的字符串形式做字典排序
    Ordering<Object> usingToStringOrdering = usingToString();
    // 把给定的Comparator转化为排序器
    Ordering<String> fromOrdering = Ordering.from(new Comparator<String>() {
        public int compare(String o1, String o2) {
            return o1.hashCode() - o2.hashCode() ;
        }
    });
    // 直接继承Ordering
    Ordering<String> byLengthOrdering = new Ordering<String>() {
        public int compare(String left, String right) {
            return Ints.compare(left.length(), right.length());
        }
    };
}

2. 链式调用方法

通过链式调用,可以由给定的排序器衍生出其它排序器

/**
 * 链式调用方法
 * 通过链式调用,可以由给定的排序器衍生出其它排序器
 * 当阅读链式调用产生的排序器时,应该从后往前读,因为每次链式调用都是用后面的方法包装了前面的排序器
 * 用compound方法包装排序器时,不遵循从后往前读的原则
 */
public static void chainingMethod(){

    List<String> withNullList = Lists.newArrayList(list);
    withNullList.add(null);
    System.out.println("withNullList:"+ withNullList);
    
    List<List> listList = Lists.newArrayList();
    listList.add(Lists.newArrayList("perter", "jerry"));
    listList.add(Lists.newArrayList("perter"));
    listList.add(Lists.newArrayList("perter", "jerry", null));
    System.out.println("listList:"+ withNullList);
    
    // 对可排序类型做自然排序,如数字按大小,日期按先后排序
    Ordering<String> naturalOrdering = natural();
    // 获取语义相反的排序器
    Ordering<String> reverseOrdering = natural().reverse();
    // 使用当前排序器,但额外把null值排到最前面
    Ordering<String> nullsFirst = natural().nullsFirst();
    // 使用当前排序器,但额外把null值排到最后面
    Ordering<String> nullsLast = natural().nullsLast();
    // 合成另一个比较器,以处理当前排序器中的相等情况
    Ordering<People> secondaryOrdering = new PeopleAgeOrder().compound(new PeopleNameLengthOrder());
    // 返回该类型的可迭代对象Iterable<T>的排序器
    Ordering lexicographicalOrdering = naturalOrdering.lexicographical();
    // 对集合中元素调用Function,再按返回值用当前排序器排序
    Ordering<String> resultOfOrdering = natural().nullsFirst().onResultOf(new Function<String, Integer>() {
        public Integer apply(String input) {
            return input == null ? null : input.length();
        }
    });
}

3. 运用排序器

/**
 * 运用排序器
 * Guava的排序器实现有若干操纵集合或元素值的方法
 */
public static void applicationMethod() {

    // 获取可迭代对象中最大的k个元素
    System.out.println("greatestOfOrdering:"+ natural().greatestOf(list, 3));
    System.out.println("leastOfOrdering:"+ natural().leastOf(list, 3));

    // 判断可迭代对象是否已按排序器排序
    // 允许有排序值相等的元素
    System.out.println("isOrdered:"+ natural().isOrdered(natural().sortedCopy(list)));
    // 判断可迭代对象是否已严格按排序器排序
    // 不允许有排序值相等的元素
    System.out.println("isStrictlyOrdered:"+ natural().isStrictlyOrdered(natural().sortedCopy(list)));

    // 以列表形式返回指定元素的已排序副本
    System.out.println("isOrdered:"+ natural().sortedCopy(list));
    // 返回包含按此排序排序的元素的不可变列表
    natural().immutableSortedCopy(list);

    // 返回两个参数中最小的那个。如果相等,则返回第一个参数
    System.out.println("min:" + natural().min("abc", "ab"));
    // 返回两个参数中最大的那个。如果相等,则返回第一个参数
    System.out.println("max:" + natural().max("abc", "ab"));

    // 返回多个参数中最小的那个。如果有超过一个参数都最小,则返回第一个最小的参数
    System.out.println("min:" + natural().min("ab", "cd", "abc"));
    // 返回多个参数中最大的那个。如果有超过一个参数都最大,则返回第一个最大的参数
    System.out.println("max:" + natural().max("ab", "cde", "abc"));

    // 返回迭代器中最小的元素。如果可迭代对象中没有元素,则抛出NoSuchElementException
    System.out.println("min:" + natural().min(list));
    // 返回迭代器中最大的元素。如果可迭代对象中没有元素,则抛出NoSuchElementException
    System.out.println("max:" + natural().max(list));

}