리스트에는 인덱스가 있지만 Set은 순서가 없는(unordered) 컬렉션이기 때문에 인덱스가 없다...(중략)...iterator는 for-each 반복문이 할 수 없는 일을 할 수 있다. 예를 들어 iterator가 지원하는 경우 반복하는 동안 요소를 제거할 수 있다...(중략)...리스트는 또한 양방향으로 반복할 수 있는 iterator를 제공한다. for-each 반복문은 처음부터 끝까지만 반복된다...(중략)...인덱스를 사용해 요소에 접근하는 것은 배열로 지원되는 컬렉션에서 약간 더 효율적이다.
그러나 ArrayList 대신 LinkedList를 사용하면 list.get(i)에 액세스할 때마다 연결된 리스트가 i번째 요소까지 모든 요소를 반복해야 하기 때문에 성능이 나빠질 것이다. iterator(따라서 for-each 루프)에는 이 문제가 없다. 컬렉션 자체에 iterator 구현이 있기 때문에 항상 주어진 컬렉션의 요소를 반복하는 가장 좋은 방법을 사용한다
Iterator의 장점
1. 컬렉션에서 요소를 제어하는 기능
2. next() 및 previous()를 써서 앞뒤로 이동하는 기능
3. hasNext()를 써서 더 많은 요소가 있는지 확인하는 기능
자료구조 중 Set의 경우 인덱스가 없기 때문에 일반 for문을 사용할 수 없지만, for-each문은 사용할 수 있다.
그러나 for-each문으로 자료구조를 돌다가 값을 수정, 삭제해야 해서 수정, 삭제를 수행하는 코드를 넣으면 ConcurrentModificationException이 발생한다.
성능 부분에선 뭐가 어떻게 좋은지 잘 모르겠지만, 인덱스가 없는 자료구조의 경우 그 안의 데이터를 돌기 위해서 for-each문과 iterator 중 하나의 방법으로 가져올 수 있단 건 알겠다.
그럼 이 iterator는 어떻게 쓰는 것인가? 간단한 예제를 확인해보자.
먼저 ArrayList에 iterator를 사용하는 것의 예시다.
import java.util.ArrayList;
import java.util.Iterator;
public class Main
{
public static void main(String[] args)
{
// 컬렉션 생성
ArrayList<String> cars = new ArrayList<>();
cars.add("벤츠");
cars.add("람보르기니");
cars.add("롤스로이스");
cars.add("페라리");
// iterator 획득
Iterator<String> iterator = cars.iterator();
// while문을 사용한 경우
while(iterator.hasNext())
{
String str = iterator.next();
System.out.println(str);
}
// for-each문을 사용한 경우
for (String str : cars)
{
System.out.println(str);
}
}
}
// >> 벤츠
// >> 람보르기니
// >> 롤스로이스
// >> 페라리
ArrayList를 만들고 값을 넣은 후, 이 리스트에 대해 iterator를 만든 다음 반복문을 통해 값을 출력하는 간단한 예제다.
간단하기로는 for-each문이 while문에 비해 상대적으로 간단해 보인다.
그럼 Set을 사용할 경우에는 iterator를 어떻게 사용할 수 있을까?
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Main
{
public static void main(String[] args)
{
Set<String> cars = new HashSet<>();
cars.add("벤츠");
cars.add("람보르기니");
cars.add("롤스로이스");
cars.add("페라리");
// while문을 사용한 경우
Iterator<String> iterator = cars.iterator();
while(iterator.hasNext())
{
System.out.println("cars : " + iterator.next());
}
// for-each문을 사용한 경우
for (String car : cars)
{
System.out.println("cars : " + car);
}
}
}
// >> cars : 람보르기니
// >> cars : 롤스로이스
// >> cars : 페라리
// >> cars : 벤츠
Set을 사용했기 때문에 출력 시 넣은 순서와 상관없이 값이 출력되는 걸 볼 수 있다.
마지막으로 iterator를 이용해 값을 수정하는 예제를 확인해보자.
import java.util.ArrayList;
import java.util.ListIterator;
public class Main
{
public static void main(String[] args)
{
// 컬렉션 생성
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
list.add("F");
System.out.println("while문 지나기 전 리스트에 들어있던 값 : " + list);
// 리스트에 들어있는 값에 각각 '+' 붙이기
ListIterator<String> listIterator = list.listIterator();
while(listIterator.hasNext())
{
Object element = listIterator.next();
listIterator.set(element + "+");
}
System.out.println("while문 지난 후 수정된 결과 : " + list);
// 리스트에 들어있는 값을 역순으로 표시
System.out.print("역순 출력 결과 : ");
while(listIterator.hasPrevious())
{
Object element = listIterator.previous();
System.out.print(element + " ");
}
System.out.println();
}
}
// >> while문 지나기 전 리스트에 들어있던 값 : [A, B, C, D, E, F]
// >> while문 지난 후 수정된 결과 : [A+, B+, C+, D+, E+, F+]
// >> 역순 출력 결과 : F+ E+ D+ C+ B+ A+