Ответ
При генерации hashCode() через Lombok (@EqualsAndHashCode) критически важно соблюдать его контракт, особенно связь с equals():
Основной контракт (из Object.hashCode()):
- Согласованность с equals(): Если
x.equals(y) == true, тоx.hashCode() == y.hashCode()обязательно. - Обратное не обязательно: Равные хеш-коды не гарантируют равенство объектов (возможна коллизия).
- Согласованность во времени: Хеш-код должен оставаться постоянным для неизменяемого объекта в рамках одного выполнения приложения.
Практические рекомендации для Lombok:
- Lombok гарантирует пункт 1, генерируя оба метода из одного набора полей.
- Используйте неизменяемые или стабильные поля. Если поле, участвующее в
hashCode(), может измениться, объект станет «невидим» для хеш-коллекций.@EqualsAndHashCode public class BadExample { private List<String> tags; // Изменение списка сломает хеш-код! } - Для изменяемых полей используйте
onlyExplicitlyIncluded = trueили@EqualsAndHashCode.Exclude.
Пример безопасного подхода:
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class User {
@EqualsAndHashCode.Include
private final Long id; // Идеальный кандидат: неизменяемый и уникальный
private String name; // Не участвует, может меняться
}
Почему важно: Нарушение контракта hashCode()/equals() приводит к потере объектов в HashSet или HashMap.