Spring中如何使用Comparator接口

我们先来回顾下Comparator接口在我们日常开发中的作用,Comparator比较器接口可以将自身传递给排序方法(比如Collections.sort或Arrays.sort),以便对排序顺序进行精确控制。比如:

List<Integer> intList = Arrays.asList(2, 3, 1);
Collections.sort(intList, (o1, o2) -> {
   return o2-o1;
});

输出

[3, 2, 1]

Comparator可以用来控制某些数据结构(如sored sets 或sorted maps)的顺序,或者为没有自然顺序的对象集合提供顺序,比如:

public class Emp {
   private int empNo;
   private String eName;
   //省略getter setter
   @Override
   public String toString()
   {
      return "empno:\t"+empno+"\tename:\t"+ename;
   }
}
Comparator<Emp> comparator = (o1, o2) -> {
            return o1.getEmpno()-o2.getEmpno();
};
empList.sort(comparator);

从以上使用方法可以看出Comparator是策略模式的一个经典体现,在Spring中它为实现了Ordered接口的类写了一个比较器名叫OrderComparator,我们来看看它的compare方法:

@Override
public int compare(@Nullable Object o1, @Nullable Object o2) {
   return doCompare(o1, o2, null);
}
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
   //判断是否实现了PriorityOrdered接口
    //o1为原先的后一个元素
    //o2为原先的前一个元素
   boolean p1 = (o1 instanceof PriorityOrdered);
   boolean p2 = (o2 instanceof PriorityOrdered);
  //p1实现了PriorityOrdered,但是p2没实现PriorityOrdered,则p1优先级更高
   if (p1 && !p2) {
         ////小于0 表示逆序 o1排前
      return -1;
   }
   else if (p2 && !p1) {
     //p2实现了PriorityOrdered,但是p1没实现PriorityOrdered,则p2优先级更高
            //大于0 表示正序 o2排前
      return 1;
   }
   int i1 = getOrder(o1, sourceProvider);
   int i2 = getOrder(o2, sourceProvider);
   return Integer.compare(i1, i2);
}

    protected int getOrder(@Nullable Object obj) {
        if (obj != null) {
            Integer order = findOrder(obj);
            if (order != null) {
                return order;
            }
        }
    //Integer.MAX_VALUE代表最低优先级
        return Ordered.LOWEST_PRECEDENCE;
    }

    @Nullable
    protected Integer findOrder(Object obj) {
        return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
    }

OrderComparator主要是通过实现Order接口方法getOrder返回的值来比较的,而通过注解Order比较的话是采用继承OrderComparator类的AnnotationAwareOrderComparator类来重载getOrder方法来实现:

@Override
@Nullable
protected Integer findOrder(Object obj) {
   // Check for regular Ordered interface
   //检查常规的Order接口
   Integer order = super.findOrder(obj);
   if (order != null) {
      return order;
   }
     //检查@Order注解和@Priority注解
   // Check for @Order and @Priority on various kinds of elements
   if (obj instanceof Class) {
      return OrderUtils.getOrder((Class<?>) obj);
   }
   else if (obj instanceof Method) {
      Order ann = AnnotationUtils.findAnnotation((Method) obj, Order.class);
      if (ann != null) {
         return ann.value();
      }
   }
   else if (obj instanceof AnnotatedElement) {
      //AnnotatedElement代表在当前运行的java虚拟机中一个可以被注解的元素,这个接口允许通过反射读取元素上面的注解,这与我们之                前的理解是一致的
      //https://www.yuque.com/cuihualong/javaseries/sh91es
      Order ann = AnnotationUtils.getAnnotation((AnnotatedElement) obj, Order.class);
      if (ann != null) {
         return ann.value();
      }
   }
   else {
      order = OrderUtils.getOrder(obj.getClass());
      if (order == null && obj instanceof DecoratingProxy) {
         order = OrderUtils.getOrder(((DecoratingProxy) obj).getDecoratedClass());
      }
   }
   return order;
}

这里顺便提下在SpringBoot中ConditionalOnBean,ConditionalOnProperty,ConditionalOnClass等注解实际上都采用了实现Order注解的方法来进行排序。这里我就截个图看下了:

Conditional注解中的OnClassCondition类就标了@Order注解

实现Comparator接口compare方法的时候主要是要注意以下几点(翻译自官方文档):

用中文简单来说就是在 JDK7 版本以上默认使用Timsort排序方法来实现,Comparator 比较器要满足自反性,传递性,反对称性,不然 Arrays.sort,Collections.sort有可能会报 IllegalArgumentException 异常。

以上就是Spring中如何使用Comparator接口的详细内容,更多关于Spring 使用Comparator接口的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java基础之Comparable与Comparator概述

    自然排序Comparable 对于自定义类进行排序要实现Comparable接口,重写compareTo() 方法,如果不重写,像使用Arrays.sort()排序就会报错 package com.che.lambda; import java.util.Objects; /** * @author cheyuhang on 2021/4/23 */ public class Good implements Comparable{ private String name; private Dou

  • 详解JAVA使用Comparator接口实现自定义排序

    1.原则 Comparator接口可以实现自定义排序,实现Comparator接口时,要重写compare方法: int compare(Object o1, Object o2) 返回一个基本类型的整型 如果要按照升序排序,则o1 小于o2,返回-1(负数),相等返回0,01大于02返回1(正数) 如果要按照降序排序,则o1 小于o2,返回1(正数),相等返回0,01大于02返回-1(负数) import java.util.ArrayList; import java.util.Compar

  • Java 比较接口comparable与comparator区别解析

    这篇文章主要介绍了Java 比较接口comparable与comparator区别解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 package test0; import java.util.Comparator; //限定修饰符为friend不能为public,一个java文件中只能有一个public类 /*** * java程序是从一个public类的main函数开始执行的, *(其实是main线程),就像c程序是从main()函数开

  • Java集合排序规则接口Comparator用法解析

    1. 前言 最近用到了集合排序(基于 Java 8).现在我能用 Stream 的就用 Stream ,真香!排序可以这么写: List<People> peoples = new ArrayList<>(); // 中间省略 // 按照年龄从小到大排序 peoples.sort(Comparator.comparing(People::getAge)); 这里排序用到了一个关键接口 java.util.Comparator.排序比较作为业务中经常出现的需求,我们有必要研究一下这个

  • java优先队列PriorityQueue中Comparator的用法详解

    在使用java的优先队列PriorityQueue的时候,会看到这样的用法. PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>(){ @Override public int compare(Integer o1, Integer o2){ return o1.compareTo(o2); } }); 那这样到底构造的是最大优先还是最小优先队列呢? 看看源码

  • Java8 Comparator排序方法实例详解

    这篇文章主要介绍了Java8 Comparator排序方法实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Java8 中 Comparator 接口提供了一些静态方法,可以方便于我们进行排序操作,下面通过例子讲解下如何使用 对整数列表排序(升序) List<Integer> list = Arrays.asList(1, 4, 2, 6, 2, 8); list.sort(Comparator.naturalOrder()); Sys

  • Java8 Comparator: 列表排序的深入讲解

    在本文中,我们将看到几个关于如何在Java 8中对List进行排序的示例. 1.按字母顺序排序字符串列表 List<String> cities = Arrays.asList( "Milan", "london", "San Francisco", "Tokyo", "New Delhi" ); System.out.println(cities); //[Milan, london, San

  • Java Comparator比较器实例解析

    这篇文章主要介绍了Java Comparator比较器实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 说几点需要注意的,提醒自己即可: 以下是单独定义一个比较器的类,实现了Comparator中的compare方法.(要在Main方法外面定义类噢) 一定是compare而不是Compare哦 package xixixi; import java.util.*; public class Main { public static voi

  • Java Comparable和Comparator对比详解

    在实际项目开发过程中,我们经常需要对某个对象或者某个集合中的元素进行排序,常用的两种方式是实现某个接口.常见的可以实现比较功能的接口有Comparable接口和 Comparator接口,那么这两个又有什么区别呢? 关于Comparable接口 关于Comparable接口,其位于 java.lang.Comparable 中,实现这个接口,可以通过重写其 compareTo 方法进行自定义排序,一般用于实体类中,比如针对学生对象,根据其姓名.身高.年龄.地址等进行排序,商品根据名称.库存.价格

  • Java Comparable及Comparator接口区别详解

    在实际应用中,我们往往有需要比较两个自定义对象大小的地方.而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的.所以Java中要比较对象的大小或者要对对象的集合进行排序,需要通过比较这些对象的某些属性的大小来确定它们之间的大小关系. 一般,Java中通过接口实现两个对象的比较,比较常用就是Comparable接口和Comparator接口.首先类要实现接口,并且使用泛型规定要进行比较的对象所属的类,然后类实现了接口后,还需

随机推荐