当前位置:  开发笔记 > 编程语言 > 正文

HashSet.remove()和Iterator.remove()不起作用

如何解决《HashSet.remove()和Iterator.remove()不起作用》经验,为你挑选了2个好方法。

我遇到了Iterator.remove()在HashSet上调用的问题.

我有一组带时间戳的物体.在向Set添加新项目之前,我遍历该集合,识别该数据对象的旧版本并将其删除(在添加新对象之前).时间戳包含在hashCode和equals()中,但不包括equalsData().

for (Iterator i = allResults.iterator(); i.hasNext();)
{
    DataResult oldData = i.next();
    if (data.equalsData(oldData))
    {   
        i.remove();
        break;
    }
}
allResults.add(data)

奇怪的是,i.remove()默默地对集合中的某些项目失败(没有异常).我已经证实了

实际上调用了i.remove()行.我可以直接在Eclipse的断点处从调试器调用它,但仍然无法更改Set的状态

DataResult是一个不可变对象,因此在最初添加到集合后它不能更改.

equals和hashCode()方法使用@Override来确保它们是正确的方法.单元测试验证了这些工作.

如果我只使用for语句和Set.remove,这也会失败.(例如循环遍历项目,找到列表中的项目,然后在循环后调用Set.remove(oldData)).

我已经在JDK 5和JDK 6中进行了测试.

我以为我必须遗漏一些基本的东西,但是在我的同事上度过了一些重要的时间后,我感到难过.有什么建议要检查吗?

编辑:

有一些问题 - DataResult是真正不可改变的.是.没有制定者.当检索Date对象(这是一个可变对象)时,它通过创建一个副本来完成.

public Date getEntryTime()
{
    return DateUtil.copyDate(entryTime);
}

public static Date copyDate(Date date)
{
    return (date == null) ? null : new Date(date.getTime());
}

进一步编辑(一段时间后):为了记录 - DataResult不是一成不变的!它引用了一个对象,该对象的哈希码在持久化到数据库时发生了变化(我知道这是一种不好的做法).事实证明,如果使用瞬态子对象创建了DataResult,并且子对象被持久化,则DataResult哈希码已更改.

非常微妙 - 我多次看了这个,并没有注意到缺乏不变性.



1> Jack Leow..:

我对这个仍然非常好奇,并写了以下测试:

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 set = new HashSet();

        set.add(new HashCodeTest());
        System.out.println(set.size());
        for (Iterator iter = set.iterator();
                iter.hasNext();) {
            iter.next();
            iter.remove();
        }
        System.out.println(set.size());
    }
}

这导致:

1
1

如果对象的hashCode()值自添加到HashSet后已更改,则它似乎无法移除对象.

我不确定你是否遇到了这个问题,但是如果你决定重新访问它,可以考虑一下.


六年后,这个答案为我节省了更多的总部互动时间。+1。+所有。

2> Spencer Korm..:

在底层,HashSet使用HashMap,当调用HashSet.remove(Object)或Iterator.remove()时,HashMap调用HashMap.removeEntryForKey(Object).此方法使用hashCode()和equals()来验证它是否从集合中删除了正确的对象.

如果Iterator.remove()和HashSet.remove(Object)都不起作用,那么你的equals()或hashCode()方法肯定是错误的.发布这些代码有助于诊断您的问题.

推荐阅读
pan2502851807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有