IT박스

반복자 대

itboxs 2020. 11. 20. 08:45

반복자 대


인터뷰에서 for 루프를 사용하는 반복자를 사용하는 이점이 무엇인지 또는 반복자보다 for 루프를 사용하는 이점이 무엇인지 질문을 받았습니다.

앞으로 비슷한 질문에 직면하면 대답 할 수있게


우선, 매우 다르게 작동하는 두 종류의 for 루프가 있습니다. 하나는 인덱스를 사용합니다.

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

이런 종류의 루프가 항상 가능한 것은 아닙니다. 예를 들어 목록에는 인덱스가 있지만 집합은 순서가없는 컬렉션이기 때문에 인덱스가 없습니다.

다른 하나, foreach 루프는 뒤에서 반복자를 사용합니다.

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

이것은 모든 종류의 Iterable 컬렉션 (또는 배열)에서 작동합니다.

마지막으로 모든 Iterable과 함께 작동하는 Iterator를 사용할 수 있습니다.

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

따라서 실제로 비교할 3 개의 루프가 있습니다.

성능, 가독성, 오류 발생 가능성, 기능 등 다양한 측면에서 비교할 수 있습니다.

반복자는 foreach 루프가 할 수없는 일을 할 수 있습니다. 예를 들어 반복자가 지원하는 경우 반복하는 동안 요소를 제거 할 수 있습니다.

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

목록은 또한 양방향으로 반복 할 수있는 반복기를 제공합니다. foreach 루프는 처음부터 끝까지 만 반복됩니다.

그러나 Iterator는 더 위험하고 가독성이 떨어집니다. foreach 루프가 필요한 경우 가장 읽기 쉬운 솔루션입니다. 반복기를 사용하면 버그가 될 수있는 다음을 수행 할 수 있습니다.

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

foreach 루프는 이러한 버그가 발생하는 것을 허용하지 않습니다.

인덱스를 사용하여 요소에 액세스하는 것은 배열로 지원되는 컬렉션에서 약간 더 효율적입니다. 그러나 마음이 바뀌고 ArrayList 대신 LinkedList를 사용하면 갑자기 성능이 끔찍할 것입니다..에 액세스 할 때마다 list.get(i)연결된 목록이 i 번째 요소까지 모든 요소를 ​​반복해야하기 때문입니다. 반복자 (따라서 foreach 루프)에는이 문제가 없습니다. 컬렉션 자체에 자체 Iterator 구현이 있기 때문에 항상 주어진 컬렉션의 요소를 반복하는 가장 좋은 방법을 사용합니다.

나의 일반적인 경험 법칙은 : 정말 반복자의 기능이 필요하지 않다면 foreach 루프를 사용하는 것입니다. 루프 내부의 인덱스에 액세스해야 할 때 배열이있는 인덱스와 함께 for 루프 만 사용합니다.


반복기 장점 :

  • 컬렉션에서 요소를 제거하는 기능.
  • 사용하여 앞뒤로 이동하는 능력 next()previous().
  • 를 사용하여 더 많은 요소가 있는지 확인하는 기능 hasNext().

루프는 이상 만 반복 설계되었습니다 Collection당신은을 통해 단지 반복 할 그렇다면, Collection같은 그것의 더 나은 사용에 루프를 for-Each,하지만 당신은 더 원하는 경우 Iterator를 사용할 수있다.


숫자 (예 : "i")로 데이터에 액세스하면 어레이를 사용할 때 빠릅니다. 요소로 직접 이동하기 때문에

그러나 다른 데이터 구조 (예 : 트리, 목록)는 첫 번째 요소에서 대상 요소로 시작하기 때문에 더 많은 시간이 필요합니다. 목록을 사용할 때. 시간 O (n)이 필요합니다. 그래서 천천히하는 것입니다.

반복자를 사용하면 컴파일러는 현재 위치를 알고 있습니다. 그래서 O (1)이 필요합니다 (현재 위치에서 시작하기 때문입니다)

finally, if you use only array or data structure that support direct access(e.g. arraylist at java). "a[i]" is good. but, when you use other data structure, iterator is more efficient


The main difference between Iterator and the classic for loop, apart from the obvious one of having or not having access to the index of the item you're iterating, is that using Iterator abstracts the client code from the underlying collection implementation, allow me to elaborate.

When your code uses an iterator, either in this form

for(Item element : myCollection) { ... }

this form

Iterator<Item> iterator = myCollection.iterator();
while(iterator.hasNext()) {    
    Item element = iterator.next();    
    ... 
}

or this form

for(Iterator iterator = myCollection.iterator(); iterator.hasNext(); ) {
   Item element = iterator.next();
   ...
}

What your code is saying is "I don't care about the type of collection and its implementation, I just care that I can iterate through its elements". Which is usually the better approach, since it makes your code more decoupled.

On the other hand, if you're using the classic for loop, as in

for(int i = 0; i < myCollection.size(); i++) {
   Item element = myCollection.get(i);
   ...
}

Your code is saying, I need to know the type of collection, because I need to iterate through its elements in a specific way, I'm also possibly going to check for nulls or compute some result based on the order of iteration. Which makes your code more fragile, because if at any point the type of collection you receive changes, it will impact the way your code works.

Summing it up, the difference is not so much about speed, or memory usage, is more about decoupling your code so that is more flexible to cope with change.

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