for
문for (Iterator<Element> i = c.iterator(); i.hasNext()) {
Element e = i.next();
// do something with e...
}
for (int i = 0; i < a.length; i++) {
// do something with e...
}
[아이템 57] 에서 보았듯이, 위의 관용구들은 while
문보다는 낫지만 가장 좋은 방법은 아니다.
⭐ 전통적인 for문의 문제점
1. 반복자와 인덱스 변수는 모두 코드를 지저분하게 할 뿐, 우리에게 진짜 필요한 건 **원소**들뿐이다.
2. 사용되는 요소 종류가 늘어나면 오류 가능성이 높아진다.
3. 잘못된 변수를 사용했을 때 컴파일러가 잡아준다는 보장이 없다.
4. 컬렉션이냐 배열이냐에 따라 코드 형태가 많이 다르다.
for-each
문위의 문제들은 모두 for-each(enhanced for statement)
문을 사용하면 해결된다.
⭐ for-each문의 장점
1. 반복자와 인덱스 변수를 사용하지 않아 코드가 깔끔하고 오류가 나지 않는다.
2. 하나의 관용구로 컬렉션과 배열을 모두 처리할 수 있다.
for (Element e : elements) {
... // e로 무언가를 한다.
}
컬렉션을 중첩하여 순회해야 한다면 for-each
문의 이점이 더욱 커진다.
다음 코드에서 버그를 찾아보자! 반복문을 중첩할 때 흔히 저지르는 실수가 담겨있다.
import java.util.*;
public class Card {
private final Suit suit;
private final Rank rank;
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());
Card(Suit suit, Rank rank ) {
this.suit = suit;
this.rank = rank;
}
public static void main(String[] args) {
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()));
}
}
위의 코드의 문제점은 suits
의 반복자에서 next
메서드가 너무 많이 호출된다는 것이다.
next
메서드는 ‘숫자(Suit
) 하나당’ 한 번씩만 불려야 하는데, 안쪽 반복문에서 호출되는 바람에 ‘카드(Rank
) 하나당’ 한 번씩 호출되고 있다.