Вызов удаления в цикле foreach в Java [duplicate]

([[][a-z \s]+[]])

Выше должно работать, учитывая следующее объяснение

  • символов в квадратных скобках [] определяет класс characte, который означает, что шаблон должен соответствовать как минимум одному символу, указанному в квадратных скобках
  • \ s указывает пространство
  • + означает, что по крайней мере один из символов, упомянутых ранее, на +.
557
задан James McMahon 30 July 2009 в 20:16
поделиться

4 ответа

Для безопасного удаления из коллекции во время итерации по ней вы должны использовать итератор.

Например:

List<String> names = ....
Iterator<String> i = names.iterator();
while (i.hasNext()) {
   String s = i.next(); // must be called before you can call i.remove()
   // Do something
   i.remove();
}

Из Документации Java :

итераторы, возвращаемые итератором этого класса и listIterator методы работают без сбоев: если список структурно изменен в любом время после создания итератора любым способом, кроме собственные методы удаления или добавления итератора, итератор выдаст ConcurrentModificationException. Таким образом, перед лицом одновременного модификации, итератор выходит из строя быстро и чисто, а не рисковать произвольным, недетерминированным поведением в неопределенное время в будущем.

Возможно, для многих новичков непонятно, что итерация по списку с использованием конструкций for / foreach неявно создает итератор, который обязательно недоступен. Эту информацию можно найти здесь

875
ответ дан 22 November 2019 в 22:09
поделиться

Java-дизайн «расширенного цикла for» заключался в том, чтобы не подвергать итератор коду, но единственный способ безопасно удалить элемент - это получить доступ к итератору. Так что в этом случае вы должны сделать это по-старому:

 for(Iterator<String> i = names.iterator(); i.hasNext();) {
       String name = i.next();
       //Do Something
       i.remove();
 }

Если в реальном коде усовершенствованный цикл for действительно того стоит, тогда вы можете добавить элементы во временную коллекцию и вызвать removeAll в списке после цикла.

РЕДАКТИРОВАТЬ (повторное добавление): Нет, изменение списка каким-либо образом за пределами метода iterator.remove () во время итерации вызовет проблемы. Единственный способ обойти это - использовать CopyOnWriteArrayList, но он действительно предназначен для решения проблем параллелизма.

Самый дешевый (с точки зрения количества строк кода) способ удаления дубликатов - выгрузить список в LinkedHashSet (а затем обратно в Список при необходимости). Это сохраняет порядок вставки при удалении дубликатов.

60
ответ дан 22 November 2019 в 22:09
поделиться

Вы не хотите этого делать . Это может вызвать неопределенное поведение в зависимости от коллекции. Вы хотите напрямую использовать итератор . Хотя конструкция for each является синтаксическим сахаром и на самом деле использует итератор, она скрывает его от вашего кода, поэтому вы не можете получить к нему доступ для вызова Iterator.remove .

Итератор работает так же. не указано, если основной коллекция изменяется, пока итерация выполняется любым способом кроме вызова этого метода.

Вместо этого напишите свой код:

List<String> names = ....
Iterator<String> it = names.iterator();
while (it.hasNext()) {

    String name = it.next();
    // Do something
    it.remove();
}

Обратите внимание, что код вызывает Iterator.remove , а не List.remove .

Добавление:

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

160
ответ дан 22 November 2019 в 22:09
поделиться

Те, кто говорят, что вы не можете безопасно удалить элемент из коллекции, кроме как с помощью Iterator, не совсем верны, вы можете сделать это безопасно, используя одну из параллельных коллекций, такую ​​как ConcurrentHashMap.

4
ответ дан 22 November 2019 в 22:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: