Я недавно работал над основной задачей, которая включала в себя сет, и я наткнулся на любопытную проблему. У меня есть следующий класс:
public static class Quadruple {
int a;
int b;
int c;
int d;
Map<Integer, Integer> histogram;
public Quadruple(int a, int b, int c, int d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.histogram = new HashMap<>();
histogram.put(a, histogram.get(a) == null ? 1 : histogram.get(a) + 1);
histogram.put(b, histogram.get(b) == null ? 1 : histogram.get(b) + 1);
histogram.put(c, histogram.get(c) == null ? 1 : histogram.get(c) + 1);
histogram.put(d, histogram.get(d) == null ? 1 : histogram.get(d) + 1);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Quadruple)) {
return false;
}
Quadruple q = (Quadruple) obj;
return q.histogram.equals(this.histogram);
}
@Override
public int hashCode() {
return Objects.hash(a, b, c, d);
}
Когда я инициализирую 2 объекта этого типа, вот так:
Quadruple q1 = new Quadruple(1, 1, 1, 2);
Quadruple q2 = new Quadruple(1, 1, 2, 1);
q1.equals (q2) возвращает true, но оба объекта могут быть добавлены в HashSet отдельно.
Теперь из контракта HashSet я понимаю, что если объект, который вы пытаетесь добавить, равен () уже существующему объекту, его следует считать существующим, и ничего не следует делать.
Мне удалось обойти эту проблему, используя LinkedList и проверяя, содержит ли список () объект перед его добавлением, что, похоже, работает соответствующим образом.
Мой вопрос в том, нормально ли это поведение, когда я проверил базовую реализацию и увидел, что HashMap, который используется в HashSet, на самом деле проверяет значения с помощью equals (). Есть ли что-то, что я могу упустить?