Iterator
이터레이터(Iterator)는 자바 컬렉션 프레임워크(Collection Framework)에 속해있는 인터페이스 중 하나.
Iterato를 구현한 클래스는 컬렉션 객체를 탐색, 데이터에 접근, 삭제할 수 있다.
Iterator 예제
public class Tester {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
System.out.println("List: ");
Iterator<Integer> listIterator = list.iterator(); // Iterator 타입 변수 생성 및 초기화
while(listIterator.hasNext()){
System.out.print(listIterator.next() + " ");
}
}
}
For-each(강화된 for 반복문)
'강화된 for 반복문(Enhanced for loop)'라고도 불리는 For-each 반복문은 자바 1.8 버전에서 추가됐으며 for/while,do-while 반복문과 비슷하게 동작하는 반복문이다.
다른 반복문과 다른점은 For-each 반복문은 이터레이터의 단점을 극복하기 위해 나왔다.
이터레이터를 사용하려면 매번 Iterator 타입의 변수 생성, 초기화해야 한다. 그리고 반복문을 통해 이터레이터의 내부에 있는 커서를 옮겨서 컬렉션 아이템을 탐색할 수 있다.
Iterator타입 객체를 사용하여 아이템을 탐색할 경우 기본 코드(boilerplate code)가 많아 진다.
예를 들어, 2차원 탐색처럼 컬렉션 아이템이 또다른 컬렉션 아이템을 담고 있는 경우 Iterator 타입의 변수 두 개를 생성하고, 초기화하고, 반복문을 코드를 작성해야 한다.
For-each 예제
public class Tester {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
System.out.println("List: ");
for (int i : list) {
System.out.print(i + " ");
}
}
}
Iterator와 For-each의 차이점
차이점 1. For-each 반복문은 처음부터 끝까지 모두 탐색한다.
공식 문서 정의에서 컬렉션 아이템을 처음부터 끝까지 모두 탐색하거나, 탐색 도중 예외(Exception)가 발생할 때까지 정해진 동작(탐색)을 수행한다고 되어 있다.
이전 For-each 예제처럼 1부터 6까지 정수값을 담고 있는 ArrayList 타입 컬렉션 객체를 For-each 반복문으로 탐색할 경우 1부터 3까지만 탐색하는것은 기본 동작에 없다는 것이다. if문 같은 조건문을 사용해서 예외처리를 해야만 반복문을 빠져 나올 수 있다.
차이점 2. For-each문은 ConcurrentModificationException 예외가 발생할 수 있다.
아래 코드는 물류창고에서 보관 중인 물품이 상했는지 확인하고(isContaminated() 메서드), 상했다면 해당 물품을 폐기하는(remove() 메서드) 작업을 하는 코드다.
class Inventory {
private List<Supply> supplies = new ArrayList<>();
void disposeConteminatedSupplies() {
for (Supply supply : supplies) {
if (supply.isContaminated()) {
supplies.remove(supply);
}
}
}
}
문제가 없어 보이지만 Supply 객체의 아이템 중 폐기해야 할 물품이 있어서 remove() 메서드를 실행하게 되면 ConcurrentModificationException 예외가 발생하게 된다. 이 예외는 수정할 수 없는 아이템을 수정하려는 상황에 발생한다.
For-each 반복문에서 각 아이템은 Iterable 타입이다. Iterable 인터페이스에는 컬렉션 아이템을 지우는 remove() 메서드 정의가 없다. Iterator 타입 아이템은 remove() 메서드를 이용하여 해당 아이템을 삭제할 수 있지만, Iterable 아이템에서는 불가능하다. Iterator와 비슷하게 탐색할 수는 있지만 100% 동일하지는 않은 것이다.
평소에 for / For-each / switch / while 등 여러 반복문을 편한대로 사용했었는데 이런 문제가 발생할 수 있다는 것을 책 '자바 코딩의 기술'을 읽으면서 세세하게 살펴보게 됐다. 기본에 충실해야 한다는게 이런건가보다.
참고 도서
자바 코딩의 기술 2.4장 '순회하며 컬렉션 수정하지 않기'
|
참고 사이트
Iterator vs forEach in Java : Link
Iterator vs Foreach In Java : Link
JSR-201 : Link
forEach : Link
The For-Each Loop : Link
ConcurrentModificationException : Link
Iterable<T> : Link
Iterator<E> : Link
'Study > Java' 카테고리의 다른 글
[Java] 정규표현식을 이용한 파일구분자 바꾸기 (0) | 2021.03.22 |
---|---|
자바 웹 프로젝트 디렉토리 구성 (0) | 2021.01.08 |
Oracle JDBC 예제 코드(PrepareStatement) (0) | 2020.11.11 |
자바스크립트로 서블릿 요청(Request)하기 (0) | 2020.11.11 |
세 가지 모듈(Module) - Java 9 Module, IntelliJ IDEA Module, Module of Build System (0) | 2020.10.25 |