Spring中如何使用Comparator接口
我們先來(lái)回顧下Comparator接口在我們?nèi)粘i_(kāi)發(fā)中的作用,Comparator比較器接口可以將自身傳遞給排序方法(比如Collections.sort或Arrays.sort),以便對(duì)排序順序進(jìn)行精確控制。比如:
List<Integer> intList = Arrays.asList(2, 3, 1);
Collections.sort(intList, (o1, o2) -> {
return o2-o1;
});
輸出
[3, 2, 1]
Comparator可以用來(lái)控制某些數(shù)據(jù)結(jié)構(gòu)(如sored sets 或sorted maps)的順序,或者為沒(méi)有自然順序的對(duì)象集合提供順序,比如:
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是策略模式的一個(gè)經(jīng)典體現(xiàn),在Spring中它為實(shí)現(xiàn)了Ordered接口的類(lèi)寫(xiě)了一個(gè)比較器名叫OrderComparator,我們來(lái)看看它的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) {
//判斷是否實(shí)現(xiàn)了PriorityOrdered接口
//o1為原先的后一個(gè)元素
//o2為原先的前一個(gè)元素
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
//p1實(shí)現(xiàn)了PriorityOrdered,但是p2沒(méi)實(shí)現(xiàn)PriorityOrdered,則p1優(yōu)先級(jí)更高
if (p1 && !p2) {
////小于0 表示逆序 o1排前
return -1;
}
else if (p2 && !p1) {
//p2實(shí)現(xiàn)了PriorityOrdered,但是p1沒(méi)實(shí)現(xiàn)PriorityOrdered,則p2優(yōu)先級(jí)更高
//大于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代表最低優(yōu)先級(jí)
return Ordered.LOWEST_PRECEDENCE;
}
@Nullable
protected Integer findOrder(Object obj) {
return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
}
OrderComparator主要是通過(guò)實(shí)現(xiàn)Order接口方法getOrder返回的值來(lái)比較的,而通過(guò)注解Order比較的話(huà)是采用繼承OrderComparator類(lèi)的AnnotationAwareOrderComparator類(lèi)來(lái)重載getOrder方法來(lái)實(shí)現(xiàn):
@Override
@Nullable
protected Integer findOrder(Object obj) {
// Check for regular Ordered interface
//檢查常規(guī)的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代表在當(dāng)前運(yùn)行的java虛擬機(jī)中一個(gè)可以被注解的元素,這個(gè)接口允許通過(guò)反射讀取元素上面的注解,這與我們之 前的理解是一致的
//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等注解實(shí)際上都采用了實(shí)現(xiàn)Order注解的方法來(lái)進(jìn)行排序。這里我就截個(gè)圖看下了:

Conditional注解中的OnClassCondition類(lèi)就標(biāo)了@Order注解

實(shí)現(xiàn)Comparator接口compare方法的時(shí)候主要是要注意以下幾點(diǎn)(翻譯自官方文檔):

用中文簡(jiǎn)單來(lái)說(shuō)就是在 JDK7 版本以上默認(rèn)使用Timsort排序方法來(lái)實(shí)現(xiàn),Comparator 比較器要滿(mǎn)足自反性,傳遞性,反對(duì)稱(chēng)性,不然 Arrays.sort,Collections.sort有可能會(huì)報(bào) IllegalArgumentException 異常。
以上就是Spring中如何使用Comparator接口的詳細(xì)內(nèi)容,更多關(guān)于Spring 使用Comparator接口的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
IDEA運(yùn)行Tomcat中文亂碼出現(xiàn)的各種問(wèn)題
這篇文章主要介紹了IDEA運(yùn)行Tomcat中文亂碼的各種問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
淺析Java內(nèi)部類(lèi)——成員內(nèi)部類(lèi)
這篇文章主要介紹了Java 成員內(nèi)部類(lèi)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java 內(nèi)部類(lèi)的相關(guān)知識(shí),感興趣的朋友可以了解下2020-08-08
一篇文章告訴你如何在Java數(shù)組中插入一個(gè)字符
本篇文章主要介紹了Java數(shù)組中插入一個(gè)字符的相關(guān)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-10-10
詳解Spring?Security怎么從數(shù)據(jù)庫(kù)加載我們的用戶(hù)
這篇文章主要為大家介紹了Spring?Security怎么從數(shù)據(jù)庫(kù)加載我們的用戶(hù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Spring Boot與RabbitMQ結(jié)合實(shí)現(xiàn)延遲隊(duì)列的示例
本篇文章主要介紹了Spring Boot與RabbitMQ結(jié)合實(shí)現(xiàn)延遲隊(duì)列的示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
使用 Spring Boot 實(shí)現(xiàn) WebSocket實(shí)時(shí)通信
本篇文章主要介紹了使用 Spring Boot 實(shí)現(xiàn) WebSocket實(shí)時(shí)通信,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10

