Реализация интерфейса компаратора в Java - PullRequest
1 голос
/ 18 марта 2012

Когда вы реализуете интерфейс Comparator в Java, нужно ли переписывать метод equals? Компилятор Java не жалуется, если я не делаю этого. Но это нормально делать?

Ответы [ 3 ]

2 голосов
/ 18 марта 2012

Интерфейс Comparator<SomeClass> реализован как отдельный класс для класса SomeClass.Нет необходимости, чтобы SomeClass.equals(Object) соответствовал компаратору.(Действительно, было бы в значительной степени побеждать цель иметь отдельный объект сравнения!)

С другой стороны, если SomeClass реализует Comparable<SomeClass>, то настоятельно рекомендуется , что equals(Object) и compare(SomeClass, SomeClass), чтобы быть последовательными.В javadoc для Comparable говорится следующее:

"Настоятельно рекомендуется (хотя и не обязательно), чтобы естественные упорядочения были совместимы с равными.наборы (и отсортированные карты) без явных компараторов ведут себя «странно», когда они используются с элементами (или ключами), естественное упорядочение которых несовместимо с равенством. В частности, такой отсортированный набор (или отсортированная карта) нарушает общий контракт для набора (или map), который определяется в терминах метода equals. "

" Например, если добавить два ключа a и b, например (!a.equals(b) && a.compareTo(b) == 0), к отсортированному набору, который выполняетЕсли не использовать явный компаратор, вторая операция добавления возвращает значение false (и размер отсортированного набора не увеличивается), поскольку a и b эквивалентны с точки зрения отсортированного набора. "


Компилятор Java не будет жаловаться, если я этого не сделаю.

Компилятор Java не может определить, совместимы ли equals и compare.(Или equals и hashcode в этом отношении.) Теоретически невозможно сделать это во всех случаях и за пределами "уровня техники" на практике.А простой тест, который вы переопределили equals, в некоторых случаях выдаст ложные предупреждения.

Вы не можете полагаться на компилятор, чтобы указать на логические ошибки в вашем приложении.


Если вопрос на самом деле касается семантики Comparable<T>.equals(Object), то ответ в javadocs:

"Обратите внимание, что всегда безопасно не переопределять Object.equals (ObjectОднако, переопределение этого метода может, в некоторых случаях, улучшить производительность, позволяя программам определять, что два разных компаратора устанавливают один и тот же порядок. "


Тед Хопп прокомментировал так:

"На самом деле, Comparator полезен для сортировки; нет причин, по которым согласование его с equals () могло бы« победить цель ». В общем, хорошая идея сделать их согласованными, хотя этоэто не требование. "

Во-первых, Тед неправильно истолковывает то, что я написал.Я сказал:

"Это ..." (то есть гипотетическое требование согласованности между T.equals (Object) и Comparator.compare (T, T) `" ... уничтожило бы цель иметь отдельный компаратор "

Во-вторых, это ни хорошая идея, ни плохаяИдея, чтобы компараторы были согласованы с равными. Это полностью зависит от предполагаемой семантики равных и предполагаемой цели компаратора.

  • Если компаратор используется для упорядочивания элементов в TreeSet, тогда несоответствие с equals приведет к странному поведению.

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

2 голосов
/ 18 марта 2012

JavaDoc для этого метода в интерфейсе компаратора говорит: «Обратите внимание, что всегда безопасно не переопределять Object.equals (Object). Однако переопределение этого метода может, в некоторых случаях, повысить производительность позволяя программам определять, что два разных компаратора устанавливают один и тот же порядок. "

В частности, обратите внимание, что метод equals() используется для сравнения другого Comparator с вашей реализацией Comparator, а не для проверки, равны ли два объекта шаблонного типа.

2 голосов
/ 18 марта 2012

A Comparator<T> - это объект, который помогает сравнивать два объекта типа T.Единственный метод, который вам необходимо реализовать, это compare(o1, o2).Указывает порядок для объектов класса T.
Это не требует переписывания метода equals, хотя для согласованности (и логики), если метод compare() компаратора возвращает 0 при сравнении двух объектов o1 и o2, o1.equals(o2) и o2.equals(o1)верните true.

Javadoc: Компаратор

...