有人可以用简单的语言解释我,为什么这个代码会抛出异常,"比较方法违反了它的一般合同!",我该如何修复它?
private int compareParents(Foo s1, Foo s2) {
if (s1.getParent() == s2) return -1;
if (s2.getParent() == s1) return 1;
return 0;
}
Run Code Online (Sandbox Code Playgroud) 嗨,下面是我比较器的比较方法.我不确定是什么问题.我在堆栈溢出时查找了其他类似的标题问题和答案,但不确定我的方法有什么问题,但我不断得到java.lang.IllegalArgumentException:比较方法违反了它的一般合同!
任何帮助将不胜感激
public int compare(Node o1, Node o2)
{
HashMap<Integer,Integer> childMap = orderMap.get(parentID);
if(childMap != null && childMap.containsKey(o1.getID()) &&
childMap.containsKey(o2.getID()))
{
int order1 = childMap.get(o1.getID());
int order2 = childMap.get(o2.getID());
if(order1<order2)
return -1;
else if(order1>order2)
return 1;
else
return 0;
}
else
return 0;
}
Run Code Online (Sandbox Code Playgroud)
添加我得到的例外
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:747)
at java.util.TimSort.mergeAt(TimSort.java:483)
at java.util.TimSort.mergeCollapse(TimSort.java:410)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
Run Code Online (Sandbox Code Playgroud) 最近,我们将Jdk版本升级1.6到1.8我的一个Java项目中.但是有一些编译或运行时错误,所以我必须升级一些库:
1.9to1.103.x到4.x那是因为他们使用的是早期版本的ASM,但仅支持jdk 1.8 5.x
Java表示它是向后兼容的,但为什么原始版本的库无法直接与jdk 1.8一起使用?
我有一些我想要比较的数字.它们代表通过不同空间的路径长度.
不幸的是,一些不精确导致了错误的比较.例如,在注意到错误的效果后,我发现我正在进行这样的比较:
a = 384.527100541296
b = 384.52710054129614 // Note the trailing 14
Run Code Online (Sandbox Code Playgroud)
为了我的目的,a和b应该是平等的.
我注意到番石榴有一种fuzzyCompare()双打方法,似乎可以做我想要的忽略一些精度:
private static final double COMPARISON_PRECISION=1e-10;
private static final Comparator<Double> fuzzyCompare= new Comparator<Double>(){
public int compare(Double o1, Double o2) {
return DoubleMath.fuzzyCompare(o1, o2, COMPARISON_PRECISION);
}
};
public int compareTo(Object o) {
if (o instanceof Spam) {
Spam other = (Spam) (o);
return ComparisonChain.start()
.compare(this.getLength(),other.getLength(),fuzzyCompare)
//...
.result();
} else {
throw new ClassCastException();
}
}
Run Code Online (Sandbox Code Playgroud)
关于模糊比较的警告并没有引起我的注意:
这不是总排序,不适合在Comparable.compareTo(T)实现中使用.特别是,它不具有传递性
我的问题是,这种缺乏传递性是一个真正的问题吗?如果是的话,它会如何呈现?我认为,如果比较真的被真正违反了,它会抛出类似于这个问题 的错误:Java错误:比较方法违反了它的一般合同,并且它甚至没有对我测试的各种值进行这样做. …
我知道这种异常有很多问题,而且我确实找到了解决方案,但我的问题是不同项目中的相同代码不会抛出异常,而这个却抛出异常。这两个项目都具有相同版本的 Java 和其他库。
基本上我有一个小函数,它从目录中检索文件列表,按时间戳对它们进行排序,然后返回绝对文件名列表:
public static List<String> getFiles(String dir) {
List<String> fileList = new ArrayList<String>();
File[] files = new File(dir).listFiles();
// Sort files by the date of their creation (last modification)
Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
for (File f : files) {
fileList.add(f.getAbsolutePath());
}
return fileList;
}
Run Code Online (Sandbox Code Playgroud)
基本上,在其中一个项目中,此代码按预期执行,而在其他项目中,它会抛出IllegalArgumentException: Comparison method violates its general contract!
我知道TimSort从 1.7 开始这是 Java 中的默认排序,解决方案之一是使用强制使用旧版的属性MergeSort。我没有走那条路...相反,我“缓存”文件及其时间戳,如下所示:
public static List<String> getFiles(String dir) {
List<String> fileList = new ArrayList<String>();
File[] files = new File(dir).listFiles();
FileLastModifiedPair[] …Run Code Online (Sandbox Code Playgroud) 我有一个自己的,相对复杂的字符串比较器和一个大的字符串列表(大约 100 个字符串,已经尝试减少但问题不可重现),当尝试使用 Java 7 进行排序时,对它们进行排序会产生上述错误。我猜,那个规则
if a < b and b < c then a < c
Run Code Online (Sandbox Code Playgroud)
可能会被侵犯。找出违反合同的样品的最佳方法是什么?
我的java代码引发了以下异常:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
Run Code Online (Sandbox Code Playgroud)
我研究了StackOverflow上的消息,并发现了一些问题,这些问题发布了他们写得不好的比较方法,但我想知道合同的编写地点以及它对于比较方法必须做什么的确切说明.
我有compareTo我的列表的代码:
public int compareTo(className a)
{
return (this.long1 > a.long1) ? 1 : -1;
}
Run Code Online (Sandbox Code Playgroud)
当我使用时Collections.sort(list),我收到以下错误:Comparison method violates its general contract!
当我将其更改为if (this.long1 >= a.long2),它可以工作,但它没有正确排序.long按顺序排序,然后按顺序排序,然后按顺序排序.使用>=,输出如下所示:
...
2000100
2000101
2000102
1000100
1000101
2000101
2000102
...
Run Code Online (Sandbox Code Playgroud)
现在,重复确实发生了,他们需要正确排序.重复项首先出现或最后出现并不重要,只要它们按顺序正确分组,如下所示:
...
2000100
2000101
2000101
2000102
2000102
1000100
1000101
...
Run Code Online (Sandbox Code Playgroud)
我该怎么做呢?谢谢.
UPDATE
该列表仍然按顺序排序,并提供以下所有建议.这是因为它是一个List<Class> list = new ArrayList<Class>();?我无法使用C#中常用的东西:List<Class> list = new List<Class>().
比较方法违反了其总合同
我按等级排序是一个double.任何人都可以看到为什么我收到此错误?
Collections.sort(productsMasterList, new Comparator<Product>() {
@Override
public int compare(Product o1, Product o2) {
final double rating1 = o1.getRating();
final double rating2 = o2.getRating();
boolean realisticRating1 = rating1 < 4.8;
boolean realisticRating2 = rating2 < 4.8;
return rating1 > rating2 && realisticRating1 ? -1 : rating2 > rating1 && realisticRating2 ? 1 : 0;
}
});
Run Code Online (Sandbox Code Playgroud)
编辑:这不是重复,因为它对我来说非常具体.我已经看到其他答案,但我仍然无法弄清楚为什么我收到此错误,我的代码似乎应该工作正常
我们的一些用户在排序列表时遇到此异常.抛出它的代码是
Collections.sort(activeConverstions, new Comparator<Conversation>() {
@Override
public int compare(Conversation o1, Conversation o2) {
return (int)(o2.getTime()- o1.getTime()); // descending order
}
});
Run Code Online (Sandbox Code Playgroud)
而getTime()的类型为"long"
java ×10
sorting ×5
comparator ×3
android ×1
collections ×1
compareto ×1
comparison ×1
file ×1
guava ×1
java-7 ×1
java-8 ×1
migration ×1