Java 为什么我的比较方法违反了它的总合同?

Java 为什么我的比较方法违反了它的总合同?,java,comparator,Java,Comparator,另外,time对象是来自Joda时间库的DateTime实例,TransportType是包含常量Train、Seaship、Barge和Truck的枚举 编辑: 好的,我将比较器编辑为: public DateTime time; public int maxDuration; public TransportType transportType; public String transportCompany; 总合同是这样的 @Override

另外,time对象是来自Joda时间库的DateTime实例,TransportType是包含常量Train、Seaship、Barge和Truck的枚举

编辑:

好的,我将比较器编辑为:

    public DateTime time;
    public int maxDuration;
    public TransportType transportType;
    public String transportCompany;

总合同是这样的

    @Override
    public int compareTo(LocationMovement lm) {
        if (this.time.isBefore(lm.time))
            return -1;
        else if (this.time.isAfter(lm.time))
            return +1;
        else {
            int c = this.maxDuration - lm.maxDuration;
            if (c != 0) return c;

            c = this.transportCompany.compareTo(lm.transportCompany);
            if (c != 0) return c;

            c = this.transportType.ordinal() - lm.transportType.ordinal();
            return c;
        }
    }

在您的情况下,一种方式返回-1的代码可能会另一种方式返回0。

请注意,如果两个容器
c1
c2
具有相同的
离开时间
,但其他属性不同,则
比较(c1,c2)
比较(c2,c1)
将返回
+1
,即。,
c1>c2
c2>c1

相反,您应该完全删除其他字段,或者在出发时间相等的情况下,在嵌套或顺序
if else
s中分别比较它们


看看这个,可以找到一种通过多个属性比较对象的干净方法。

为了实现
比较
,您检查的所有事物必须具有彼此“较小”、“较大”或“相等”的概念,然后您必须决定检查它们的顺序,返回第一个不相等项的较小值/较大值。这样,您就满足了
compare(a,b)
必须与
compare(b,a)
相反的契约。如果您正在比较的所有部分都没有“大”或“小”的概念(例如,传输类型),那么要么您无法实现
比较
,要么您必须强制对它们进行任意(但可靠)的大/小解释

下面是一个这样做的概念性示例。在本例中,我(任意)选择的顺序是:时间、持续时间、公司和类型。但不同的顺序可能更合理。这只是一个例子。另外,您还没有说明
transportType
的类型,因此我假设它有一个
compareTo
方法;显然,它可能不是,你可能不得不调整

COMPARATOR.compare(a, b) = - COMPARATOR.compare(b, a)
公共静态比较器离开=新比较器(){
@凌驾
公共int比较(容器container1、容器container2){
int-rv;
//时代
rv=集装箱1.出发时间.比较(集装箱2.出发时间);
如果(rv==0){
//持续时间
if(container1.deafit.maxDurationcontainer2.deposition.maxDuration){
rv=1;
}
否则{
//运输公司
rv=集装箱1.出发.运输公司.比较(集装箱2.出发.运输公司);
如果(rv==0){
//运输类型
rv=集装箱1.出发.运输类型.比较(集装箱2.出发.运输类型);
}
}
}
返回rv;
}
};

如果集装箱
c1
和集装箱
c2
具有相同的
出发时间
,但其他属性不同,则两者都
比较(c1,c2)
比较(c2,c1)
将返回
+1
。旁注:在
中进行如此巨大的计算,否则如果
只是自找麻烦。谢谢你们的回答。你能看一下我的编辑吗?你的前两个
if
检查相同的条件。此外,在“equals”(新的
else
)情况下,您还应该有可能返回
-1
,或者您仍然存在与第一种方法相同的问题。在您的解决方案中,如果(c!=0)返回c,您当然可以更改最后一个
;返回0
to
返回c。(您可以只返回顺序比较的结果,但如果您先将其放入
c
,则更容易调试。)我可以看到他的原始代码如何在一个方向返回
1
,而在另一个方向返回
0
,但无法看到它如何返回
-1
0
。当然,没关系,问题是一样的。谢谢你的回答,我已经编辑了我的问题,其中包含了我的解决方案。
    public static Comparator<Container> ARRIVAL = new Comparator<Container>() {
        @Override
        public int compare(Container container1, Container container2) {
            return container1.arrival.compareTo(container2.arrival);
        }
    };

    public static Comparator<Container> DEPARTURE = new Comparator<Container>() {
        @Override
        public int compare(Container container1, Container container2) {
            return container1.departure.compareTo(container2.departure);
        }
    };
    @Override
    public int compareTo(LocationMovement lm) {
        if (this.time.isBefore(lm.time))
            return -1;
        else if (this.time.isAfter(lm.time))
            return +1;
        else {
            int c = this.maxDuration - lm.maxDuration;
            if (c != 0) return c;

            c = this.transportCompany.compareTo(lm.transportCompany);
            if (c != 0) return c;

            c = this.transportType.ordinal() - lm.transportType.ordinal();
            return c;
        }
    }
COMPARATOR.compare(a, b) = - COMPARATOR.compare(b, a)
public static Comparator<Container> DEPARTURE = new Comparator<Container>() {
    @Override
    public int compare(Container container1, Container container2) {
        int rv;

        // Times
        rv = container1.departure.time.compareTo(container2.departure.time);
        if (rv == 0) {
            // Duration
            if (container1.departure.maxDuration < container2.departure.maxDuration) {
                rv = -1;
            }
            else if (container1.departure.maxDuration > container2.departure.maxDuration) {
                rv = 1;
            }
            else {
                // Transport company
                rv = container1.departure.transportCompany.compareTo(container2.departure.transportCompany);
                if (rv == 0) {
                    // Transport type
                    rv = container1.departure.transportType.compareTo(container2.departure.transportType);
                }
            }
        }
        return rv;
    }
};