【问题标题】:Comparison method violates its general contract even though Double.compare(v1, v2) is used即使使用 Double.compare(v1, v2),比较方法也违反了它的一般约定
【发布时间】:2013-12-29 20:35:22
【问题描述】:

首先:我知道,这个问题在堆栈溢出的很多地方都有回答,但是,这个问题是不同的。我不是要自己进行比较,而是使用 Double.compare() 来比较 2 个双打。

所以,例外:

Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(Unknown Source)
at java.util.TimSort.mergeAt(Unknown Source)
at java.util.TimSort.mergeCollapse(Unknown Source)
at java.util.TimSort.sort(Unknown Source)
at java.util.TimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
at repository.corpus.document.Summarizer.summarize(Summarizer.java:53)
at muse.GATrainer.RougeNEvaluator.getFitness(RougeNEvaluator.java:63)
at muse.GATrainer.RougeNEvaluator.getFitness(RougeNEvaluator.java:1)
at org.uncommons.watchmaker.framework.FitnessEvalutationTask.call(FitnessEvalutationTask.java:52)
at org.uncommons.watchmaker.framework.FitnessEvalutationTask.call(FitnessEvalutationTask.java:26)
... 4 more

代码:

List<Sentence> sentenceList = finalRepresentation.getSentences();
Comparator<Sentence> scoreComperator = new Comparator<Sentence>()
{
    public int compare(Sentence o1, Sentence o2)
    {
    if (o1.equals(o2))
    {
        System.out.println("Trying to compare a sentence to it self");
    }       

    if (Double.isInfinite(o1.getScore()) || Double.isNaN(o1.getScore()))
    {
        System.out.println(o1.getSentence() + " score " + o1.getScore());
    }
    if (Double.isInfinite(o2.getScore()) || Double.isNaN(o2.getScore()))
    {
        System.out.println(o2.getSentence() + " score " + o2.getScore());
    }

    return Double.compare(o1.getScore(), o2.getScore());
    }
};

Collections.sort(sentenceList, Collections.reverseOrder(scoreComperator)); // source of the exception

这是句子类代码(部分与分数有关):

public class Sentence implements Comparable<Sentence>
{
// ...
private double score = Integer.MIN_VALUE; // the final score of the sentence will be saved here later
// ...
public double getScore()
{
    return score;
}

public void setScore(double score)
{
    this.score = score;
}
// ..
}

link,您可以找到我在比较器中打印出的一些分数(我添加了一个打印出 o1 和 o2 get 句子的系统)

注意:字段分数被初始化为 Double.MIN_VALUE,正如您在代码中看到的那样,我已经测试了它的极值点(NaN 和 Infinity)。比较器中的测试不会在控制台上打印任何内容,因此我认为分数既不是 NaN 也不是 Infinity。可能是我弄错了。

我会采纳一些想法。

【问题讨论】:

  • 如果在排序的同时调用setScore,就会发生这种情况。
  • 你从getScore()得到什么?
  • 你能告诉我们一些分数输入吗?我无法重现这个。
  • 您不止一次获得分数,因此您检查有限性和 NaN-ness 的 double 可能与您正在比较的不同。对于任何给定的xx.getScore() == x.getScore() || isNaN(x.getScore()) &amp;&amp; isNaN(x.getScore()) 是否总是如此?
  • 能否重现这个问题,并找出错误发生时涉及哪些实例(分数/字符串)?

标签: java sorting exception collections comparator


【解决方案1】:

您是否还记得重写 equals() 以使其与您的 compareTo() 方法相对应?请记住,如果 compareTo==0 对象必须是 equals()

【讨论】:

  • 这不会违反compare的总合同。另请注意,TimSort 从不调用 equals
  • 我正在使用外部比较器,我认为它不应该使用 equals,但是,只是为了论证 - 也实现了 equals 方法。但是,内部 compareTo() 方法和 equals() 方法使用 String.compareTo 和 String.equals 方法通过句子字符串比较 Sentence 类。我需要按每个句子的分数对数组进行排序,然后按与内部比较和等于方法不同的 ID 对数组进行排序。
  • 那么两个句子的字符串相同但分数不同的情况会发生吗?
  • 这不可能发生,但是为了论证,我将在比较器中为同一实例添加一个检查。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多