For Loop를 이용해서 List 순회 중에 , 어떤 요소를 삭제하면 EXCEPTION이 발생하거나 요소를 탐색하지 못하는 문제가 발생할 수 있다.
문제점
CooncurrentModificationException 발생 가능성
반복문에서 순회 중, 일부 요소가 탐색에서 누락될 수 있는 가능성
반복문 순회 중, 일부 요소가 탐색에서 누락될 수 있는 가능성
아래 코드처럼 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
문제점 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는 탐색되지 못한다.
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);
}
}
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);
}
}
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/