Comparing integers using Integer.compare vs subtraction

04 August 2015

TL;DR: Use Integer.compare to avoid overflow that can occur when subtracting two integers.

I took Oracle’s Java 8 MOOC: Lamdbas And Streams class. I had a question about using Integer.compare that arose from one of the homework questions. I am recording the question and answer here so I can find it easily in the future, instead of having it buried in a thread about a homework assignment using the Streams API. The original post is on the Oracle community forums.

My question was:

My answers were pretty similar to what has already been posted. However, for the sort in question 7 I did:

 .sorted((word1, word2) -> Integer.compare(word1.length(), word2.length()))

whereas most implementations in this thread have done something like:

 .sorted((word1, word2) -> word1.length() - word2.length())

Is there any advantage to using subtraction vs using the Integer.compare method? Or is just different ways of doing the same thing?

The reply from Stuart Marks-Oracle was:

For this particular problem, there is essentially no difference. However, there are cases when comparing integers, where writing a comparator that simply subtracts the two values can fail to produce the right answer. Consider the following:

List<Integer> list = Arrays.asList(Integer.MAX_VALUE, -1, 0, 1, Integer.MIN_VALUE);  
list.sort((i1, i2) -> i1 - i2);  
System.out.println(list);  
  
// output  
[-1, 0, 1, 2147483647, -2147483648]  

This is clearly wrong. Can you see why? Overflow, that’s why! When comparing numbers of extreme magnitude, such as MAX_VALUE and -1, these are subtracted, giving a result with the wrong sign. That’s why the sorting fails in the case. The correct way to compare integers is, as you note, using Integer.compare():

List<Integer> list = Arrays.asList(Integer.MAX_VALUE, -1, 0, 1, Integer.MIN_VALUE);  
list.sort(Integer::compare);  
System.out.println(list);  
  
// output       
[-2147483648, -1, 0, 1, 2147483647]  
 

There’s nothing magical about Integer.compare(). It’s basically a conditional expression that uses comparison operations instead of subtraction:

	return (x < y) ? -1 : ((x == y) ? 0 : 1);  

In the exercise, string lengths are always non-negative, so subtracting them cannot result in overflow. However, I always recommend using Integer.compare(), so that you don’t have to prove that overflow cannot occur.

The kofi logo of a coffee mugLike this? Please buy me a coffee!

Share