JAVA

Iterator, for문과의 차이

yebin0322 2025. 1. 26. 21:27
반응형

Iterator(반복자)

Interface Iterator<E>
  • Java Collections Framework의 일부
  • 컬렉션을 순회하는 데 사용되는 인터페이스
    • 리스트를 순회할 수 있게 해 주는 객체
  • 배열이나 그와 유사한 자료구조의 내부요소를 순회하는 객체

타입 매개변수 E

  • 반복자가 반환하는 요소의 타입

사용 이유

for문과 같은 반복문을 사용해도 되지만 Iterator를 사용하는 이유는 다음과 같다

  1. index가 없어도 반복문 사용 가능
List<String> list = Arrays.asList("A", "B", "C", "D");
Iterator<String> iterator = list.iterator();

while (iterator.hasNext()) {
    String element = iterator.next();
    System.out.println(element);
}
  1. 모든 컬렉션에서 사용 가능 : index가 없는 set과 같은 컬렉션에서도 사용 가능
Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3, 4));
Iterator<Integer> iterator = set.iterator();

while (iterator.hasNext()) {
    Integer number = iterator.next();
    System.out.println(number);
}
  1. 코드 간결성 : forEach 메소드를 사용해 코드가 더 간결해짐
List<String> list = Arrays.asList("A", "B", "C", "D");
list.forEach(System.out::println);
  • forEach 메소드는 내부적으로 Iterator를 사용하여 컬렉션의 요소를 순회
  1. 안전한 삭제
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
Iterator<String> iterator = list.iterator();

while (iterator.hasNext()) {
    String element = iterator.next();
    if (element.equals("B")) {
        iterator.remove(); // 안전하게 요소 삭제
    }
}

System.out.println(list); // [A, C, D]
  1. 빠른 속도
    배열의 경우는 index를 사용하여 요소에 접근하기 때문에 O(1)로 매우 빠름. 하지만, 리스트나 트리처럼 인덱스로 직접 접근할 수 없는 요소의 경우에는 맨 처음 요소부터 순차적으로 접근해야 함. 이 경우 시간 복잡도는 O(n)이 되어 효율성이 떨어짐. 하지만 iterator를 사용하면 현재 위치를 기억하고 있기 때문에 다음 요소에 접근할 때 O(1)로 빠르게 접근할 수 있음.
  • "현재 위치를 저장한다"는 의미가 무엇일까? 그리고 for문의 경우도 순차적으로 1씩 인덱스가 증가하는데 왜 현재 위치를 저장하는 것이 도움이 되나?
    Iterator는 next()를 호출할 때 마다 현재 요소의 위치가 내부적으로 update된다. 하지만, for문의 경우에는 index 변수가 현재 요소의 위치를 나타내지만, 내부적으로는 매번 인덱스를 계산하여 접근하는 것이다. 아래 코드를 보면, 이해가 더 쉽다
//Iterator
package day5;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class IteratorExample {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("A", "B", "C", "D");
        Iterator<String> iterator = list.iterator();

        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);
        }
    }
}


//for문
package day5;

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

public class ForLoopExample {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("A", "B", "C", "D");

        for (int i = 0; i < list.size(); i++) {
            String element = list.get(i);
            System.out.println(element);
        }
    }
}

여기서 for문의 경우, list.get(i)를 호출하여 인덱스에 해당하는 요소에 접근하게 되는데, 이 과정에서 각 호출마다 리스트의 요소를 찾기 위한 계산이 필요하기 때문에 더 오래걸리는 것이다. 특히, LinkedList와 같은 데이터 구조에서는 해당 index에 도달하기 위해 list의 처음부터 순차적으로 탐색해야 하므로 시간 복잡도가 O(n)까지 증가하는 것이다.

실제 실행 시간을 비교해 보면, 반복문의 개수가 1000이 넘어가는 순간부터 반복문과 iterator의 성능 차이가 나는 것을 알 수 있다.

반응형