首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >比较法在比较java.util.Date时违反其一般契约

比较法在比较java.util.Date时违反其一般契约
EN

Stack Overflow用户
提问于 2017-08-18 03:30:46
回答 2查看 7.6K关注 0票数 5

以下是我的错误:

代码语言:javascript
复制
Caused by: javax.faces.el.EvaluationException: java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101) [jboss-jsf-api_2.1_spec-2.1.28.SP1-redhat-1.jar:2.1.28.SP1-redhat-1]
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:101) [jsf-impl-2.1.28.redhat-10.jar:2.1.28.redhat-10]
    at javax.faces.component.UICommand.broadcast(UICommand.java:315) [jboss-jsf-api_2.1_spec-2.1.28.SP1-redhat-1.jar:2.1.28.SP1-redhat-1]
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:786) [jboss-jsf-api_2.1_spec-2.1.28.SP1-redhat-1.jar:2.1.28.SP1-redhat-1]
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1251) [jboss-jsf-api_2.1_spec-2.1.28.SP1-redhat-1.jar:2.1.28.SP1-redhat-1]
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81) [jsf-impl-2.1.28.redhat-10.jar:2.1.28.redhat-10]
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.28.redhat-10.jar:2.1.28.redhat-10]
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl-2.1.28.redhat-10.jar:2.1.28.redhat-10]
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) [jboss-jsf-api_2.1_spec-2.1.28.SP1-redhat-1.jar:2.1.28.SP1-redhat-1]
    ... 29 more
Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.TimSort.mergeHi(TimSort.java:899) [rt.jar:1.8.0_65]
    at java.util.TimSort.mergeAt(TimSort.java:516) [rt.jar:1.8.0_65]
    at java.util.TimSort.mergeForceCollapse(TimSort.java:457) [rt.jar:1.8.0_65]
    at java.util.TimSort.sort(TimSort.java:254) [rt.jar:1.8.0_65]
    at java.util.Arrays.sort(Arrays.java:1512) [rt.jar:1.8.0_65]
    at java.util.ArrayList.sort(ArrayList.java:1454) [rt.jar:1.8.0_65]
    at java.util.Collections.sort(Collections.java:175) [rt.jar:1.8.0_65]

下面是我的比较方法代码。vo1.getAttribute()返回java.util.Date对象。

代码语言:javascript
复制
    @Override
    public int compare(DateComparableVO vo1, DateComparableVO vo2) {
        if (vo1 != null && vo1.getAttribute() != null && vo2 != null && vo2.getAttribute() != null) {
            return vo1.getAttribute().compareTo(vo2.getAttribute());
        }
        return -1;
    }

比较方法的实现有什么问题吗?

在空的情况下。

为什么下面的代码工作没有任何问题。

代码语言:javascript
复制
package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

public class TestMain {

    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<Employee>();
        employees.add(new Employee(new Date()));
        employees.add(null);
        employees.add(new Employee(new Date()));
        employees.add(new Employee(new Date()));
        employees.add(null);
        employees.add(new Employee(new Date()));
        employees.add(null);
        System.out.println(employees.size());
        Collections.sort(employees, new EmployeeComparator());

    }

}

class Employee {


    private Date attribute;

    public Employee() {
        // TODO Auto-generated constructor stub
    }

    public Employee(Date attribute) {
        this.attribute = attribute;
    }


    public Date getAttribute() {
        return attribute;
    }

    public void setAttribute(Date attribute) {
        this.attribute = attribute;
    }

    @Override
    public String toString() {
        return "Employee [attribute=" + attribute + "]";
    }
}

class EmployeeComparator implements Comparator<Employee>{

    @Override
    public int compare(Employee vo1, Employee vo2) {
        System.out.println("VO1 : " + vo1 + " VO2 : " + vo2);

        if (vo1 != null && vo1.getAttribute() != null && vo2 != null && vo2.getAttribute() != null) {
            return vo1.getAttribute().compareTo(vo2.getAttribute());
        }
        return -1;
    }

}

输出

代码语言:javascript
复制
7
VO1 : null VO2 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017]
VO1 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017] VO2 : null
VO1 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017] VO2 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017]
VO1 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017] VO2 : null
VO1 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017] VO2 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017]
VO1 : null VO2 : null
VO1 : null VO2 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017]
VO1 : null VO2 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017]
VO1 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017] VO2 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017]
VO1 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017] VO2 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017]
VO1 : null VO2 : null
VO1 : null VO2 : Employee [attribute=Fri Aug 18 11:51:11 SGT 2017]
VO1 : null VO2 : null

我是不是在理解比较的过程中遗漏了一些重要的部分?

EN

回答 2

Stack Overflow用户

发布于 2017-08-18 03:42:51

最后的盲-1意味着null值没有得到稳定的处理(并且破坏了合并排序算法)。你可以做这样的事

代码语言:javascript
复制
@Override
public int compare(DateComparableVO vo1, DateComparableVO vo2) {
    Date l = null, r = null;
    if (vo1 != null) {
        l = vo1.getAttribute();
    }
    if (vo2 != null) {
        r = vo2.getAttribute();
    }
    if (l == null && r == null) {
        return 0;
    } else if (l == null) {
        return -1;
    } else if (r == null) {
        return 1;
    }
    return l.compareTo(r);
}
票数 6
EN

Stack Overflow用户

发布于 2017-08-18 12:23:54

除了其他答案已经指出的之外,在java 8中实现这样一个Comparator的另一种方法是使用静态工厂方法组合它,例如:

代码语言:javascript
复制
Comparator<DateComparableVO> c = Comparator.nullsLast(
    Comparator.comparing(DateComparableVO::getAttribute,
        Comparator.nullsLast(Date::compareTo)));

nullsFirst,取决于您希望如何处理空值。这是否更易读可能是一个讨论的问题,但它是自我记录什么是关于空值的预期行为。

如果您知道不能有任何空值,无论是对象本身还是属性,都可以简化为

代码语言:javascript
复制
Comparator<DateComparableVO> c = Comparator.comparing(DateComparableVO::getAttribute);

它将在遇到空值时抛出NullPointerException

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45748077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档