карта дерева использует compareTo вместо equals для containsKey()

Я пытаюсь использовать метод containsKey метода TreeMap, но почему-то у меня с ним проблемы.

Объекты, хранящиеся в карте дерева, определены таким образом, что equals() не дает того же результата, что и compareTo(). это предназначено.

Однако документ java.util.Map говорит:

Возвращает true, если эта карта содержит сопоставление для указанного ключа. Более формально, возвращает true тогда и только тогда, когда эта карта содержит отображение для ключа k такого, что (key==null ? k==null : key.equals(k)). (Таких отображений может быть не больше одного.)

Итак, я попробовал следующее:

c = someModifiedObject();
boolean t1 = sm.containsKey(c);
someObject c2 = new someObject();
boolean t2 = sm.containsKey(c2);
boolean t3 = c.equals(new Chain());
int t4 = c.compareTo(new Chain());

t1 истинно, так как объект находится в древовидной карте. t3 истинно, так как t1 равно t3 (относительно оператора изменения equals()) t4 ложно, однако t2 также ложно. Кажется, что TreeMap использует compareTo(), а не equals(), чтобы определить, присутствует ли объект.

Есть ли другая реализация отсортированной карты, где я могу использовать equals() для проверки существования объекта?


person user3320142    schedule 17.02.2014    source источник
comment
Используйте Comparator, который делает compareTo согласованным с equals, или, что еще лучше, исправьте метод compareTo, чтобы он согласовывался с equals. Метод сравнения, который не согласуется с равными, скорее должен быть реализован как компаратор, а не как естественное упорядочение, присущее классу.   -  person JB Nizet    schedule 17.02.2014
comment
Но в документации также говорится: Многие методы в интерфейсах Collections Framework определяются в терминах метода equals. Например, спецификация метода containsKey(Object key) гласит: [слишком длинно, чтобы соответствовать комментарию, но это определение, которое вы дали] Эта спецификация не должна толковаться как подразумевающая, что вызов Map.containsKey с ненулевым аргументом key приведет к вызову key.equals(k) для любого ключа k. Реализации могут свободно реализовывать оптимизации, позволяющие избежать вызова equals, например, сначала сравнивая хэш-коды двух ключей.   -  person Alexis C.    schedule 17.02.2014
comment
Почему в зеленой земле &божества вы хотите, чтобы compareTo и equals не реагировали одинаково??? (И имейте в виду, что любой упорядоченный набор будет использовать относительное сравнение для установления относительного положения сущностей в наборе, поэтому естественно используется compareTo. Вам нужно будет использовать неупорядоченный набор для equals, чтобы быть логичным.)   -  person Hot Licks    schedule 17.02.2014
comment
@HotLicks: предположим, что класс имеет два поля типа BigDecimal и хочет выполнить сортировку по первому и подсортировать по второму (для значений, которым соответствует первое поле). Чтобы разрешить (1.00, 2.0) сортировать между (1.0, 1.0) и (1.0, 3.0), необходимо, чтобы реляционный компаратор для BigDecimal игнорировал точность [количество нулей после запятой]. С другой стороны, даже если 1,00 не выше и не ниже 1,0, это не значит, что его следует считать эквивалентным.   -  person supercat    schedule 18.02.2014
comment
@supercat - сравнение и равенство должны быть согласованы. Если вам нужны другие операторы сравнения, назовите их по-другому.   -  person Hot Licks    schedule 18.02.2014
comment
@HotLicks: ожидается, что метод compareTo будет использоваться для сортировки; метод equals используется для проверки эквивалентности. Поведение, необходимое для двух заданий естественно, будет в значительной степени совпадать, но когда они расходятся, compareTo лучше вести себя так, как наиболее подходит для сортировки, а equals вести себя так, как наиболее подходит для эквивалентности. тестирования, чем заставить любой из этих способов вести себя таким образом, который на самом деле не подходит для его основной задачи.   -  person supercat    schedule 18.02.2014
comment
Они не должны расходиться.   -  person Hot Licks    schedule 18.02.2014
comment
containsKey будет использовать compareTo для поиска ключей-кандидатов. Возвращает true, когда для ключа-кандидата compareTo == 0 и он равен искомому ключу. Возможно, у вас есть аргументы в пользу floorEntry (ключ) или что-то подобное.   -  person Joop Eggen    schedule 30.01.2018


Ответы (1)


Несмотря на то, что не существует стандартного java API, чтобы точно получить то, что вы хотите, вы можете создать свой собственный интерфейс Comparator, а затем заставить свой TreeMap реализовать этот Comparator. Вы можете переопределить метод compareTo(), чтобы он вел себя так, как вы хотите (в вашем случае заставьте его вести себя так же, как метод equals()).

person ucsunil    schedule 17.02.2014