У меня возникают проблемы с Iterator.remove(), вызванным в HashSet.
У меня есть набор объектов с меткой времени. Перед добавлением нового элемента в набор я прохожу через набор, идентифицирую старую версию этого объекта данных и удаляю его (перед добавлением нового объекта). метка времени включена в hashCode и equals(), но не равна equataData().
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 является неизменным объектом, поэтому он не может быть изменен после того, как он был первоначально добавлен в набор.
-
Методы equals и hashCode() используют @Override, чтобы гарантировать, что они являются правильными методами. Тестирование модулей проверяет эти работы.
-
Это также не удается, если я просто использую оператор for и Set.remove. (например, через элементы, найдите элемент в списке, затем вызовите Set.remove(oldData) после цикла).
-
Я тестировал в JDK 5 и JDK 6.
Я думал, что должен упустить что-то основное, но, проведя некоторое значительное время на этом, мой коллега и я в тупике. Любые предложения по проверке вещей?
EDIT:
Появились вопросы - действительно ли DataResult неизменен. Да. Нет сеттеров. И когда объект Date извлекается (который является изменяемым объектом), это делается путем создания копии.
public Date getEntryTime()
{
return DateUtil.copyDate(entryTime);
}
public static Date copyDate(Date date)
{
return (date == null) ? null : new Date(date.getTime());
}
ДАЛЬНЕЙШЕЕ ИЗМЕНЕНИЕ (спустя некоторое время): Для записи - DataResult не был неизменным! Он ссылался на объект, у которого был хэш-код, который изменился при сохранении в базе данных (плохая практика, я знаю). Оказалось, что если DataResult был создан с временным подобъектом, и подобъект был сохранен, хэш-код DataResult был изменен.
Очень тонко - я смотрел на это много раз и не замечал отсутствия неизменности.