[Effective Java]일반적인 프로그래밍 원칙들_2

Kim Ji Yun·2021년 11월 23일
0

Effective Java

목록 보기
2/9
post-thumbnail

2. for문 보다는 for-each문을 사용하라

  • for-each문은 전통적인 for문에 비해 명료하고 버그 발생 가능성도 적으며, 성능도 for문에 뒤지지 않음

ex05) 컬렉션이나 배열 순회 시 예제

// 컬렉션이나 배열 순회할 때는 이 숙어를 따르자 
for (Element e : elements) {
    doSomthing(e);
}
  • for-each문에서 ‘:’ 기호는 “안에있는(in)" 의 의미
  • 해석 : elements 안에 있는 e 각각에 대해서 순회

ex06) 두 개의 컬렉션에 대한 순환문을 중첩시킬 때 발생하는 버그

enum Suit { CLUB, DIAMOND, HEART, SPADE }
enum Rank { ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT,
    NINE, TEN, JACK, QUEEN, KING }
...
Collection<Suit> suits = Arrays.asList(Suit.values());
Collection<Rank> ranks = Arrays.asList(Rank.values());
List<Card> deck = new ArrayList<Card>();
for (Iterator<Suit> i = suits.iterator(); i.hasNext(); )
    for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); )
deck.add(new Card(i.next, j.next()));
  • 바깥쪽 순환문 안에서 카드 종류별로 4회 호출되어야 하는데, 안쪽 순환문에서 호출되어 카드 숫자별로 13회 호출됨
  • NoSuchElementException 발생

ex07) 두 개의 컬렉션에 대한 순환문을 중첩시킬 때 발생하는 버그2

// 주사위를 두 번 굴렸을 때 얻을 수 있는 모든 조합 출력
enum Face { ONE, TWO, THREE, FOUR, FIVE, SIX }
...
Collection<Face> faces = Arrays.asList(Face.values());
for (Iterator<Face> i = faces.iterator(); i.hasNext(); )
    for (Iterator<Face> j = faces.iterator(); j.hasNext(); )
System.out.println(i.next() + " " + j.next());
  • 위 프로그램은 예외를 발생하지 않으나 짝패만 출력하게 됨(“ONE ONE”부터 “SIX SIX”)

ex08) ex06)을 해결하기 위한 방법

for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) {
    Suit suit = i.next();
    for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); )
deck.add(new Card(suit, j.next()));
}
  • 바깥쪽 순환문의 유효범위 안에 새로운 변수 추가

ex09) for-each문을 중첩하여 간결하게 코딩한 예제

for (Suit suit : suits)
    for (Rank rank : ranks)
deck.add(new Card(suit, rank));
  • for-each문으로 컬렉션과 배열뿐 아니라 Iterable 인터페이스를 구현하는 어떤 객체도 순회할 수 있음

ex10) Iterable 인터페이스

public interface Iterable<E> {
	// 이 Iterable 안에 있는 원소들에 대한 반복자 반환 
	Iterator<E> iterator();
}
  • 원소들의 그룹을 나타내는 자료를 작성할 때는 Iterable을 구현하여 클라이언트가 for-each 문을 통해 해당 자료형을 순회할 수 있도록 함

for-each문 미적용 사항

1. 필터링(filtering)
컬렉션을 순회하다가 특정한 원소를 삭제할 필요가 있다면, 반복자의 remove 메서드를 호출해야 하기 위해 반복자를 명시적으로 사용.
2. 변환(transforming)
리스트나 배열을 순회하다가 그 원소 가운데 일부 또는 전부의 값을 변경해야 한다면, 원소의 값을 수정하기 위해 리스트 반복자나 배열 첨자가 필요.
3. 병렬순회(parallel iteration)
여러 컬렉션을 병렬적으로 순회해야 하고, 모든 반복자나 첨자 변수가 발맞춰 나아가도록 구현해 야 한다면 반복자나 첨자변수를 명시적으로 제어

0개의 댓글