编写一个正确的compareTo实现

时间:2019-03-10 16:55:39

标签: java sorting comparable custom-compare

private static class CharacterIndex implements Comparable<CharacterIndex> {
    private final char c;
    private final int index;

    public CharacterIndex(char c, int index) {
        this.c = c;
        this.index = index;
    }
}

现在,我想覆盖此类的compareTo方法,这样,如果我拥有List对象CharacterIndex中的以下[('y', 1), ('x', 2), ('b', 3), ('a', 3)],则在排序后,这些对象应该像[('b', 3), ('a', 3), ('x', 2), ('y', 1)]

排序策略:

索引不同的对象可以随机播放(并且应该仅基于字符的值进行排序)。具有相同索引的对象在排序后应保持其相对顺序。

另一个例子:

对于[('y', 1), ('w', 2), ('x', 3)],已排序列表应为[(w, 2), (x, 3), (y, 1)],而不是[(x, 3), (w, 2), (y, 1)]

我的尝试:

@Override
public int compareTo(CharacterIndex ci) {
    if (this.index == ci.index)
        return -1; // don't swap if the index is same
    return Character.compare(this.c, ci.c);
}

但是这种方法给了我一个例外:

Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:866)
    at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:483)
    at java.util.ComparableTimSort.mergeForceCollapse(ComparableTimSort.java:422)
    at java.util.ComparableTimSort.sort(ComparableTimSort.java:222)
    at java.util.Arrays.sort(Arrays.java:1312)
    at java.util.Arrays.sort(Arrays.java:1506)
    at java.util.ArrayList.sort(ArrayList.java:1462)
    at java.util.Collections.sort(Collections.java:141)

我看到了this。但是我不清楚我为什么会得到这个例外。

是否有更好的方法通过上述给定策略对List<CharacterIndex>进行排序?

1 个答案:

答案 0 :(得分:0)

这是因为您有(device-height: 1194px) and (device-width: 834px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)o1.compareTo(o2) == -1 && o2.compareTo(o1) == -1o1.index == o2.index方法的约定是,这两个必须具有不同的符号:compareToo1.compareTo(o2)

换句话说,这意味着o2.compareTo(o1)小于o1o2小于o2,这都是不可能的。

可能的解决方案:

o1

在这里,我们正在按其携带的字符进行比较。正如@RealSkeptic注意到的那样,由于关系不再具有传递性,因此无法考虑索引。