简体   繁体   中英

Removing element from HashSet

I have the code:

System.out.println("before: " + clusters.size());

        Iterator it = clusters.iterator();
        while (it.hasNext()) {
            Set<Place> set = (Set<Place>) it.next();
            if (set == max2) {
                System.out
                        .println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                it.remove();
                break;
            }
        }

        System.out.println("after: " + clusters.size());

I made this because clusters.remove(max2) returned false. Now it prints

before: 96
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
after: 96

How is it possible?

While your code should (intuitively) work, you're hitting a limitation of the way sets are designed. The hash of a set is the sum of all the hashes of its items, and a hash set's items MUST have consistent hashes, or it is unable to find them during lookups. You're using a set of sets, and I believe you have modified your child sets while they were in the set-of-sets, so it now cannot find them to remove them. This is undefined behaviour territory, so you may find it behaves differently when compiled against different versions and implementations of the standard library.

You would be better off using a map of key->set. In general, remember that after adding an item to a set (or using it as a key in a map), you should do nothing which would change its hash (of course, this is for HashSet s and HashMap s, which are easily the most common. For other types, follow the specific rules given in their docs, but it often boils down to: don't change it once added).

Edit: seems that KEYSER beat me to it with his information in a comment. Oh well.

Also, the notes on your use of == instead of equals are sort-of valid, but if you know that the object is certainly the exact same reference then your code is OK (and faster!). From the log statements you're seeing, this appears to be the case.


Removes from the underlying collection the last element returned by the iterator (optional operation). This method can be called only once per call to next. The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM