Рубрики
Без рубрики

Java – Как удалить элементы из списка во время итерации?

Несколько решений для удаления элементов из списка во время итерации и избежания исключения ConcurrentModificationException.

Автор оригинала: mkyong.

В Java, если мы удалим элементы из списка во время его повторения, он выбросит java.util. Исключение ConcurrentModificationException . В этой статье показано несколько способов ее решения.

Содержание

  • 1. java.использование. Исключение ConcurrentModificationException
  • 2. Коллекция Java 8#Удалить если
    • 2.1 Удалить примеры
    • 2.2 Удалить, если используется итератор
  • 3. Пример составителя списка
  • 4. Отфильтруйте и соберите пример
  • 5. Рекомендации

P.S Протестирован с Java 11.

1. java.использование. Исключение ConcurrentModificationException

Если мы удалим элемент из ArrayList во время его итерации, list.remove(ы) вызовет java.util. Исключение ConcurrentModificationException .

package com.mkyong.basic;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class IteratorApp1 {

  public static void main(String[] args) {

      List list = new ArrayList<>();
      list.add("A");
      list.add("B");
      list.add("C");

      for (String s : list) {
          if ("A".equals(s)) {
              // throws java.util.ConcurrentModificationException
              list.remove(s);
          }
      }

      System.out.println(list);

  }

}

Выход

Exception in thread "main" java.util.ConcurrentModificationException

at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)
at com.mkyong.basic.IteratorApp.main(IteratorApp.java:16)

2. Коллекция Java 8#Удалить если

В Java 8 мы можем использовать API Collection#removeIf для удаления элементов из списка во время его повторения.

2.1 Удалить примеры

package com.mkyong.basic;

import java.util.ArrayList;
import java.util.List;

public class IteratorApp2A {

  public static void main(String[] args) {

      List list = new ArrayList<>();
      list.add("A");
      list.add("B");
      list.add("C");

      // remove if item is "A"
      list.removeIf("A"::equals);

      System.out.println(list);

  }

}

Выход

[B, C]

Другой удалить, Если пример.

package com.mkyong.basic;

import java.util.ArrayList;
import java.util.List;

public class IteratorApp2B {

  public static void main(String[] args) {

      List list = new ArrayList<>();
      list.add(1);
      list.add(2);
      list.add(3);

      // remove if item is 1 or 3
      list.removeIf(x -> x == 1 || x == 3);

      System.out.println(list);

  }

}

Выход

[2]

2.2 Удалить, если используется итератор

Просмотрите подпись метода Java 8 Collection#removeIf , и API использует Итератор для удаления элемента во время его повторения.

package java.util;

public interface Collection extends Iterable {

  //...

  default boolean removeIf(Predicate filter) {
      Objects.requireNonNull(filter);
      boolean removed = false;
      final Iterator each = iterator();
      while (each.hasNext()) {
          if (filter.test(each.next())) {
              each.remove();
              removed = true;
          }
      }
      return removed;
  }

  //...
}

3. Пример составителя списка

До Java 8 мы можем использовать ListIterator для удаления элементов из списка при его повторении.

package com.mkyong.basic;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class IteratorApp3 {

    public static void main(String[] args) {

        List list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");

        ListIterator iter = list.listIterator();
        while(iter.hasNext()){
            if("A".equals(iter.next())){
                iter.remove();
            }
        }

        System.out.println(list);

    }

}

Выход

[B, C]

4. Отфильтруйте и соберите пример

4.1 Мы также можем создать новый Список для хранения отфильтрованного результата.

package com.mkyong.basic;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class IteratorApp4A {

  public static void main(String[] args) {

      List list = new ArrayList<>();
      list.add("A");
      list.add("B");
      list.add("C");

      List result = new ArrayList<>();
      for (String s : list) {
          if (!"A".equals(s)) {
              result.add(s);
          }
      }

      System.out.println(result);

  }

}

Выход

[B, C]

4.2 В Java 8 мы можем использовать поток для фильтрации и сбора.

package com.mkyong.basic;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class IteratorApp4B {

  public static void main(String[] args) {

      List list = new ArrayList<>();
      list.add("A");
      list.add("B");
      list.add("C");

      // Java 8
      List result = list
              .stream()
              .filter(x -> !"A".equals(x))
              .collect(Collectors.toList());

      System.out.println(result);

  }

}

Выход

[B, C]

5. Рекомендации

Оригинал: “https://mkyong.com/java/java-how-to-remove-items-from-a-list-while-iterating/”