java.util.Set.remove (Object o) - проблема - PullRequest
       0

java.util.Set.remove (Object o) - проблема

4 голосов
/ 08 сентября 2011

Я должен что-то здесь упустить ... У меня есть следующий код и вывод. Вы видите, почему 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

удалить

логическое удаление (Объект o)

Удаляет указанный элемент из этого набора, если он присутствует (необязательная операция). Более формально удаляет элемент e такой, что (o == null? E == null: o.equals (e)), если этот набор содержит такой элемент. Возвращает true, если этот набор содержал элемент (или эквивалентно, если этот набор изменился в результате вызова). (Этот набор не будет содержать элемент после возврата вызова.)

Ответы [ 2 ]

16 голосов
/ 08 сентября 2011

Ваш набор на самом деле HashSet.Категория не реализует hashCode.В результате, когда вы собираетесь удалить объект, идентификатор объекта используется в качестве хеш-кода, и для каждого отдельного объекта, даже если он семантически эквивалентен, он в конечном итоге использует другой хеш-код, глядя в неправильном месте вхэш установлен и не найден соответствующий соответствующий объект.

Добавьте

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

к Category и все должно быть в порядке.

Требование переопределить hashCode можетчитать в JavaDoc для java.lang.Object # равно :

Обратите внимание, что обычно необходимо переопределить метод hashCode всякий раз, когда этот метод переопределяется, чтобы сохранитьобщий контракт для метода hashCode, в котором говорится, что равные объекты должны иметь равные хеш-коды.

Как следует из этого текста, JavaDoc для hashCode описывает это более подробно.

В то время как JavaDoc для remove может быть более понятным по предмету, он ссылается только на equals как часть спецификации, для которого объект будет удаленove - это не значит, что equals - единственное, что он будет использовать.

Наконец, если вы используете Eclipse, вы можете включить предупреждение, которое предупредит вас, если вы переопределите equals без переопределения hashCode или наоборот.

2 голосов
/ 08 сентября 2011

Если вы переопределяете equals (), вам также следует переопределить hashCode ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...