【问题标题】:Java error: "Comparison method violates its general contract!"Java 错误:“比较方法违反了它的一般约定!”
【发布时间】:2012-02-27 17:23:41
【问题描述】:

我有这个代码:

package org.optimization.geneticAlgorithm;
import org.optimization.geneticAlgorithm.selection.Pair;

public abstract class Chromosome implements Comparable<Chromosome> {
    public abstract double fitness();
    public abstract Pair<Chromosome> crossover(Chromosome parent);
    public abstract void mutation();
    public int compareTo(Chromosome o) {
        int rv = 0;
        if (this.fitness() > o.fitness()) {
            rv = -1;
        } else if (this.fitness() < o.fitness()) {
            rv = 1;
        }
        return rv;
    }
}

每次我运行这段代码时都会出现这个错误:

Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:835)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:453)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:376)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:182)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at java.util.Collections.sort(Collections.java:155)
at org.optimization.geneticAlgorithm.GeneticAlgorithm.nextGeneration(GeneticAlgorithm.java:74)
at org.optimization.geneticAlgorithm.GeneticAlgorithm.execute(GeneticAlgorithm.java:40)
at test.newData.InferenceModel.main(InferenceModel.java:134)

我使用 OpenJDK7u3,当对象相等时我返回 0。有人可以向我解释这个错误吗?

【问题讨论】:

  • 无论在同一个对象上调用多少次,您的fitness() 方法是否总是返回相同的值?你能和我们分享一下实现吗?

标签: java openjdk comparable


【解决方案1】:

如果你有任何 NaN 值,你可能会陷入这种情况:

例如:

public class Test
{
    public static void main(String[] args) {
        double a = Double.NaN;
        double b = Double.NaN;
        double c = 5;

        System.out.println(a < b);
        System.out.println(a > b);
        System.out.println(b < c);
        System.out.println(c < b);
    }
}

所有这些打印false。因此,您最终可能会遇到两个非 NaN 值都被视为“等于”NaN,但一个大于另一个的情况。基本上,您应该弄清楚要如何处理 NaN 值。还要检查这确实是问题所在,当然……你真的想要 NaN 值来适应你的健康吗?

【讨论】:

  • 您可能不想要 NaN 值,但仅供参考,int Double.compare(double, double) 将进行满足 Comparator 合约的比较。正如 Javadoc 中所指定的,NaN 的值将被比较为等于和大于使用此比较的所有其他值。
【解决方案2】:

您的适应度函数很可能以以下两种方式之一被破坏:

  1. 在同一个对象上调用时,它并不总是返回相同的值。
  2. 它可以返回 NaN。正如 Jon Skeet 所解释的,您的 compareTo() 在存在 NaN 的情况下不可传递。

你可以使用Double.compare()重写你的比较函数:

public int compareTo(Chromosome o) {
    return Double.compare(o.fitness(), this.fitness());
}

这需要更少的代码并处理极端情况(NaN、负零等)。当然,这些极端情况是否应该首先出现是由您决定和解决的。

【讨论】:

    【解决方案3】:

    您应该尝试添加if (this == o) return 0; 因为同一个对象必须返回相等。

    【讨论】:

      猜你喜欢
      • 2018-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多