Comparator через a - b — ловушка, которую не поймает юнит-тест

Классический способ написать компаратор для сортировки по числовому полю — вычесть одно значение из другого:

list.sort((a, b) -> a.getBalance() - b.getBalance());

Тест с балансами в разумном диапазоне проходит зелёным. Проблема появляется, когда значения близки к границам int: если a.getBalance() большое положительное, а b.getBalance() большое отрицательное, разность переполняется и меняет знак — компаратор врёт о порядке. Collections.sort может даже выкинуть IllegalArgumentException «Comparison method violates its general contract», потому что TimSort проверяет транзитивность.

Правильный вариант — Integer.compare() или Long.compare(): они сравнивают напрямую, без вычитания и переполнения.

list.sort((a, b) -> Integer.compare( a.getBalance(), b.getBalance()));

Ловушка: с double то же самое не лечится автоматически Double.compare() — если в данных встречается NaN, порядок всё равно может оказаться неожиданным, потому что Double.compare() трактует NaN как больше любого числа, включая Infinity. Если бизнес-логика не ожидает NaN в этом поле, баг просто переедет на уровень выше.

На собеседовании это вопрос не про синтаксис — это вопрос про то, проверяете ли вы граничные случаи, а не только happy path в тестах.

Тренажёр: 600 вопросов, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки