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方法:

@Overridepublic 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@Nullableprotected 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接口的资料请关注其它相关文章!

如果说,罗马是一座厚重和凝固的堡垒,

Spring中如何使用Comparator接口

相关文章:

你感兴趣的文章:

标签云: