728x90
- 우리의 주관심사는 배열, 컬렉션의 원소이지 반복자(Iterator)나 인덱스 변수가 아님(이를 접근하는 for문은 코드를 지저분하게 한다.)
- 잘못된 인덱싱을 할 가능성도 있음
- 컬렉션이나 배열이냐에 따라 코드 형태가 달라진다.
향상된 for문 : for-each (enhanced for statement)
- Iterator 인터페이스를 구현한 객체에서 사용가능함 (Collections, Array 등)
- 반복자와 인덱스 코드가 없음(오류 가능성 감소)
- 하나의 관용어구로 컬렉션, 배열을 모두 처리 가능
- 컬렉션을 중첩해서 사용할때 저지르는 실수 방지
enum Suit { CLUB, DIAMOND, HEART, SPADE}
enum Rank { ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING}
static Collection<Suit> suits = Arrays.asList(Suit.values());
static Collection<Rank> ranks = Arrays.asList(Rank.values());
List<Card> deck = new ArrayList<>();
for(Iterator<Suit> i = suits.iterator(); i.hasNext();) {
for(Iterator<Rank> j = ranks.iterator(); j.hasNext();) {
deck.add(new Card(i.next(), j.next()));
}
}
enum Suit { CLUB, DIAMOND, HEART, SPADE}
enum Rank { ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING}
static Collection<Suit> suits = Arrays.asList(Suit.values());
static Collection<Rank> ranks = Arrays.asList(Rank.values());
List<Card> deck = new ArrayList<>();
for(Iterator<Suit> i = suits.iterator(); i.hasNext();) {
for(Iterator<Rank> j = ranks.iterator(); i.hasNext();) {
deck.add(new Card(i.next(), j.next()));
}
}
- 1번째에서는 deck.add(new Card(i.next(), j.next())); 줄이 오류를 일으킨다.
- 원래대로 하면 숫자 1개당 rank가 여러번 불려야 하는데 저러면 숫자 1개에 rank 1개 불려 NoSuchElementException 을 던진다.
- 2번째 예제에서는 j.hasNext()를 써야하는데 i.hasNext()로 잘못 작성함
enum Suit { CLUB, DIAMOND, HEART, SPADE}
enum Rank { ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING}
static Collection<Suit> suits = Arrays.asList(Suit.values());
static Collection<Rank> ranks = Arrays.asList(Rank.values());
List<Card> deck = new ArrayList<>();
for(Suit suit : suits) {
for(Rank rank : ranks) {
deck.add(new Card(suit, rank));
}
}
For-Each를 사용하면 코드가 깔끔해지고 실수를 할 가능성도 줄어든다.
For-Each를 사용할수 없는 경우
- 파괴적인 필터링 (컬렉션 순회중에 remove 메서드를 호출해서 Iterator가 꺠지는 경우)
- 변형 (리스트나 배열 순회중 값을 바꿔야하는 경우)
- 병렬 반복(여러 컬렉션을 병렬로 순회해야하는 경우 각각의 반복자와 인덱스 변수를 명시해서 제어해야한다.)