Мы пишем класс, который требует очень сложной логики для вычисления equals() и hashCode(). Что-то вдоль линий с:
@Getters @Setters @FieldDefaults(level=AccessLevel.PRIVATE)
public class ExternalData {
TypeEnum type;
String data;
List<ExternalData> children;
}
Мы не создаем эти объекты, они десериализуются из XML из внешней сложной системы. Существует 20 типов и в зависимости от типа данных можно игнорировать или обрабатывать с детьми или обрабатывать без детей, а сравнение данных для каждого типа node зависит от типа.
Мы создали equals() и hashCode(), чтобы отразить все эти правила, но в последнее время столкнулись с проблемой, из-за которой hashCode вышел из синхронизации с равными, в результате чего равные объекты добавляются дважды в HashSet. Я считаю, что HashMap (и HashSet в этом отношении) реализованы таким образом в Java: https://en.wikipedia.org/wiki/Hash_table Реализация сначала помещает объекты в ведра на основе hashCode а затем для каждого ведра проверяется равным. В неудачном сценарии, когда 2 равных объекта перейдут в разные ведра, они никогда не будут сравниваться с помощью equals(). Под "вне синхронизации" здесь я имею в виду, что они входят в разные ведра.
Каков наилучший способ убедиться, что equals и hashCode не выходят из синхронизации?
Edit: Этот вопрос отличается от Какие проблемы следует учитывать при переопределении равных и hashCode в Java? Там они спрашивают об общих рекомендациях, и принятый ответ не применяется в моей ситуации. Они говорят, что "сделать равенства и hashCode последовательными", здесь я спрашиваю, как именно я это делаю.