Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my simple comparator broken?

I have a class, which I have simplified to this:

final class Thing {
    private final int value;
    public Thing(int value) {
        this.value = value;
    }
    public int getValue() {
        return value;
    }
    @Override public String toString() {
        return Integer.toString(value);
    }
}

I want to sort an array of this thing. So I have created a simple copmarator:

private static final Comparator<Thing> reverse = new Comparator<Thing>() {
    public int compare(Thing a, Thing b) {
        return a.getValue() - b.getValue();
    }
};

I then use the two argument form of Arrays.sort.

This works fine for my test cases, but sometimes it goes all wrong with the array ending up in a strange but repeatable order. How can this be?

like image 633
Tom Hawtin - tackline Avatar asked Mar 03 '09 23:03

Tom Hawtin - tackline


People also ask

What do comparators return?

A comparator is a function that takes two arguments x and y and returns a value indicating the relative order in which x and y should be sorted. It can be a 3-way comparator returning an integer, or a 2-way comparator returning a boolean.

How do Java comparators work?

Comparator , represents a component that can compare two objects so they can be sorted using sorting functionality in Java. When sorting e.g a Java List you can pass a Java Comparator to the sorting method. The Comparator is then used to compare the objects in the List during sorting.


1 Answers

Integer overflow… or more precisely, underflow.

Instead, do an explicit comparison:

private static final Comparator<Thing> reverse = new Comparator<Thing>() {
    public int compare(Thing a, Thing b) {
      int av = a.getValue(), bv = b.getValue();
      return (av == bv) ? 0 : ((av < bv) ? -1 : +1);
    }
};

Using subtraction is fine if you are sure that the difference won't "wrap around". For example, when the values in question are constrained to be non-negative.

like image 78
erickson Avatar answered Sep 30 '22 20:09

erickson