0

Now I know that questions on this topic have already been asked before, however my question isn't pertaining to a particular example.

I just wish to understand what the stated error means. All that I have been able to find on the internet is example-based solutions. Can someone explain what the core of this error is, and when it can occur?

I'm just a student trying to learn, and haven't been able to understand this via other sources, so please be patient with me.

Thanks.

Pratyush Panshikar
  • 163
  • 1
  • 1
  • 8
  • Though your question is pertaining to the general reason of the exception, those concepts have already been answered in previous question. TLDR; You do not respect the rules of implementation. The most frequent example is transitivity: `if A < B && B < CC then A < C`. Comparators must respect those rules, that are called altogether a contract. – Turtle Apr 04 '18 at 15:03

2 Answers2

1

If you don't want a specific example, simply turn to the specification of the contract, for example to be found in the Comparator javadoc:

A comparison function, which imposes a total ordering on some collection of objects ... The ordering imposed by a comparator c on a set of elements S is said to be consistent with equals if and only if c.compare(e1, e2)==0 has the same boolean value as e1.equals(e2) for every e1 and e2 in S. ...

and so on. And even more to the point: the javadoc for the compare() method:

Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.

In the foregoing description, the notation sgn(expression) designates the mathematical signum function, which is defined to return one of -1, 0, or 1 according to whether the value of expression is negative, zero or positive.

The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and y. (This implies that compare(x, y) must throw an exception if and only if compare(y, x) throws an exception.)

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.

It is generally the case, but not strictly required that (compare(x, y)==0) == (x.equals(y)). Generally speaking, any comparator that violates this condition should clearly indicate this fact. The recommended language is "Note: this comparator imposes orderings that are inconsistent with equals."

These specifications define what the "contract" is about. And when you violate the contract, and the system is able to detect that, you end up with said exception.

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248
1

Comparable defines a contract for the compareTo method:

  • The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.)

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

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

If the implementor does not ensure these conditions, it is a violation of the contract and users of the Comparable.compareTo method may report that with an exception.

Community
  • 1
  • 1
lexicore
  • 42,748
  • 17
  • 132
  • 221
  • alright so what I get from this is: this exception is thrown if i make some comparisons between variables, and these comparisons turn out to be unnecessary or illogical. am i right? – Pratyush Panshikar Apr 04 '18 at 16:50
  • @PratyushPanshikar No. You get this if you implement the `compareTo` method so that it breaks one of the listed requirements. For instance if `a.compareTo(b) > 0` and `b.compareTo(a) <= 0`. Or if `a > b`, `b > c` but `a <= c`. It is quite easy to make such a mistake when implementing the comparison. – lexicore Apr 04 '18 at 16:55
  • I haven't used the compareTo method anywhere in my code, but I'm still getting the exception, which is why I'm a little extra curious. – Pratyush Panshikar Apr 04 '18 at 17:28
  • @PratyushPanshikar Well, if you would have actually posted the code and the exception, then we could talk further. As it stands now, you have asked it rather generally, theoretically and not based on any examples. So this is the answer. – lexicore Apr 04 '18 at 19:58
  • Could you tell me in what cases this exception may occur when compareTo hasn't been used? – Pratyush Panshikar Apr 04 '18 at 20:00
  • @PratyushPanshikar Look, I can throw this exception with this very text from anywhere, completely unrelated to `compareTo`. But it is typically thrown if there is a problem with the `compareTo` method. How are you so sure that `compareTo` isn't used? – lexicore Apr 04 '18 at 20:07
  • @PratyushPanshikar Next, please excuse me, but it is a bit tiresome to play "please answer my theoretical question based on my assumptions (which may actually not be true)". Show your code, show your implementation of the `compareTo` method, show the complete exception details, then we'll talk further on. – lexicore Apr 04 '18 at 20:09
  • Okay I think I may be missing something here. Do you mean the invocation of an inbuilt, non-coded compareTo method, or do you mean a compareTo method I have personally invoked in my code? – Pratyush Panshikar Apr 04 '18 at 20:09
  • @PratyushPanshikar I'm not sure what you mean by "inbuilt, non-coded `compareTo`", I do not know about such a thing. But you don't have to personally invoke `compareTo` in your code for it to be used. If you have a class which implements `Comparable` and you sort a collection of this class instances using `Collections.sort` or use a sorted collection like `TreeSet` - then the `compareTo` method is used. Without you personally calling it in your code. – lexicore Apr 04 '18 at 20:13
  • By 'inbuilt, non-coded', I meant the invocation of a compareTo method without me directly calling it in my code. I understand what you're saying now. I have an interesting development in this topic which, if you're open to it, I'd like to discuss with you. You clearly have knowledge about the topic and I'm eager to learn more about this. – Pratyush Panshikar Apr 04 '18 at 20:15