먼저 iterator와 원형인 iterate의 사전적 정의가 무엇인지 확인해보자.
iterate : (계산, 컴퓨터 처리 절차를) 반복하다
iterator : 반복자
계산 같은 컴퓨터의 작업 처리 절차를 반복한다는 뜻 같다.
그럼 자바에서의 iterator는 뭘 반복한다는 것인가?
en.wikipedia.org/wiki/Iterator
프로그래밍에서 반복기는 개발자가 컨테이너, 특히 리스트를 순회할 수 있게 해주는 객체다. 다양한 유형의 반복기는 종종 컨테이너의 인터페이스를 통해 제공된다. 주어진 반복기의 인터페이스와 의미는 고정돼 있지만, 반복기는 컨테이너 구현의 기본 구조로 구현되는 경우가 많으며 반복기의 작동 의미를 사용하기 위해 컨테이너와 밀접하게 연결되는 경우가 많다. 반복자는 순회를 수행하고 컨테이너의 데이터 요소에 대한 액세스를 제공하지만 자체적으로 반복을 수행하진 않는다. 반복기는 데이터베이스 커서와 동작이 유사하다.
ko.wikipedia.org/wiki/%EB%B0%98%EB%B3%B5%EC%9E%90
반복자는 객체 지향적 프로그래밍에서 배열이나 그와 유사한 자료구조의 내부요소를 순회하는 객체다
배열 따위의 자료구조 안을 돌면서 들어있는 데이터에 접근할 수 있게 해주는 객체라는 것 같다.
ArrayList에도 적용할 수 있을텐데, 그렇다면 ArrayList 이외의 다른 컬렉션에서도 적용할 수 있지 않을까?
www.w3schools.com/java/java_iterator.asp
iterator는 ArrayList, HashSet과 같은 컬렉션을 반복하는 데 사용할 수 있는 객체다. iterator는 반복의 기술 용어기 때문에 반복자라고 한다
컬렉션에서도 충분히 사용 가능한 듯하다.
그런데 궁금한 게 있다. 컬렉션을 반복하고 그 안의 데이터에 접근하기 위해서라면 for, while 같은 반복문을 써서도 충분히 가능할 터다. iterator는 왜 만들어진 건가?
stackoverflow.com/questions/22267919/iterator-vs-for
리스트에는 인덱스가 있지만 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+
- 유효성 검사 예제
ex) 전화번호 - 핸드폰
String regex_phoneNum = "^01([0|1|6|7|8|9])-?([0-9]{4})-?([0-9]{4})$";
while(!Pattern.matches(regex_phoneNum, phoneNum)){
out.println("전화번호의 형식이 일치하지 않습니다. 다시 입력해주세요.");
out.print("전화번호 (ex. 012-3456-7890): ");
phoneNum = sc.nextLine();
}
return phoneNum;
'Study > 개발일지' 카테고리의 다른 글
[백엔드스터디WIL]3주차 학습일지 (3) | 2023.06.09 |
---|---|
[백엔드온라인TIL] java 학습 12일차 (0) | 2023.06.08 |
[백엔드온라인TIL] java 학습 10일차 (0) | 2023.06.05 |
[백엔드스터디WIL]3주차 학습일지 (0) | 2023.06.02 |
[백엔드온라인TIL] java 학습 9일차 (0) | 2023.06.02 |