Spring中如何使用Comparator接口

 更新时间:2021年06月22日 11:35:41   作者:沉迷Spring  
Comparator比较器接口可以将自身传递给排序方法(比如Collections.sort或Arrays.sort),以便对排序顺序进行精确控制。本文讲述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接口的资料请关注脚本之家其它相关文章!

相关文章

  • java中的反射及其优点说明

    java中的反射及其优点说明

    这篇文章主要介绍了java中的反射及其优点说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • Mybatis(ParameterType)传递多个不同类型的参数方式

    Mybatis(ParameterType)传递多个不同类型的参数方式

    这篇文章主要介绍了Mybatis(ParameterType)传递多个不同类型的参数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • Spring中@Configuration和@Component注解的区别及原理

    Spring中@Configuration和@Component注解的区别及原理

    这篇文章主要介绍了Spring中@Configuration和@Component注解的区别及原理,从功能上来讲,这些注解所负责的功能的确不相同,但是从本质上来讲,Spring内部都将其作为配置注解进行处理,需要的朋友可以参考下
    2023-11-11
  • MyBatis一对一级联更新问题小结

    MyBatis一对一级联更新问题小结

    日常工作中经常会涉及到一对一级联更新的问题,本文主要介绍了MyBatis一对一级联更新问题小结,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • springboot整合mail实现邮箱的发送功能

    springboot整合mail实现邮箱的发送功能

    本文分步骤给大家介绍springboot整合mail实现邮箱的发送功能,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-09-09
  • Java使用Swing实现一个模拟电脑计算器

    Java使用Swing实现一个模拟电脑计算器

    Java Swing 是一个用于创建 Java GUI(图形用户界面)的框架,它提供了一系列的 GUI 组件和工具,可以用于创建桌面应用程序,包括按钮、文本框、标签、表格等等,本文给大家介绍了Java使用Swing实现一个模拟计算器,感兴趣的同学可以自己动手尝试一下
    2024-05-05
  • SpringDataJPA实体类关系映射配置方式

    SpringDataJPA实体类关系映射配置方式

    这篇文章主要介绍了SpringDataJPA实体类关系映射配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Java设计模式之代理模式与装饰模式实例详解

    Java设计模式之代理模式与装饰模式实例详解

    这篇文章主要介绍了Java设计模式之代理模式与装饰模式,结合具体实例形式分析了代理模式与装饰模式的概念、功能、java实现方法与相关使用注意事项,需要的朋友可以参考下
    2017-09-09
  • Netty的心跳检测解析

    Netty的心跳检测解析

    这篇文章主要介绍了Netty的心跳检测解析,客户端的心跳检测对于任何长连接的应用来说,都是一个非常基础的功能,要理解心跳的重要性,首先需要从网络连接假死的现象说起,需要的朋友可以参考下
    2023-12-12
  • java: 程序包com.fasterxml.jackson.annotation不存在的解决办法

    java: 程序包com.fasterxml.jackson.annotation不存在的解决办法

    当我们在导入程序之后,系统给出错误提示:java: 程序包com.fasterxml.jackson.annotation不存在,本文主要介绍了Java程序包不存在的三种解决方法,需要的朋友可以参考下
    2024-02-02

最新评论