[ACCEPTED]-Why won't it remove from the set?-puzzle

Accepted answer
Score: 10

For a HashSet, this can occur if the object's 7 hashCode changes after it has been added 6 to the set. The HashSet.remove() method 5 may then look in the wrong Hash bucket and 4 fail to find it.

This probably wouldn't happen if you did iterator.remove(), but in any case, storing 3 objects in a HashSet whose hashCode can 2 change is an accident waiting to happen 1 (as you've discovered).

Score: 3

Puzzle? If Object.hashCode, Object.equals or the "hash set" were implemented 5 incorrectly (see for instance, java.net.URL - use URI).

Also 4 if the set (directly or indirectly) contains 3 itself, something odd is likely to happen 2 (exactly what is implementation and phase 1 of the moon dependent).

Score: 2

What is the implementation type of the set 12 and what objects are inside the set?

  • If it is a HashSet, make sure that the value of the object's hashCode() method remains constant between set.put(...) and set.remove(...).
  • If it is a TreeSet, make sure that not modifications were made to the object that affect the set's comparator or the object's compareTo method.

In both 11 cases, the code between set.put(...) and set.remove(...) violates the 10 contract defined by the respective class 9 implementation. As a rule of thumb, it is 8 a good idea to use immutable objects as 7 set content (and as Map keys). By their 6 very nature such objects cannot be changed 5 while they are stored inside a set.

If you 4 are using some other set implementation, check 3 out its JavaDoc for its contract; but usually 2 either equals or hashCode must remain the same while the 1 object is contained in the set.

Score: 1

Beyond the missing ';' after set.remove(obj), It can happen 2 in three situations (quoted from javadoc).

ClassCastException - if the type of the specified element is incompatible with this set (optional).
NullPointerException - if the specified element is null and this set does not support null elements (optional). 
UnsupportedOperationException - if the remove method is not supported by this set.

You 1 can also try:

public void foo(Set<Object> set)
{
    Object obj=set.iterator().next();
    iterator.remove();
}
Score: 1

Should it be:

public void foo(Set<Object> set)
{
    Iterator i = set.iterator();
    i.next();
    i.remove();
}

?

The bug could be something 4 to do with:

public void remove()

The behavior of an iterator is unspecified 3 if the underlying collection is modified 2 while the iteration is in progress in 1 any way other than by calling this method.

(Reference)

Score: 0

My similar case:

enter image description here

This not work for me. I 3 need @Override equals and hashCode on my class Group, like 2 this:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    Group other = (Group) obj;
    if (id == null) {
        if (other.id != null) return false;
    } else if (!id.equals(other.id)) return false;
    return true;
}

This forces to compare POJOs by id field, without 1 the phase of the moon.

More Related questions