| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java EE (J2EE) и Spring > Проверить объекты на equals |
| Автор: garbuz 26.9.2009, 04:09 | ||||
Есть код, который достает из базы через хибернейт два оъекта - юзера и проджект. У проджекта есть коллекция юзеров. Перед добавление пользователя в проект, проверяю его наличие в этом проекте, хотя даже если такой пользователь имеется, то все равно происходит добавление.
Судя по дебаггеру, не срабатывает
У проджекта коллекция юзеров проинициализирована. Пробовал проверять объекты юзеров из проджекта на equals с текущим пользователем, тоже нифига не equals. В чем дело? Объекты разные получаются? У объектов поля одинаковые, хотя как у одного, так и у другого есть не проинициализированные поля. У энтити юзер нет ни метода hashCode ни equals. Может в них дело? Спасибо. |
| Автор: Galaran 26.9.2009, 08:18 | ||
| contains не срабатывает, так как надо метод equals() переопределить у класса юзер, иначе оно использует equals() класса Object, который просто по ссылке сравнивает. Когда будешь писать сравнение для юзеров, не наткнись на то, что я недавно напоролся. А именно, если id у тебя там Long (не long), и ты сравниваешь по нему, надо сначала взять значение у этих лонгов, иначе по ссылке будет. Примерно так:
|
| Автор: garbuz 26.9.2009, 17:24 | ||
| Парсер лохе! Первый раз не отправил мое сообщение Galaran, спасибо за совет, так и думал сделать, однако вчера на это не хватило сил (5-ый час). Сделал сегодня - не работает. Дело в том, что при получении дочерней коллекции из объекта, вытащенного с пом хибернейт, мы получаем объект PersistentSet, где метод contains почему-то не работает. На это есть даже баг в джире http://opensource.atlassian.com/projects/hibernate/browse/HHH-2634 и пара тем на форумах https://forum.hibernate.org/viewtopic.php?t=965543, https://forum.hibernate.org/viewtopic.php?t=928172, которые пока не прочитал
Думаю есть более красивое решение |
| Автор: MisterCleric 28.9.2009, 15:01 | ||
А какая версия hibernate? А то я как-то не задумывался о том, что они могут не работать и так все и сделал у себя как здесь описано (давно уже...). Взял переопределил методы equals & hashCode и все нормально работает на contains |
| Автор: magicfly 28.9.2009, 16:40 | ||||
| Привет, ну во первых можно использовать не обычный итератор а дженерик итератор, во вторых, не мешало бы переопределить и хеш код ( когда переопределяешь иквелс лучше сразу и переопределелять хеш код), в третьих небольшое замечание насчет сравнения лонгов как было написано
Проверил, PersistentSet есть Wrapper вокруг HashSet'a следовательно еще необходимо как было сказано переопределить HashCode |
| Автор: Dims 28.9.2009, 16:44 |
| Вообще-то, чтобы объекты правильно хранились в коллекции, в общем случае, нужно переопределять не только equals, но и hashCode. Добавлено @ 16:48 Потому что, например, класс HashSet определяет расположение объектов по хэшкоду, то есть, сравнение хэшкодов используется как быстрая (но неточная) операция сравнения. И только когда хэшкоды совпали, при необходимости, вызывается медленная проверка с помощью equals. Возможно, в ваших функциях тоже где-то в глубине используется хэшкод. Вообще, есть, можно сказать правило: переопределил equals -- переопредели hashCode. |
| Автор: garbuz 28.9.2009, 17:27 |
| Ок, домой приду - поробую переопределить hashCode. А может еще кто скажет как правильно его переопрделять? Мне собственно никогда не приходилось делать это. IDE сама генерит. На нее можно положиться? |
| Автор: magicfly 28.9.2009, 17:56 |
| http://www.geocities.com/technofundo/tech/java/equalhash.html Смотря как она это делает. Грубо говоря ты (вы?) можешь использовать те поля по которым идет сравнение и для вычисления hashCode, т.е. равные объекты имеют одинаковый хеш код, разные -разный. Однако на больших массивах данных это не оптимально. Советую посмотреть как работают хеш коллекции для большего понимания. Насколько я помню это есть в "thinking in java" |
| Автор: Dims 28.9.2009, 18:33 |
Ну я обычно для составного объекта генерю хэшкод так: беру хэшкоды всех членов и произвожу над ними исключающее побитовое "или". Если это встроенный тип int, то я ксорю прямо его значение. Если другой, то сперва преобразую в ссылочный и беру его hashCode. Надо учитывать, что если хэшкод для объекта не переопределён, то это будет нечто вроде адреса в памяти, то есть, число отличающееся у идентичных, но разных объектов (например, у объекта и его клона). Поэтому может потребоваться переопределить хэшкоды для членов тоже. До абсурда доводить не надо. На каком-то уровне вполне может подойти стандартная функция от Обжекта. |
| Автор: garbuz 28.9.2009, 22:24 | ||
Вот что выдала IDEA. Пойдет?
Проверил - работает! Всем спасибо за помощь |
| Автор: MisterCleric 28.9.2009, 22:38 | ||
Galaran,
Высказывание не верно: все обертки простых типов + String являются http://www.google.com.ua/search?q=java+immutable: каждый раз создается новый объект. И говорит о том, что будет сравнение по ссылке не верное. У них как раз методы equals такие, что берутся на сравнеие их значение простых типов. посмотрите исходники |
| Автор: magicfly 28.9.2009, 23:15 | ||||
Хотелось бы заметить это не совсем правда.
вернет одинаковые ссылки т.е. i==j. И для Integer"ов до 128 ссылки тоже будут равны,т.е.
выведет true false |
| Автор: MisterCleric 29.9.2009, 09:16 | ||||||
А я как раз говорю о том, что не надо брать это значение, если используем метод equals, а не сравниваем их перегруженным для этого оператором "==" Вот пример метода класса Long
Мы обсуждаем метод equals, а не оптимизацию интерпретатора для констант по 128 |
| Автор: magicfly 29.9.2009, 10:16 | ||
Я лишь указал на промахи, в частности на
Из immutable не следует что каждый раз создается один объект и сравнение по ссылке временами бывает верным |