我必须在这里遗漏一些东西...我有以下代码和输出。你能看出为什么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
boolean remove(Object o)
如果存在,则从该集合中移除指定的元素(可选操作)。更正式地,如果此集合包含这样的元素,则删除元素e(o == null?e == null:o.equals(e))。如果此set包含元素,则返回true(或等效地,如果此set由于调用而更改)。 (一旦调用返回,该集合将不包含该元素。)
答案 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()。