Java Set iterator, безопасный для удаления элементов? - PullRequest
9 голосов
/ 28 сентября 2010

Я хотел бы перебрать множество и удалить элементы из набора, которые соответствуют некоторому условию. Документация итератора ничего не говорит об изменении списка при его итерации по нему.

Возможно ли это? Если нет, то как лучше всего это сделать? Обратите внимание, что я хочу удалить только те элементы из набора, которые предоставлены итератором.

Редактировать : Быстро было показано, что это возможно. Могу ли я сделать это со следующим синтаксисом?

for(Node n : mySet) {
    mySet.remove(n);
}

Ответы [ 5 ]

16 голосов
/ 28 сентября 2010

Да, вы можете использовать итератор для безопасного удаления текущего элемента:

iterator.remove();

javadoc из remove() говорит:

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


Ответ на ваш следующий вопрос: Нет, вы не можете.Изменение набора во время итерации по нему с расширенным циклом for приведет к ConcurrentModificationException.

1 голос
/ 30 ноября 2015

Это на самом деле улучшилось в Java 8. Теперь вы можете просто

mySet.removeIf(element -> someConditionMatches());

Выше реализовано как default метод в java.util.Collection и должно спасти всех от записискучные петли.Тем не менее, он должен работать для любого типа коллекции, а не только Set.

1 голос
/ 28 сентября 2010

Ответ тангенса правильный.Если вы не используете iterator.remove (), а удалили непосредственно из Set, вы получите вызов исключения ConcurrentModificationException

0 голосов
/ 28 сентября 2010

для (Узел n: mySet) { mySet.remove (п); }

не будет работать, так как вы изменяете набор, который вы повторяете. Это, однако, может быть сделано только с использованием итератора, который в данном случае не так.

Это один из недостатков использования улучшенных циклов for.

0 голосов
/ 28 сентября 2010

Это то, что делает .remove ():

http://download.oracle.com/javase/6/docs/api/java/util/Iterator.html#remove%28%29

"Удаляет из базовой коллекции последний элемент, возвращаемый итератором (необязательная операция). Этот метод можно вызватьтолько один раз за вызов к следующему. Поведение итератора не определено, если базовая коллекция изменена во время итерации любым другим способом, кроме вызова этого метода. "

...