Integer compareTo() method, does it always return -1, 0 or 1?

115 views Asked by At

The javadocs for the method compareTo() of the Integer class are extremely vague:

Returns: the value 0 if this Integer is equal to the argument Integer; a value less than 0 if this Integer is numerically less than the argument Integer; and a value greater than 0 if this Integer is numerically greater than the argument Integer (signed comparison)

The phrasing "a value less than 0" makes it seem like I can expect compareTo() to return all sort of negative integers (-1, -20, -9999, etc). Same for "a value greater than 0", it could really be anything above 0.

I noticed the method tends to return -1 and 1, however from the javadocs there is no guarantee that this behavior will be consistent. All I'm allowed to expected is an integer less than 0 or greater than 0, which could really be anything.

Does the function indeed always return -1, 0, or 1? Or does it occasionally return other values?

If it only returns -1, 0, and 1, why is that not clearly stated in the javadocs?

Example:

Integer myInteger = 8;
System.out.print(myInteger.compareTo(5));
// This prints 1

EDIT:

Interestingly, IntelliJ acts as if compareTo() always returns -1, 0, or 1. That is, if you have the following code:

public int myCompare(int x, int y){
    if(x == y){
        return 0;
    } else if(x < y){
        return -1;
    } else{
        return 1;
    }
}

IntelliJ will give the warning "Expression can be replaced with 'Integer.compare'", and recommend the method be changed to:

public int myCompare(int x, int y){
    return Integer.compare(x, y);
}
3

There are 3 answers

1
Stephen C On BEST ANSWER

It is (IMO) unlikely that they will change the implementation of Integer. However the spec for Integer.compareTo does not state that the result is -1, 0 or +1 ... so they >could< change it. And if they do, then your code that relied on it would break.

So if I want to guarantee it returns -1, 0 or 1, I have to wrap it with a Integer.signum()?

Correct. Or implement your own Comparator or compareTo method ... if that is viable.

If you are concerned about performance, there is a good chance that the JIT compiler will inline signum(compareTo(anInteger)). It may even optimize away the redundant signum logic ...

If it only returns -1, 0, and 1, why is that not clearly stated in the javadocs?

We can't speak for the people who wrote the spec. However, I imagine that they didn't want to preclude the possibility of changing the implementation; e.g. for (hypothetical) performance reasons.

6
Bohemian On

-1 and 1 are chosen for readability, convention and correctness.

For objects that are compared using an integer value, returning the difference of that value would seem to make for a simpler implementation, eg

int compareTo(MyClass that) {
    return myInt - that.myInt;
}

however integer overflow can result in returning an incorrect result. Consider when this.myInt is a large positive number and that.myInt is a large negative number - the arithmetic result may be more than Integer.MAX_VALUE which would then roll around to be a negative number, which would be wrong.

Whatever the implementation, don't rely on anything but the contract - ie "any int" may be returned.

0
Dorian Gray On

I suppose they didn't specify it because the exact return value is completely irrelevant to the user. They kept it concise.

You rarely call that function yourself. It is mostly used to sort a list.

Also they can change it at any time (very unlikely but possible).