关于Comparator使用说明

1. 源码分析

1.1 介绍

@FunctionalInterface
public interface Comparator
比较功能,对一些对象的集合施加了一个整体排序 。 可以将比较器传递给排序方法(如Collections.sortArrays.sort ),以便对排序顺序进行精确控制。 比较器还可以用来控制某些数据结构(如顺序sorted sets或sorted maps ),或对于不具有对象的集合提供的排序natural ordering 。
通过比较c上的一组元素S的确定的顺序对被认为是与equals一致当且仅当c.compare(e1, e2)==0具有用于S每e1和e2相同布尔值e1.equals(e2)。
当使用能够强制排序不一致的比较器时,应注意使用排序集(或排序图)。 假设具有显式比较器c的排序集(或排序映射)与从集合S中绘制的元素(或键) 一起使用 。 如果88446235254451上的c强制的排序与equals不一致,则排序集(或排序映射)将表现为“奇怪”。 特别是排序集(或排序图)将违反用于设置(或映射)的一般合同,其按equals定义。
例如,假设一个将两个元件a和b ,使得(a.equals(b) && c.compare(a, b) != 0)到空TreeSet与比较c 。 因为a和b与树集的角度不相等,所以第二个add操作将返回true(并且树集的大小将增加),即使这与Set.add方法的规范相反。
注意:这通常是一个好主意比较,也能实现java.io.Serializable,因为它们可能被用来作为排序的序列化数据结构的方法(如TreeSet , TreeMap )。 为了使数据结构成功序列化,比较器(如果提供)必须实现Serializable 。
对于数学上的倾斜,即限定了施加顺序 ,给定的比较器c上一组给定对象的S强加关系式为:
{(x, y) such that c.compare(x, y) <= 0}.
这个总订单的商是:
{(x, y) such that c.compare(x, y) == 0}.
它从合同compare,该商数是S的等价关系紧随其后,而强加的排序是S, 总订单 。 当我们说S上的c所规定的顺序与等于一致时,我们的意思是排序的商是由对象equals(Object)方法定义的等价关系:
{(x, y) such that x.equals(y)}.
与Comparable不同,比较器可以可选地允许比较空参数,同时保持对等价关系的要求。
关于Comparator使用说明_第1张图片

1.2 方法

关于Comparator使用说明_第2张图片
关于Comparator使用说明_第3张图片

1.2.1

2. 简单应用

        List<UserVO> list = new ArrayList<>();

        //返回 对象集合以类属性一升序排序
        list.stream().sorted(Comparator.comparing(UserVO::getLoginTime));

        //返回 对象集合以类属性一降序排序 注意两种写法
        //先以属性一升序,结果进行属性一降序
        list.stream().sorted(Comparator.comparing(UserVO::getLoginTime).reversed());

        //以属性一降序
        list.stream().sorted(Comparator.comparing(UserVO::getLoginTime,Comparator.reverseOrder()));

        //返回 对象集合以类属性一升序 属性二升序
        list.stream().sorted(Comparator.comparing(UserVO::getLoginTime).thenComparing(UserVO::getRegTime));

        //返回 对象集合以类属性一降序 属性二升序 注意两种写法
        //先以属性一升序,升序结果进行属性一降序,再进行属性二升序
        list.stream().sorted(Comparator.comparing(UserVO::getLoginTime).reversed().thenComparing(UserVO::getRegTime));

        //先以属性一降序,再进行属性二升序
        list.stream().sorted(Comparator.comparing(UserVO::getLoginTime,Comparator.reverseOrder()).thenComparing(UserVO::getRegTime));

        //返回 对象集合以类属性一降序 属性二降序 注意两种写法
        //先以属性一升序,升序结果进行属性一降序,再进行属性二降序
        list.stream().sorted(Comparator.comparing(UserVO::getLoginTime).reversed().thenComparing(UserVO::getRegTime,Comparator.reverseOrder()));

        //先以属性一降序,再进行属性二降序
        list.stream().sorted(Comparator.comparing(UserVO::getLoginTime,Comparator.reverseOrder()).thenComparing(UserVO::getRegTime,Comparator.reverseOrder()));

        //返回 对象集合以类属性一升序 属性二降序 注意两种写法
        //先以属性一升序,升序结果进行属性一降序,再进行属性二升序,结果进行属性一降序属性二降序
        list.stream().sorted(Comparator.comparing(UserVO::getLoginTime).reversed().thenComparing(UserVO::getRegTime).reversed());

        //先以属性一升序,再进行属性二降序
        list.stream().sorted(Comparator.comparing(UserVO::getLoginTime).thenComparing(UserVO::getRegTime,Comparator.reverseOrder()));

通过以上例子我们可以发现,两种排序是完全不一样的,,一定要区分开来,2更好理解,建议使用2

  1. Comparator.comparing(类::属性一).reversed(); 是得到排序结果后再排序
  2. Comparator.comparing(类::属性一,Comparator.reverseOrder()); 是直接进行排序,很多人会混淆导致理解出错

注意

1. 空值排序Comparator.nullsLast()Comparator.nullsFirst()

nullsFirst排序后,空值在后,非空在前,nullsLast排序后,空值在前,非空值在后
关于Comparator使用说明_第4张图片

你可能感兴趣的:(java进阶,comparator)