Как уже упоминалось, можно принять следующие три решения:
- использовать неизменяемые предметы; даже когда ваш класс изменчив, вы можете использовать неизменные идентификаторы в вашей
hashcode
реализации и equals
проверке, например, в виде идентичного значения.
- Аналогично приведенному выше, реализуйте
add
/ remove
, чтобы получить клон вставленного объекта, а не фактическую ссылку. HashSet
не предлагает функцию get
(например, чтобы позже вы могли изменить объект); таким образом, вы в безопасности, дубликатов не будет.
- Соблюдайте дисциплину, не меняя их после того, как они были использованы, как @ Джон Скит предлагает
Но, если по какой-то причине вам действительно нужно изменить объекты после вставки в HashSet
, вам нужно найти способ «информировать» вашу Коллекцию о новых изменениях. Для достижения этой функциональности:
- Вы можете использовать шаблон проектирования Observer и расширить
HashSet
для реализации интерфейса Observer
. Ваши Member
объекты должны быть Observable
и update
HashSet
на любом сеттере или другом методе, который влияет на hashcode
и / или equals
.
Примечание 1: Расширение 3 с использованием 4: мы можем принимать изменения, но те, которые не создают уже существующий объект (например, я обновил идентификатор пользователя, назначив новый идентификатор, не устанавливая его для существующего). В противном случае вы должны рассмотреть сценарий, в котором объект трансформируется таким образом, что теперь он равен другому объекту, уже существующему в Set
. Если вы примете это ограничение, 4-е предложение будет работать нормально, иначе вы должны проявлять инициативу и определять политику для таких случаев.
Примечание 2: Вы должны предоставить как предыдущее, так и текущее состояние измененного объекта в вашей реализации update
, потому что вы должны сначала удалить более старый элемент (например, использовать getClone()
перед установкой новых значений), затем добавить объект с новым состоянием. Следующий фрагмент является лишь примером реализации, он требует изменений в зависимости от вашей политики добавления дубликата.
@Override
public void update(Observable newItem, Object oldItem) {
remove(oldItem);
if (add(newItem))
newItem.addObserver(this);
}
Я использовал аналогичные методы в проектах, где мне требуется несколько индексов для класса, поэтому я могу посмотреть с помощью O (1) для Наборов объектов, которые имеют общую идентичность; представьте его как MultiKeymap из HashSets (это действительно полезно, так как вы можете затем пересекать / объединять индексы и работать аналогично поиску, подобному SQL). В таких случаях я аннотирую методы (обычно сеттеры), которые должны fireChange-обновить каждый из индексов, когда происходит значительное изменение, поэтому индексы всегда обновляются с последними состояниями.