Replacing a HashSet Java member

前端 未结 5 1449
我在风中等你
我在风中等你 2021-01-07 16:47

I have Set of that structure. I do not have duplicates but when I call: set.add(element) -> and there is already exact element I would like the old to be replac

相关标签:
5条回答
  • 2021-01-07 17:13

    Try something as follows (this will only make sense if the equals and hashCode depends on one field, but the other fields could have different values):

    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
    }
    

    Check out the documentation for the Set.add method

    If this set already contains the element, the call leaves the set unchanged and returns false.

    0 讨论(0)
  • 2021-01-07 17:13

    I was working on a problem where I had a set then I wanted to replace/override some of the objects with objects from another set.

    In my case what I ended up doing was creating a new set and putting the overrides in first then adding the current objects second. This works because a set won't replace any existing objects when adding new objects.

    If you have:

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

    Instead of:

    for each override, replace the object in current info
    

    I did:

    Set<WordInfo> updated = new HashSet<>();
    updated.addAll(overrides);
    updated.addAll(currentInfo);
    
    0 讨论(0)
  • 2021-01-07 17:26

    Do a remove before each add:

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

    The remove will remove any object that is equal to myObject. Alternatively, you can check the add result:

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

    Which would be more efficient depends on how often you have collisions. If they are rare, the second form will usually do only one operation, but when there is a collision it does three. The first form always does two.

    0 讨论(0)
  • 2021-01-07 17:26

    Check the HashSet code within the JDK. When an element is added and is a duplicate, the old value is replaced. Folk think that the new element is discarded, it's wrong. So, you need no additional code in your case.

    UPDATED---------------------

    I re-read the code in JDK, and admit a mistake that I've made.

    When put is made, the VALUE is replaced not the KEY from an HashMap.

    Why am I talking about Hashmap??!! Because if you look at the HashSet code, you will notice:

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

    So the PRESENT value is replaced with the new one as shown in this portion of code:

          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;
        }
    

    But I agree, the key isn't replaced, and since the keys represent the HashSet's values, this one is said to be "untouched".

    0 讨论(0)
  • 2021-01-07 17:27

    If the set already contains an element that equals() the element you are trying to add, the new element won't be added and won't replace the existing element. To guarantee that the new element is added, simply remove it from the set first:

    set.remove(aWordInfo);
    set.add(aWordInfo);
    
    0 讨论(0)
提交回复
热议问题