Как избежать хранения дубликатов в наборе, если тип объектов исходит из скомпилированного файла .class?

Я пытаюсь сохранить объекты в наборе, чтобы избежать дублирования.

Как объясняется в этой теме Мне нужно @Override два метода: hashCode() и equals(Object obj).

Тип объектов, который я пытаюсь сохранить в приведенном выше Set, взят из скомпилированного файла .class и не имеет hashCode() и equals(Object obj), а также его родителей в цепочке наследования (кроме Object).

Есть ли способ сохранить их в наборе, чтобы избежать дублирования?


person Robert    schedule 05.02.2021    source источник


Ответы (1)


Если вы не можете изменить объекты, вы можете обернуть их.

class EmployeeHolder {
  private final Employee employee;
  public int hashCode() { ... }
  public boolean equals(Object o) {
    if (!(o instanceof EmployeeHolder)) return false;
    ...
  }
}
Set<EmployeeHolder> set = new HashSet<>();
person Louis Wasserman    schedule 05.02.2021
comment
Я понимаю, что у меня будет Set‹EmployeeHolder› для использования его методов hashCode() и equals(Object o), но в конце концов мне понадобится Set‹Employee›. После заполнения Set‹EmployeeHolder› мне нужно будет пересечь его, чтобы извлечь каждого сотрудника. Если это правильно, есть ли более эффективный способ сделать это? - person Robert; 06.02.2021
comment
Нет, нет. Но зачем вам нужен Set<Employee>? Что вы можете сделать с ним, чего не можете сделать с Set<EmployeeHolder>? - person Louis Wasserman; 06.02.2021
comment
Set<Employee> realSet = oldSet.map(EmployeeHolder::getEmployee).collect(Collectors.toSet()); Для этого потребуется геттер в классе держателя Employee. В качестве альтернативы вы можете продублировать методы в своем классе Employeeholder, чтобы они соответствовали методам класса Employee. Когда эти методы вызываются, просто передайте вызов экземпляру Employee и верните результат. - person WJS; 06.02.2021
comment
@LouisWasserman Я провел некоторый рефакторинг и все еще использую некоторые методы устаревшего кода. Эти методы используют определенный формат данных Employee в данном случае. @WJS В первой части вашего ответа я не просил решения для сопоставления. Что касается второй части вашего ответа, как я объяснил выше, я не могу избавиться от Employee, потому что он все еще используется в устаревшем коде, с которым я имею дело. - person Robert; 06.02.2021
comment
Если вы можете жить с поиском O (log n), а не с поиском O (1), вы можете использовать TreeSet с пользовательским компаратором. В качестве альтернативы вы можете создать подкласс AbstractSet<Employee>, который делегирует HashSet<EmployeeHolder> для add, size() и contains, проверяет и реализует такие методы, как iterator(), используя шаблон, показанный @WJS. Вам нужны только метод size() и iterator(), чтобы получить действительную реализацию Set, add, чтобы сделать его изменчивым, но contains уже является хорошей оптимизацией. Это так просто. - person Holger; 09.02.2021