请教关于java中stream排序collect比较问题

报错异常:

java.lang.IllegalArgumentException: Comparison method violates its general contract

List<Record> recordsKC = getSpecificationKC();
recordsKC = recordsKC.stream().filter(r ->
        {
            boolean b = true;
            b = r.getStr("specificationName").toLowerCase().contains(keyword.toLowerCase().trim());
            
            return b;

        }

).sorted((e1, e2) -> {
    return compareBylenght(e1, e2,keyword);
    
    //return e1.getStr("specificationName").compareTo(e2.getStr("specificationName"));
}).collect(Collectors.toList());

排序自定义个了一个方法compareBylenght,结果报错

public static int compareBylenght(Record lhs, Record rhs,String keyword) {

    if (lhs.getStr("specificationName").startsWith(keyword)) {
        if (lhs.getStr("specificationName").contains("T")){
            return 1;
        }
        if (rhs.getStr("categoryName").equals("方管") || rhs.getStr("categoryName").equals("矩管")){//"categoryName").equals("方管")
            if (rhs.getStr("specificationName").trim().endsWith("*6米")){
                if (lhs.getStr("specificationName").trim().endsWith("*6米") && rhs.getStr("specificationName").trim().endsWith("*6米") && lhs.getStr("specificationName").length() > rhs.getStr("specificationName").length()) {
                    return 1;
                }else if(lhs.getStr("specificationName").trim().endsWith("*6米") && rhs.getStr("specificationName").trim().endsWith("*6米") && lhs.getStr("specificationName").length() < rhs.getStr("specificationName").length()){
                    return -1;
                }
                return 1;
            }else if(lhs.getStr("specificationName").trim().endsWith("*6米")){
                return -1;//返回负数不交换
            }else {
                if(!lhs.getStr("specificationName").trim().endsWith("*6米") && rhs.getStr("specificationName").trim().endsWith("*12米")){
                    return 1;
                } else {
                    return -1;
                }
            }
        }
        return -1;
    }else if(rhs.getStr("specificationName").startsWith(keyword)){
        return 1;
    }else if(lhs.getStr("specificationName").contains(keyword)){
        return lhs.getStr("specificationName").compareTo(rhs.getStr("specificationName"));

    }else if (lhs.getStr("specificationName").length() > rhs.getStr("specificationName").length()) {
        return 1;
    } else if (lhs.getStr("specificationName").length() == rhs.getStr("specificationName").length()) {
        return -1;
    } else {
        return 0;
    }
}


错误详细信息:

[ERROR]-[Thread: XNIO-1 task-4]-[com.jfinal.core.ActionHandler.handle()]: com.l2qq.specification.SpecificationController.searchByTotalSingleCount() : /admin/specification/searchByTotalSingleCount?keyword=40*&searchType=&searchAll=true
java.lang.IllegalArgumentException: Comparison method violates its general contract!
	at java.base/java.util.TimSort.mergeLo(TimSort.java:781)
	at java.base/java.util.TimSort.mergeAt(TimSort.java:518)
	at java.base/java.util.TimSort.mergeCollapse(TimSort.java:448)
	at java.base/java.util.TimSort.sort(TimSort.java:245)
	at java.base/java.util.Arrays.sort(Arrays.java:1306)
	at java.base/java.util.ArrayList.sort(ArrayList.java:1721)
	at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:392)
	at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at com.l2qq.specification.SpecificationService.searchByTotalSingleCount(SpecificationService.java:114)
	at com.l2qq.specification.SpecificationController.searchByTotalSingleCount(SpecificationController.java:149)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at com.jfinal.aop.Invocation.invoke(Invocation.java:97)
	at com.jfinal.admin.auth.AdminAuthInterceptor.intercept(AdminAuthInterceptor.java:50)
	at com.jfinal.aop.Invocation.invoke(Invocation.java:91)
	at com.jfinal.admin.auth.IsInitialPwInterceptor.intercept(IsInitialPwInterceptor.java:17)
	at com.jfinal.aop.Invocation.invoke(Invocation.java:91)
	at com.jfinal.admin.login.LoginSessionInterceptor.intercept(LoginSessionInterceptor.java:54)
	at com.jfinal.aop.Invocation.invoke(Invocation.java:91)
	at com.jfinal.core.ActionHandler.handle(ActionHandler.java:88)
	at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:90)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:280)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:79)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:134)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:131)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:260)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:79)
	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:100)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:387)
	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852)
	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1423)
	at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280)
	at java.base/java.lang.Thread.run(Thread.java:831)


评论区

zzutligang

2022-05-11 15:48

这和jfinal没关系,stream的sorted,需要完整的比较规则,必须遵守如下规则:
自反性:当两个相同的元素相比时,compare必须返回0,也就compare(o1, o1) = 0;
反对称性:如果compare(o1,o2) = 1,则compare(o2, o1)必须返回符号相反的值也就是 -1;
传递性:如果 a>b, b>c, 则 a必然大于c。也就是compare(a,b)>0,compare(b,c)>0, 则compare(a,c)>0。
从这个方向着手,改进你的比较函数,应该就行了。

fmpoffice

2022-05-12 17:10

@zzutligang 谢谢大佬回复,我重写了一遍,再看看还有没有报错