[JAVA]반복문 안에서 List 요소 삭제

류동재·2022년 3월 4일
1

For Loop를 이용해서 List 순회 중에 , 어떤 요소를 삭제하면 EXCEPTION이 발생하거나 요소를 탐색하지 못하는 문제가 발생할 수 있다.

  • 문제점

    • CooncurrentModificationException 발생 가능성

    • 반복문에서 순회 중, 일부 요소가 탐색에서 누락될 수 있는 가능성

    • 반복문 순회 중, 일부 요소가 탐색에서 누락될 수 있는 가능성

      문제점 1 : ConcurrentModificationException 가능성

      아래 코드처럼 for loop에서 list의 특정 요소를 삭제하게 되면 ConcurrentModificationException이 발생할 수 있다. 순회 중에 리스트의 요소을 삭제 했을 때, 다음에 참조하는 요소의 인덱스가 list의 범위를 벗어 나게 된다. 이 상황에서 예외가 발생한다.

      public class RemoveIteratorSol4 {
          public static void main(String[] args) {
              List<String> list = new ArrayList<>();
              list.add("1");
              list.add("2");
              list.add("3");
              list.add("4");
      
              for (String item : list) {
                  if (item.equals("2")) {
                      list.remove(item);
                  }
              }
          }
      }

      Output

      문제점 2 : 반복문 순회 중 , 일부 요소가 탐색에서 누락될 수 있는 가능성

      문제점 1 처럼 ConcurrentModificationException 이 발생하지 않아도, 낮은 index에서 높은 index로 탐색하면서 요소를 삭제하면 탐색에서 제외되는 아이템이 발생할 수 도 있다.

      public class RemoveIterator2 {
          public static void main(String[] args) {
              List<String> list = new ArrayList<>();
              list.add("1");
              list.add("2");
              list.add("3");
              list.add("4");
      
              for (int i = 0; i < list.size(); i++) {
                  String item = list.get(i);
                  System.out.println("Iterating: " + item);
                  if (item.equals("1") || item.equals("2")) {
                      list.remove(item);
                  }
              }
      
              System.out.println(list);
          }
      }

      위처럼 2는 탐색되지 못한다.

      SOL 1 :List의 높은 인덱스에서 낮은 인덱스 방향으로 순회

      List의 높은 Index에서 낮은 Index 방향으로 순회하면, for loop에서 요소를 안전하게 삭제 할 수 있다. 요소삭제가 탐색할 요소의인덱스에 영향을 주지 않는다.

      public class RemoveIteratorSol1 {
      
          public static void main(String[] args) {
      
              List<String> list = new ArrayList<>();
              list.add("1");
              list.add("2");
              list.add("3");
              list.add("4");
      
              for (int i = (list.size() - 1); i > -1; i--) {
                  String item = list.get(i);
                  System.out.println("Iterating: " + item);
                  if (item.equals("2")) {
                      list.remove(item);
                  }
              }
      
              System.out.println("Result: " + list);
          }
      }

      SOL 2 : Collection.removeIf()

      Collection.removeIf()는 인자로 함수형 인터페이스 Predicate를 전달하고, 요소를 안전하게 삭제한다.

      public class RemoveIteratorSol2 {
          public static void main(String[] args) {
      
              List<String> list = new ArrayList<>();
              list.add("apple");
              list.add("kiwi");
              list.add("melon");
              list.add("banana");
      
              list.removeIf(item -> item.equals("kiwi"));
      
              System.out.println("Result: " + list);
          }
      }

      SOL 3 : Iterator

      Iterator는 자바 컬랙션 프레임워크에서 컬랙션에 저장되어 있는 요소들을 읽어오는 방법을 표준화 한 것이다.

      Iterator를 통해 리스트를 순회하고, 특정 요소를 안전하게 삭제할 수 있다.

      public class RemoveIteratorSol3 {
          public static void main(String[] args) {
      
              List<String> list = new ArrayList<>();
              list.add("apple");
              list.add("kiwi");
              list.add("melon");
              list.add("banana");
      
              Iterator<String> it = list.iterator();
              while (it.hasNext()) {
                  String item = it.next();
                  System.out.println("Iterating: " + item);
                  if (item.equals("kiwi")) {
                      it.remove();
                  }
              }
      
              System.out.println("Result: " + list);
          }
      }

REFERENCE
https://codechacha.com/ko/java-remove-from-list-while-iterating/

0개의 댓글