Замена элемента Java HashSet

У меня есть набор этой структуры. У меня нет дубликатов, но когда я звоню: set.add(element) → и есть уже точный элемент, я бы хотел, чтобы старый был заменен.

import java.io.*;

public class WordInfo implements Serializable {
    File plik;
    Integer wystapienia;

    public WordInfo(File plik, Integer wystapienia) {
        this.plik = plik;
        this.wystapienia = wystapienia;
    }

    public String toString() {
    //  if (plik.getAbsolutePath().contains("src") && wystapienia != 0)
            return plik.getAbsolutePath() + "\tWYSTAPIEN " + wystapienia;
    //  return "";
    }
    @Override
    public boolean equals(Object obj) {
        if(this == obj) return true;
        if(!(obj instanceof WordInfo)) return false;
        return this.plik.equals(((WordInfo) obj).plik);
    }

    @Override
    public int hashCode() {        
        return this.plik.hashCode();
    }
}

Ответ 1

Сделайте удаление перед каждым добавлением:

 someSet.remove(myObject);
 someSet.add(myObject);

Удалить удалит любой объект, который равен myObject. Кроме того, вы можете проверить результат добавления:

 if(!someSet.add(myObject)) {
     someSet.remove(myObject);
     someSet.add(myObject);
 }

Что будет более эффективно, зависит от того, как часто вы сталкиваетесь. Если они редки, вторая форма обычно выполняет только одну операцию, но при столкновении она делает три. Первая форма всегда делает два.

Ответ 2

Если набор уже содержит элемент, который equals() элемент, который вы пытаетесь добавить, новый элемент не будет добавлен и не заменит существующий элемент. Чтобы гарантировать добавление нового элемента, сначала удалите его из набора:

set.remove(aWordInfo);
set.add(aWordInfo);

Ответ 3

Попробуйте что-то следующее (это будет иметь смысл, если equals и hashCode зависит от одного поля, но другие поля могут иметь разные значения):

if(!set.add(obj)) {
    //set already contains the element (not the same object though) 
    set.remove(obj); //remove the one in  the set
    set.add(obj); //add the new one
}

Ознакомьтесь с документацией для метода Set.add

Если этот набор уже содержит элемент, вызов оставляет неизменным и возвращает false.

Ответ 4

Я работал над проблемой, где у меня был набор, тогда я хотел заменить/переопределить некоторые объекты объектами из другого набора.

В моем случае то, что я закончил, это создать новый набор и сначала перенести переопределения, а затем добавить текущие объекты. Это работает, потому что набор не заменяет любые существующие объекты при добавлении новых объектов.

Если у вас есть:

Set<WordInfo> currentInfo;
Set<WorldInfo> overrides;

Вместо:

for each override, replace the object in current info

Я сделал:

Set<WordInfo> updated = new HashSet<>();
updated.addAll(overrides);
updated.addAll(currentInfo);

Ответ 5

Проверьте код HashSet в JDK. Когда элемент добавляется и является дубликатом, старое значение заменяется. Народ считает, что новый элемент отброшен, это неправильно. Таким образом, вам не нужен дополнительный код в вашем случае.

ОБНОВЛЕНО ---------------------

Я перечитываю код в JDK и допускаю ошибку, которую я сделал.

Когда выполняется put, VALUE заменяется не KEY с HashMap.

Почему я говорю о HashMap??!! Потому что если вы посмотрите на код HashSet, вы заметите:

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

Итак, значение PRESENT заменяется новым, как показано в этой части кода:

      public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

Но я согласен, что key не заменяется, а поскольку key представляют значения HashSet's, это называется "нетронутым".