首先:这不是Partial Ordered Comparator问题的副本,而是建立在它之上。
我的目标是对对象列表(例如[2,“a”,1])进行就地排序,以便在排序后没有两个整数出现乱序。
为此,我在这个答案中使用了以下部分排序的实现并得到了IllegalArgumentException
:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
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)
at MySortUtils.sortPartially(ArimsCollectionUtils.java:150)
这是因为建议的比较器存在缺陷。示范:
对iff和都是整数并根据整数的自然排序的R
所有Object
实例使用偏序:a.before(b)
a
b
a < b
public boolean before(Object a, Object b) {
// only integers are ordered
if (a instanceof Integer && b instanceof Integer) {
int intA = ((Integer) a).intValue();
int intB = ((Integer) b).intValue();
return intA < intB;
} else {
return false;
}
}
原因是通过以下实现
Comparator<Object> fullCmp = new Comparator<Object>() {
// Implementation shamelessly plucked from
// https://stackoverflow.com/a/16702332/484293
@Override
public int compare(Object o1, Object o2) {
if(o1.equals(o2)) {
return 0;
}
if(partialComparator.before(o1, o2)) {
return -1;
}
if(partialComparator.before(o2, o1)) {
return +1;
}
return getIndex(o1) - getIndex(o2);
}
private Map<Object ,Integer> indexMap = new HashMap<>();
private int getIndex(Object i) {
Integer result = indexMap.get(i);
if (result == null) {
indexMap.put(i, result = indexMap.size());
}
return result;
}
};
这可以在生成的排序中产生一个循环,因为
// since 2 and "a" are incomparable,
// 2 gets stored with index 0
// "a" with index 1
assert fullCmp.compare(2, "a") == -1
// since "a" and 1 are incomparable,
// "a" keeps its index 1
// 2 gets index 2
assert fullCmp.compare("a", 1) == -1
// since 1 and 2 are comparable:
assert fullCmp.compare(1, 2) == -1
都是真的,即 2 < "a"、"a" < 1 和 "1 < 2,这显然不是有效的总排序。
这给我留下了最后一个问题:如何修复这个错误?