首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HashSet.remove()和Iterator.remove()不能工作

HashSet.remove()和Iterator.remove()不能工作
EN

Stack Overflow用户
提问于 2008-10-31 18:25:44
回答 10查看 28.5K关注 0票数 43

在调用一个Iterator.remove() HashSet时,我遇到了问题。

我有一套有时间戳的东西。在向集合添加新项之前,我循环遍历该集合,标识该数据对象的旧版本并删除它(在添加新对象之前)。时间戳包含在hashCode和equals()中,但不包括equalsData()。

代码语言:javascript
复制
for (Iterator<DataResult> 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的状态,因此它在添加到set

等于之后不会更改,hashCode()方法使用@重写来确保它们是正确的方法。单元测试验证这些工作。如果我只使用一个for语句和一个

  • ,那么它也会失败。(例如,循环遍历项目,在列表中找到项目,然后在循环后调用Set.remove(oldData) )。

我想我一定是错过了一些基本的东西,但在这方面花了大量的时间之后,我和我的同事感到很困惑。有什么建议要检查吗?

编辑:

有一些问题-- DataResult真的是不可变的吗?是。没有赛特人。当检索Date对象(这是一个可变对象)时,它通过创建一个副本来完成。

代码语言:javascript
复制
public Date getEntryTime()
{
    return DateUtil.copyDate(entryTime);
}

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

进一步编辑(一段时间后):为了记录-- DataResult不是不变的!它引用了一个对象,该对象的哈希代码在持久化到数据库时发生了更改(我知道,实践很糟糕)。结果表明,如果使用瞬态子对象创建了一个DataResult,并且该子对象被持久化,那么DataResult的哈希代码就会被更改。

非常微妙--我看了这么多次,并没有注意到它的不可变性。

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2008-11-01 23:27:26

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

代码语言:javascript
复制
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());
    }
}

其结果是:

代码语言:javascript
复制
1
1

如果对象的hashCode()值在添加到HashSet后发生了更改,则它似乎使对象不可移动。

我不确定这是否是你遇到的问题,但如果你决定重新审视这个问题,这是值得研究的。

票数 59
EN

Stack Overflow用户

发布于 2008-11-01 05:01:56

在幕后,HashSet使用HashMap,在调用HashSet.remove(Object)或Iterator.remove()时调用HashMap.removeEntryForKey(Object)。该方法同时使用hashCode()和equals()来验证它是否正在从集合中移除适当的对象。

如果Iterator.remove()和HashSet.remove(对象)都不能工作,那么equals()或hashCode()方法肯定有问题。发布这些代码将有助于诊断您的问题。

票数 7
EN

Stack Overflow用户

发布于 2008-11-01 03:37:23

你确定DataResult是不可变的吗?时间戳的类型是什么?如果它是一个java.util.Date,那么在初始化DataResult时,您是否正在复制它?请记住,java.util.Date是可变的。

例如:

代码语言:javascript
复制
Date timestamp = new Date();
DataResult d = new DataResult(timestamp);
System.out.println(d.getTimestamp());
timestamp.setTime(System.currentTimeMillis());
System.out.println(d.getTimestamp());

会印两个不同的时间。

如果您可以发布一些源代码,这也会有所帮助。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/254441

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档