HashSet.remove() and Iterator.remove() not working

前端 未结 10 1494
借酒劲吻你
借酒劲吻你 2020-12-13 00:32

I\'m having problems with Iterator.remove() called on a HashSet.

I\'ve a Set of time stamped objects. Before adding a new item to the Set, I loop through the set, i

相关标签:
10条回答
  • 2020-12-13 00:45

    Under the covers, HashSet uses HashMap, which calls HashMap.removeEntryForKey(Object) when either HashSet.remove(Object) or Iterator.remove() is called. This method uses both hashCode() and equals() to validate that it is removing the proper object from the collection.

    If both Iterator.remove() and HashSet.remove(Object) are not working, then something is definitely wrong with your equals() or hashCode() methods. Posting the code for these would be helpful in diagnosis of your issue.

    0 讨论(0)
  • 2020-12-13 00:45

    Are you absolutely certain that DataResult is immutable? What is the type of the timestamp? If it's a java.util.Date are you making copies of it when you're initializing the DataResult? Keep in mind that java.util.Date is mutable.

    For instance:

    Date timestamp = new Date();
    DataResult d = new DataResult(timestamp);
    System.out.println(d.getTimestamp());
    timestamp.setTime(System.currentTimeMillis());
    System.out.println(d.getTimestamp());
    

    Would print two different times.

    It would also help if you could post some source code.

    0 讨论(0)
  • 2020-12-13 00:48

    The Java HashSet has an issue in "remove()" method. Check the link below. I switched to TreeSet and it works fine. But I need the O(1) time complexity.

    https://bugs.openjdk.java.net/browse/JDK-8154740

    0 讨论(0)
  • 2020-12-13 00:53

    I was very curious about this one still, and wrote the following test:

    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Random;
    import java.util.Set;
    
    public class HashCodeTest {
        private int hashCode = 0;
    
        @Override public int hashCode() {
            return hashCode ++;
        }
    
        public static void main(String[] args) {
            Set<HashCodeTest> set = new HashSet<HashCodeTest>();
    
            set.add(new HashCodeTest());
            System.out.println(set.size());
            for (Iterator<HashCodeTest> iter = set.iterator();
                    iter.hasNext();) {
                iter.next();
                iter.remove();
            }
            System.out.println(set.size());
        }
    }
    

    which results in:

    1
    1
    

    If the hashCode() value of an object has changed since it was added to the HashSet, it seems to render the object unremovable.

    I'm not sure if that's the problem you're running into, but it's something to look into if you decide to re-visit this.

    0 讨论(0)
  • 2020-12-13 00:55

    If there are two entries with the same data, only one of them is replaced... have you accounted for that? And just in case, have you tried another collection data structure that doesn't use a hashcode, say a List?

    0 讨论(0)
  • 2020-12-13 00:56

    Thanks for all the help. I suspect the problem must be with equals() and hashCode() as suggested by spencerk. I did check those in my debugger and with unit tests, but I've got to be missing something.

    I ended up doing a workaround-- copying all the items except one to a new Set. For kicks, I used Apache Commons CollectionUtils.

        Set<DataResult> tempResults = new HashSet<DataResult>();
        CollectionUtils.select(allResults, 
                new Predicate()
                {
                    public boolean evaluate(Object oldData)
                    {
                        return !data.equalsData((DataResult) oldData);
                    }
                }
                , tempResults);
        allResults = tempResults;
    

    I'm going to stop here-- too much work to simplify down to a simple test case. But the help is miuch appreciated.

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