Java Integer compareTo () - зачем использовать сравнение против вычитания? - PullRequest
76 голосов
/ 28 апреля 2010

Я обнаружил, что java.lang.Integer реализация метода compareTo выглядит следующим образом:

public int compareTo(Integer anotherInteger) {
    int thisVal = this.value;
    int anotherVal = anotherInteger.value;
    return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
}

Вопрос в том, зачем использовать сравнение вместо вычитания:

return thisVal - anotherVal;

Ответы [ 5 ]

90 голосов
/ 28 апреля 2010

Это связано с целочисленным переполнением. Если thisVal очень велико и anotherVal отрицательно, то вычитание последнего из первого дает результат, который больше thisVal, который может перетекать в отрицательный диапазон.

62 голосов
/ 28 апреля 2010

Вычитание "хитрость" для сравнения двух числовых значений нарушено !!!

        int a = -2000000000;
        int b =  2000000000;
        System.out.println(a - b);
        // prints "294967296"

Здесь a < b, но a - b положительно.

НЕ используйте эту идиому. Это не работает.

Более того, , даже если он работает , он НЕ обеспечит какое-либо значительное улучшение производительности и может фактически стоить читабельности.

Смотри также

  • Java Puzzlers Головоломка 65: Странная сага подозрительного рода

    Эта головоломка имеет несколько уроков. Наиболее конкретным является: Не используйте компаратор на основе вычитания, если вы не уверены, что разница между значениями никогда не будет больше, чем Integer.MAX_VALUE. В целом остерегайтесь переполнения int. Другой урок заключается в том, что вам следует избегать «умного» кода. Старайтесь писать ясный, правильный код и не оптимизируйте его, если в этом нет необходимости.

9 голосов
/ 28 апреля 2010

Проще говоря, тип int недостаточно велик, чтобы хранить разницу между двумя произвольными значениями int. Например, разница между 1,5 млрд. И -1,5 млрд. Составляет 3,0 млрд., Но int не может содержать значения, превышающие 2,1 млрд.

3 голосов
/ 28 апреля 2010

Возможно, чтобы избежать переполнения / недостаточного заполнения.

1 голос
/ 28 апреля 2010

В дополнение к функции переполнения, вы должны заметить, что версия с вычитанием не дает таких же результатов .

  • Первая версия CompareTo возвращает одно из трех возможных значений: -1, 0 или 1.
  • Если заменить последнюю строку вычитанием, результатом может быть любое целочисленное значение.

Если вы знаете, что переполнения не будет, вы можете использовать что-то вроде этого:

public int compareTo(Integer anotherInteger) {
    return sign(this.value - anotherInteger.valuel);
}
...