【问题标题】:Collection contains object but cannot remove it集合包含对象但无法删除它
【发布时间】:2012-07-03 15:55:20
【问题描述】:

我有一个包含多个集合的类,但在从其中一个集合中删除某些对象时遇到问题。如果我调用 collection.contains(object) 它返回 true 然后在下一行我调用 collection.remove(object) 并且对象不会被删除。

这是无效的原始代码。所有的集合都是 SortedSet。这里让我感到困惑的是,男性集合是直接从 people 集合中填充的,但是当您尝试从 people 集合中删除男性对象时,并非所有对象都会被删除。

    for(Person person : peopleBin.getPeople())
    {
        if(person.isMale())
        {
            peopleBin.getMen().add(person);
        }
    }
    peopleBin.getPeople().removeAll(peopleBin.getMen());

Person 有这样的 equals 方法

public boolean equals( Object obj ) 
{
    if ( obj == null )
        return false;
    if ( !(obj instanceof Person) )
        return false;
    Person that = (Person)obj;
    return
        that.age == age &&
        that.id == id &&
        that.someCount == someCount ;
}

现在当我用这个替换第一个 sn-p 的 removeAll 行时,我得到了奇怪的行为。

    for(Person person: personBin.getMen())
    {
        if(personBin.getPeople().contains(person)) 
            personBin.getPeople().remove(person);
    } 

if(personBin.getPeople().contains(person)) 总是返回 true,但 personBin.getPeople().remove(person) 并不总是删除。有时会,有时不会。

我已将所有类名和字段名更改为通用的,以便在公共论坛上发布。

任何帮助将不胜感激!

编辑:这里是 compareTo 实现

    public int compareTo (Object o)
{
    if ( ! ( o instanceof Person) ) 
    {
        throw new ClassCastException();
    }

    Person that = (Person)o;

    int comparison = 0;

    return 
        ( (comparison = this.age () - that.age ()) != 0 ? comparison :
        ( (comparison = this.id - that.id) != 0 ? comparison :
        ( (comparison = this.someCount - that.someCount ))));
}

编辑:这里是 hashCode impl

public int hashCode() {
    int result = 31;
    result = 61*result + age;
    result = 61*result + id;
    result = 61*result + someCount;
    return result;
}

【问题讨论】:

  • 我们能看到比较器的实现吗?或者compareTo,如果您只是使用自然排序?
  • 将底部示例中的代码切换为if(peopleBin.getPeople().remove(person)) { println("Removed" +person); } else { println("Didn't remove" + person); },看看是否能识别出任何模式。
  • 您是否收到任何错误消息?您是否尝试过使用调试器?
  • 是的,确实如此——具体来说,它破坏了整个集合,或多或少无法恢复。这就是为什么您应该只将不可修改的对象放入Set。如果我是你,我会尝试查看不同的Collection 实现是否仍然出现该错误。到目前为止,您提供的代码看起来或多或少都不错,但到目前为止,此类错误的最常见原因是修改对象、错误的比较器/哈希代码实现或错误的 equals 实现。
  • 要清楚,在List 中很好,只是在Set 中或Map 键中没有,如Set javadoc 中指定的那样:“注意:必须非常小心如果可变对象用作集合元素。如果对象的值以影响相等比较的方式更改,而对象是集合中的元素,则不指定集合的​​行为。此禁止的一个特殊情况是不允许集合包含自己作为元素。”

标签: java collections


【解决方案1】:

要从集合中删除项目,最好的方法是使用迭代器来避免任何问题:

用这个替换你的循环,然后再试一次:

for(Iterator<Person> iterator =  personBin.getMen().iterator();iterator.hasNext();){
            Person person = iterator.next();
            if(personBin.getPeople().contains(person)){
                iterator.remove();
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-13
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 2015-09-19
    相关资源
    最近更新 更多