java.util.Set.remove(Object o) - 问题

时间:2011-09-07 22:51:00

标签: java collections

我必须在这里遗漏一些东西...我有以下代码和输出。你能看出为什么Category categoryToBeDeleted没有从result中每本书的类别集中删除?

谢谢!

代码:

List<Book> result = ... //get list from database

final Category categoryToBeDeleted = ... //get category from database

System.out.println("categoryToBeDeleted id: " + categoryToBeDeleted.getId() + " name: " + categoryToBeDeleted.getName());

for (Book book : result) {
    System.out.println("before remove :");
    for (Category category : book.getCategories()) {
        System.out.println("category id: " + category.getId() + " name: " + category.getName() + " equals: " + category.equals(categoryToBeDeleted));
    }
    System.out.println("-----------------------");

    book.getCategories().remove(categoryToBeDeleted);

    System.out.println("after remove :");
    for (Category category : book.getCategories()) {
        System.out.println("category id: " + category.getId() + " name: " + category.getName() + " equals: " + category.equals(categoryToBeDeleted));
    }
    System.out.println("-----------------------");

}

输出:

categoryToBeDeleted id: 10 name: cosmetics
before remove :
category id: 10 name: cosmetics equals: true
category id: 1 name: cleaning equals: false
-----------------------
after remove :
category id: 10 name: cosmetics equals: true
category id: 1 name: cleaning equals: false
-----------------------
before remove :
category id: 9 name: junk-2 equals: false
category id: 10 name: cosmetics equals: true
-----------------------
after remove :
category id: 9 name: junk-2 equals: false
category id: 10 name: cosmetics equals: true
-----------------------
before remove :
category id: 6 name: knick-knacks equals: false
category id: 4 name: baby equals: false
category id: 9 name: junk-2 equals: false
category id: 10 name: cosmetics equals: true
-----------------------
after remove :
category id: 6 name: knick-knacks equals: false
category id: 4 name: baby equals: false
category id: 9 name: junk-2 equals: false
category id: 10 name: cosmetics equals: true
-----------------------

P.S。类别包含:

@Override
public boolean equals(Object obj) {
    if (obj instanceof Category) {
        Category thatCategory = (Category) obj;
        return this.id.equals(thatCategory.id);
    }
    return false;
}

的Javadoc

remove

boolean remove(Object o)

如果存在,则从该集合中移除指定的元素(可选操作)。更正式地,如果此集合包含这样的元素,则删除元素e(o == null?e == null:o.equals(e))。如果此set包含元素,则返回true(或等效地,如果此set由于调用而更改)。 (一旦调用返回,该集合将不包含该元素。)

2 个答案:

答案 0 :(得分:16)

您的设置实际上是HashSet。类别未实现hashCode。因此,当您去除对象时,对象标识符将用作哈希代码,并且对于每个不同的对象,即使它在语义上等效,它最终也会使用不同的哈希代码,查找错误的位置。哈希集,但没有找到合适的匹配对象。

添加

@Override
public int hashCode() {
    return id.hashCode();
}

Category,一切都应该好。

可以在JavaDoc for java.lang.Object#equals

中阅读覆盖hashCode的要求
  

请注意,通常需要覆盖hashCode方法   每当重写此方法时,都要保持一般   hashCode方法的契约,它声明了相等的对象必须   有相同的哈希码。

正如本文所暗示的那样,JavaDoc for hashCode更详细地介绍了这一点。

虽然remove的JavaDoc可能在这个主题上更清楚,但它只引用equals作为规范的一部分,它将删除哪个对象 - 它没有说{{1}它是唯一可以使用的东西。

最后,如果你正在使用Eclipse,那么你可以打开一个警告,如果你覆盖equals而没有覆盖equals,反之亦然,它会发出警告。

答案 1 :(得分:2)

如果覆盖equals(),则还应覆盖hashCode()。