“Comparison method violates its general contract” is thrown only in certain cases

巧了我就是萌 提交于 2019-12-05 18:23:25

why this error is not always thrown

Because it's not the job of Collections.sort to validate your comparison method. Its job is simply to implement the sort. But the logic of doing so can reveal an invalid comparison method as a by-product of its logic in certain conditional branches. And in that case it makes sense to throw rather than attempting to continue to sort with an invalid comparison method.

What is really contract of comparator (in context of breaking it) ?

That if you break the contract, sort may not function correctly, or at all. (Not that it will validate your comparison method.)

Why for some set of data this exception is thrown and for other not ?

If the sort doesn't happen to follow a path that leads to a logical flaw that the sorting code can detect, it won't know to throw. But the TimSort being used does happen to go down a logical branch which reveals the invalid comparison method, so it does throw.

The exception will in fact always be thrown if Collections.sort() gets the chance to detect that your comparator misbehaves. This happens in certain rare cases where the sort() function knows that a certain item should fall within a certain range, because the comparator previously indicated so, and now it is invoking your comparator and it is being told that the item should fall outside of that range. But sort() is quite complex, and it tries to do as little work as possible, so quite often the conditions for detecting this misbehavior do not happen.

If sort() was to always throw the exception, then before starting to sort your list it would have to pre-emptively invoke your comparator N^2 (that's N squared) times so as to make sure that it always honors its contract for all permutations of pairs of entries in your list. That would be insanely inefficient.

The contract that the comparator must honor is laid out in the documentation: (https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html)

  • The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and y.

  • The implementor must also ensure that the relation is transitive: ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0.

  • Finally, the implementor must ensure that compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z.

(where sgn(x) is the 'Math.signum()' function.)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!