I recently came across a comparator that on the surface looks incorrect. However, I’ve been unable to come up with an input to it that causes the comparator to produce the wrong result.
It incorrectly treats values as equal if o1 <= o2, and correctly returns 1 if o1 > o2.
I’ve tried to simplify the scenario as much as possible below. Can anyone either:
- Explain why this is ok.
- Produce an input array that causes it to sort the output incorrectly.
I’ve experimented with it quite a a bit and I’m throwing in the towel!
package comparator;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class BadComparator implements Comparator<Integer>
{
public int compare(Integer o1, Integer o2)
{
// Generally Accepted implementation
//return o1 - o2;
// Incorrect(?) Implementation
return (o2 < o1) ? 1 : 0;
}
public static void main(String[] args)
{
List<Integer> intList = Arrays.asList(10, 9, 8, 1, 2, 3, 7, 4, 5, 6);
Collections.sort(intList, new BadComparator());
System.out.println(intList);
}
}
Collections.sort is implemented as mergesort. looking at the source, all compare conditions are
>0or<=0which by chance treat the negative case the same as the equal case. a different sort implementation can fail.Per jbellis’s comment, “It’s not quite “just luck,” though — Collections.sort is guaranteed to be “stable,” meaning that equal elements must be in the same relative order post-sort. I’m not sure it’s impossible to come up with a stable sort implementation that fails with this comparator, but I can’t think of one off the top of my head.“