我已经花了两天时间来缩短这个错误,甚至我尝试了几个stackoverflow帖子中建议的解决方法“-Djava.util.Arrays.useLegacyMergeSort=true”,但它也不起作用。
以下是我的命令及其返回错误的详细信息:
命令:
hadoop jar CloudBrush.jar -Djava.awt.headless=true -Djava.util.Arrays.useLegacyMergeSort=true -reads /Ec10k -asm Ec10k_Brush -k 21 -readlen 36
错误:
Error: java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:895)
at java.util.TimSort.mergeAt(TimSort.java:512)
at java.util.TimSort.mergeCollapse(TimSort.java:437)
at java.util.TimSort.sort(TimSort.java:241)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.Collections.sort(Collections.java:175)
at Brush.VerifyOverlap$VerifyOverlapReducer.reduce(VerifyOverlap.java:252)
at Brush.VerifyOverlap$VerifyOverlapReducer.reduce(VerifyOverlap.java:1)
at org.apache.hadoop.mapred.ReduceTask.runOldReducer(ReduceTask.java:444)
at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:392)
at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:163)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1628)
at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158)
Exception in thread "main" java.io.IOException: Job failed!
at org.apache.hadoop.mapred.JobClient.runJob(JobClient.java:836)
at Brush.VerifyOverlap.run(VerifyOverlap.java:381)
at Brush.BrushAssembler.buildOverlap(BrushAssembler.java:326)
at Brush.BrushAssembler.run(BrushAssembler.java:838)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
at Brush.BrushAssembler.main(BrushAssembler.java:913)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.apache.hadoop.util.RunJar.run(RunJar.java:221)
at org.apache.hadoop.util.RunJar.main(RunJar.java:136)
这是比较器:
class OvelapSizeComparator implements Comparator {
public int compare(Object element1, Object element2) {
OverlapInfo obj1 = (OverlapInfo) element1;
OverlapInfo obj2 = (OverlapInfo) element2;
if ((int)(obj1.overlap_size - obj2.overlap_size) >= 0) {
return -1;
} else {
return 1;
}
}
}
我修复了错误。我以为是Hadoop的问题,我错了。这是Java版本的问题。我们还升级了Java版本和Hadoop一起。如果要排序的元素数量超过32个,java 7和java 8的rrays.sort()方法使用TimSort。蒂姆排序在比较中强制执行严格的传递属性。
如果(比较(x,y)
您应该更改比较方法以与传递属性保持一致,或者使用旧版本排序,将“映射任务Java选择库”或“减少任务Java选择库”的“java.util.rrays.useLegacyMergeSort”设置为true,然后它应该应用于所有为映射或减少而启动的JVM。
对于2.6.0-cdh5.4.2 Haddop,您可以通过添加
-Dmapreduce.map.java.opts="-Djava.util.Arrays.useLegacyMergeSort=true"
-Dmapreduce.reduce.java.opts="-Djava.util.Arrays.useLegacyMergeSort=true"
或者通过密码
工作getConfiguration()。set(“mapreduce.map.java.opts”,“-Djava.util.Arrays.useLegacyMergeSort=true”);
job.get配置(). set("mapreduce.reduce.java.opts","-Djava.util.Arrays.useLegacyMergeSort=true");
您可以通过在测试中运行main方法来重现此错误。JVM7或更高版本上的java代码。总结一下这段代码的作用。这段代码尝试使用不具有传递属性的比较方法对40个人对象进行排序
//人。JAVA
公共阶层人士{
public String name;
public int age ;
public int salary;
@Override
public int compareTo(Person o) {
if(o instanceof Person){
int ret=0;
if(age == 25 && ((Person)o).age ==27) ret = 1;
else if(age == 27 && ((Person)o).age ==29) ret = 1;
else if(age == 25 && ((Person)o).age ==29) ret = -1;
else{
if( age < ((Person)o).age) ret = -1;
if(age > ((Person)o).age) ret = 1;
if(salary < ((Person)o).salary) ret = -1;
if(salary > ((Person)o).salary) ret = 1;
}
return ret;
}
return 0;
}
@Override
public String toString(){
return "name="+name+":age="+age+";";
}
}
//测试。JAVA
导入java.util.数组;
公开课考试{
public static void main(String args[]) {
Test t = new Test();
t.sortPersons(args);
}
public void sortPersons(String args[]) {
Person p1 = new Person();
p1.age = 25;
p1.name = "ABC";
Person p2 = new Person();
p2.age = 29;
p2.name = "ABZ";
Person p3 = new Person();
p3.age = 27;
p3.name = "AZ";
Person p4 = new Person();
p4.age = 27;
p4.name = "AZ";
Person p5 = new Person();
//p5.age = 22;
//p5.name="ZZ";
Person[] p = new Person[40];
p[0] = p2;
p[1] = p3;
p[2] = p4;
p[3] = p1;
p[4] = p5;
for (int i = 1; i < 8; i++) {
p[i * 5] = p[0];
p[i * 5 + 1] = p[1];
p[i * 5 + 2] = p[2];
p[i * 5 + 3] = p[3];
p[i * 5 + 4] = p[4];
}
System.out.println("\nSortingInput\n");
Arrays.sort(p);
System.out.println("\nSorting complete\n");
}
}
真正的问题是您的OvelapSize比较器
[sic]有缺陷。如果两个对象的overlap_size
值相等,它会返回-1
,而它应该返回0
。如果它们不相等,它会返回一个符号不正确的值。
要解决此问题,请替换以下内容:
if ((int)(obj1.overlap_size - obj2.overlap_size) >= 0) {
return -1;
} else {
return 1;
}
...有了这个:
return obj1.overlap_size - obj2.overlap_size;
我正在根据下面的比较器对集合进行排序。 这些值总是非空的。getOrderSendTime()对象属于java.util.Date类。 我知道这是一种传递性不一致,我认为这样的类不会有这样的问题。我搜索了未解决的问题,但没有找到有关该主题的任何问题。 有什么想法吗?
我收到以下错误:“比较方法违反了它的一般合同!”当使用下面的比较器时,我无法使用jUnit复制异常。我想知道是什么导致了这个问题,以及如何复制它。有其他人也有同样的问题,但不知道如何复制。 使用以下方法调用该代码: 感谢任何帮助。 额外信息:该错误似乎发生在Java utils中的TimSort类中,并来自一个名为mergeLo的方法。链接:http://grepcode.com/file/rep
我知道很多答案已经回答了我的问题。在我的代码中,异常说“比较方法违反了它的一般合同”,但我不知道我的比较方法如何违反了它的一般合同。这是我的代码:
我看到我的应用程序在一些中国 Android 手机上发生了很多崩溃,并出现错误:比较方法违反了其总合同! 我读过这与Collections.sort有关。 我不太确定的是,这是否是因为我的自定义比较器。 以下是错误发生的地方: 比较器是这样的: 所以我不太确定比较器是否搞砸了什么,或者我是否需要以不同的方式进行collections.sort调用 感谢任何帮助
问题内容: 有人可以简单地向我解释一下,为什么此代码会引发异常,“比较方法违反了它的一般约定!”,我该如何解决? 问题答案: 你的比较器不是可传递的。 让是的父,并成为母公司。既然和,那一定是这样。但是,如果在和上调用比较器,它将返回零,即。这违反了合同,因此引发异常。 该库可以很好地检测到这一点并让你知道,而不是行为不规律。 满足传递性要求的一种方法是遍历整个链,而不仅仅是查看直接祖先。
我正在尝试编写一个表排序器,该排序器将始终将空值排序到底部。所以我写了一个实现 “包装器”类: 您会注意到方法只执行空检查,然后服从包装值类的方法。 然后我编写了一个< code >行排序器,它的< code >比较器检查< code >排序顺序 但这会引发一个错误(无法找出原因,无法重现-继续阅读): 幸运的是,这个错误似乎没有影响任何事情,因为一切都按预期进行。 看到这个问题(Java . l