Учитывая такой класс:
class MyObject {
private String id1;
private String id2;
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof MyObject)) {
return false;
}
MyObject other = (MyObject) o;
return id1.equals(other.id1) || id2.equals(other.id2);
}
}
Обратите внимание, что равенство не зависит от соответствия обоих полей, любое из полей работает. Какая реализация hashCode была бы подходящей для этого класса?
@Andreas, вы могли бы использовать минимум два.
@AndyTurner Нет, не можешь. ["A", "B"] vs ["C", "B"] равны, но младший хэш-код - нет.
@Andreas Хм, верно. Что ж, вы можете использовать константу ...
@Andreas, но определенно это определение равенства нарушает общий договор о равенстве (в частности, транзитивность).
@AndyTurner Верно, но константа - это не хэш-код. Это будет работать, но в основном превращает HashMap в LinkedList.




Это недопустимая реализация equals.
В частности, это нарушает требование транзитивности.
Таким образом, вы также не можете реализовать hashCode «правильно», за исключением того, что все экземпляры будут иметь один и тот же хэш-код.
Спасибо. В этом есть смысл.
Я расширил HashSet <String> и реализовал add и contains для работы с этим. Звучит здесь как правильный ход?
@mkohram, расширяющий HashSet никогда, кажется правильным, особенно если вы меняете поведение существующих методов.
Как еще вы удалили бы дубликат списка этих объектов?
Также я не меняю поведение. Просто добавил add(MyObject o) и contains(MyObject o) к HashSet<String>.
Это все еще звучит так, как будто это не сработает. Вместо этого сделайте, например, Map<String, MyObject> mapFromId1 и Map<String, MyObject> mapFromId2 и проверяйте их оба для каждого нового объекта.
@LouisWasserman, вот как в основном выглядят реализации моих add и contains. Он просто абстрагирован, поэтому каждый раз, когда я хочу «добавить» MyObject в набор, мне не нужно делать 2 вставки. Спасибо.
Вы, не должен, делаете эту абстракцию, а не в том, что притворяется HashSet или Set вообще. Set должны отражать только поведение equals и верный, при этом удовлетворяющее контракту поведение equals.
@LouisWasserman Я понимаю, о чем вы говорите. Итак, каждый раз, когда я хочу проверить contains в Map, о котором вы говорили, я бы сделал 2 (или более) проверки кода? Это много повторяющегося кода.
Или создайте свой собственный класс, который выполняет эти операции за вас, но не претендует на роль Set.
Спасибо, вот что я сделаю.
Я не верю, что есть какой-либо хэш-код, который можно использовать для этого.