본문 바로가기

카테고리 없음

item 58) 전통적인 for문보다는 For-each 문을 사용하라

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가 꺠지는 경우)
  • 변형 (리스트나 배열 순회중 값을 바꿔야하는 경우)
  • 병렬 반복(여러 컬렉션을 병렬로 순회해야하는 경우 각각의 반복자와 인덱스 변수를 명시해서 제어해야한다.)