HihoBookStudy / EffectiveJava

이펙티브 자바 북스터디입니다.
1 stars 0 forks source link

[Item 57] iterator vs for #46

Open IAGREEBUT opened 2 days ago

IAGREEBUT commented 2 days ago

반복의 대표적인 방법인 iterator를 통한 반복과 for문 반복의 차이점을 명확하게 정리하고 넘어가고 싶어서 stackoverlfow에 있는 글을 번역해서 가져왔습니다

https://stackoverflow.com/questions/22267919/iterator-vs-for

IAGREEBUT commented 2 days ago

먼저, loop에는 2가지 종류가 있으며, 이 둘은 작동방식이 매우 다릅니다.

첫번째는 인덱스를 이용하는 방법입니다.

for (int i = 0; i < list.size(); i++) {
  Thing t = list.get(i);
    ...
}

이 방법은 항상 사용가능한 것은 아닙니다. 예를 들면, List는 인덱스가 있지만, Set은 그렇지 않죠(unordered 컬렉션이기 때문에).

2번째 방법은 foreach를 사용하는 방법인데, for each는 내부적으로는 iterator를 이용하고 있습니다.

for (Thing thing : list) {
    ...
}

이 방법은 모든 종류의 Iterable collection/array에서 사용가능한 방법입니다.

마지막 방법은, Iterator를 이용하는 방법인데, 마찬가지로 모든 종류의 Iterable에서 사용가능한 방법입니다.

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    Thing t = it.next();
    ...
}

결론적으로 3개의 loop문이 있는건데 비교해보면 다음과 같습니다.

이렇게 4가지 측면으로 비교해볼 수가 있는데 성능, 가독성, 오류가능성, 능력치(? 어떤 기능을 가지고 있는가) performance, readability, error-proneness, capabaility

Iterator는 foreach loop가 할 수 없는 것들을 해낼 수 있습니다. iterator가 remove 기능을 지원한다면, 반복중에 요소들을 제거할 수 있습니다

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    Thing t = it.next();
    if (shouldBeDeleted(thing) {
        it.remove();
    }
} 

List는 양방향으로 반복이 가능한 iterator를 제공합니다. foreach loop 시작부분 부터만 반복이 가능합니다 (역방향 불가능) 그러나 iterable은 훨씬 더 위험하고 가독성이 떨어집니다. foreach loop를 사용해도 충분한 경우에는 이를 사용하는 것이 가장 가독성이 좋은 방법입니다. iterator를 이용하면 다음과 같은 코드에서 에러가 나는데

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    System.out.println(it.next().getFoo());
    System.out.println(it.next().getBar());
} 

foreach loop를 사용하는 경우에는 다음과 같은 에러가 발생하는 상황을 허용하지 않습니다.

인덱스를 이용하여 element에 접근하는 경우는 collection이나 array를 뒤에서부터 반복하는 경우에 조금 더 효과적입니다. 하지만 ArrayList대신에 LinkedList를 이용하는 경우 성능면에서 매우 나빠질 수 있습니다. 왜냐면 list.get(i)를 통해 접근을 시도할 때마다, linked list는 i번째 원소에 도달할 때까지 모든 원소를 탐색해야할 것이기 때문입니다. iterator는 위와같은 문제가 발생하지 않습니다. iterator를 사용하는 경우에 주어진 collection에 대해 항상 가능한 최선의 방법으로 반복이 이루어지는데 모든 collection은 자신만의 iterator를 implement했기 때문입니다.

정리해보자면 다음과 같습니다. iterator가 제공하는 기능을 써야만 원하는 기능을 구현해낼 수 있는 상황이 아니라면 foreach를 이용해라. 인덱스를 통한 for문은 array나, loop를 반복하는 도중에 index 변수를 사용해야하는 경우에만 사용해라.

[추가] Iterator의 장점

  1. collection을 순회하면서 요소를 삭제할 수 있다.
  2. next(), previos()메서드를 사용해서 collection을 앞뒤로 탐색할 수 있다
  3. hasNext()메서드를 사용하여 요소가 더 있는지 없는지를 판단할 수 있다.