Changing values in HashSet

前端 未结 3 2051
滥情空心
滥情空心 2020-12-29 15:20

I\'ve read this question: Changing the elements in a set changes the \'equals\' semantics

However, I don\'t know how to solve the problem that I can\'t change an ite

相关标签:
3条回答
  • 2020-12-29 15:56

    As the question you linked to details, and as others have pointed out, you're encountering the mutable key issue. I'll requote from the Javadoc:

    Note: Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set.

    As you pointed out, you get that. The question is, how do you actually remove the object given that's the case? You can't use Set.remove(), because your object is lost in the hash table. You can, however, use an Iterator to do it. Something like the following:

    TestClass toRemove = <the same instance, but mutated>;
    for (Iterator<TestClass> iter = set.iterator(); iter.hasNext(); ) {
      TestClass item = iter.next();
      if (toRemove.equals(item)) {
        iter.remove();
      }
    }
    

    This approach relies on the fact that standard equals() methods, like you're using, have an instance check, and that check will return true.

    Please keep in mind this is not the right way to solve this problem. The right way is to either use an immutable key or "exercise great care", but it is a way to remove a mutated object from a HashSet.

    0 讨论(0)
  • 2020-12-29 15:58

    You are facing the problem because the keys in your hashset are not immutable. If you don't have immutable keys, you will lose the reference of the original key object once modified. And will never be able to get handle of that, which is sometimes referred as memory leaks in collection. So if you use immutable keys, you wouldn't run into this situation.

    0 讨论(0)
  • 2020-12-29 16:03

    When you add testElement to the HashSet, it selects a bucket based on the hash code for testElement. When you ask the HashSet if it contains a TestElement, it computes the hash code of the object that it's looking for and searches only in that bucket.

    As your hashCode() is based on non-final field, the hash code can change behind the scenes of the HashSet. Thus completely invalidating the basic assumption of the HashSet.

    A correct implementation for the Testclass would have the s1 field as final.

    0 讨论(0)
提交回复
热议问题