BigDecimal.equals() сравнивает scale, compareTo() — нет
new BigDecimal("2.0") и new BigDecimal("2.00") математически одно и то же число. equals() у BigDecimal считает их разными — метод сравнивает и unscaledValue, и scale одновременно. 2.0 хранится как unscaledValue=20, scale=1; 2.00 — unscaledValue=200, scale=2. Разные пары — equals() возвращает false.
compareTo() устроен иначе: он сравнивает только числовые значения, scale игнорируется. Для тех же двух чисел compareTo() вернёт 0 — они равны по величине.
Проблема всплывает там, где BigDecimal кладут в HashSet или используют как ключ HashMap: contains() и get() построены на equals()+hashCode(), а не на compareTo(). Дедупликация сумм с разным количеством нулей после запятой молча не срабатывает.
BigDecimal a = new BigDecimal("2.0"); BigDecimal b = new BigDecimal("2.00");
a.equals(b); // false
a.compareTo(b) == 0; // true
Спросят следом: как нормализовать перед сравнением. stripTrailingZeros() убирает незначащие нули, но меняет scale непредсказуемо для целых чисел вроде 200 → 2E+2. Надёжнее явно задавать scale через setScale() перед equals(), либо изначально не использовать BigDecimal как ключ коллекции, построенной на equals().
Для сортированных структур (TreeMap, TreeSet) это не проблема — они используют compareTo(). Ловушка живёт именно в hash-based коллекциях.
Тренажёр: 600 вопросов, мок с таймером, план повторов
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки