Я использую java.util.Set интерфейс с java.util.HashSet реализацией и сохраняю его на карте.
Я добавляю объект в Set, затем снова получаю объект Set и могу добавить еще один объект, равный первому.
При добавлении, казалось бы, равных объектов, Set.add возвращает true
, и два равных объекта сохраняются в HashSet. Как это возможно и что я могу сделать, чтобы исправить это явное нарушение контракта Set?
Я использую Java 12 через IntelliJ IDEA 2018.3.6 и проверил мою java.lang.Object.hashCode реализацию класса двух объектов, которые я добавляю в Set, причем оба возвращают тот же хеш-код. Я также проверил реализацию java.lang.Objects.equals , и она возвращает true
, когда метод используется для проверки их равенства. Оба объекта обернуты в другой объект, Entity, но он только перенаправляет реализации hashCode
и equals
объектов.
class Model {
...
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Offer)) {
return false;
}
Offer offer = (Offer) obj;
return Objects.equals(id, offer.id)
&& Objects.equals(name, offer.name)
;
}
@Override
public int hashCode() {
int result = 1;
result = 31 * result + Objects.hashCode(id);
result = 31 * result + Objects.hashCode(name);
return result;
}
...
}
class Store {
...
private static class Entry {
Object value;
Entry(Object value) {
this.value = value;
}
Object getValue() {
return value;
}
@Override
public boolean equals(Object obj) {
return Objects.equals(value, obj);
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
public String toString() {
return "Entry[value = " + value + "]";
}
}
...
private Map<Class<?>, Set<Entry>> data;
...
private Set<Entry> get(Class<?> type) {
return data.getOrDefault(type, new HashSet<>());
}
@Override
public void persist(Object obj) {
Entry entry = new Entry(obj);
Set<Entry> objects = get(obj.getClass());
if (objects == null) {
objects = new HashSet<>();
}
if (!objects.add(entry)) {
throw new ObjectExistsException
("Object already exists: " + obj);
}
data.put(obj.getClass(), objects);
}
...
}
Когда obj1
и obj2
типа Model равны и objects
уже содержит obj1
, обернутый в объект Entry, я ожидаю, что obj2
не будет добавлен к objects
, когда obj2
обернут в entry
и для objects.add(entry)
, чтобы вернуть false
, затем выдается исключение ObjectExistsException.
Однако в действительности objects.add(entry)
возвращает true
, а obj2
, завернутый в entity
, добавляется к objects
.