Home [Effective Java] Item58. 전통적인 for 문보다는 for-each 문을 사용하라!
Post
Cancel

[Effective Java] Item58. 전통적인 for 문보다는 for-each 문을 사용하라!

Item58. 전통적인 for 문보다는 for-each 문을 사용하라!

Intro

  • 아이템 45에서 봤듯이 스트림이 제격인 작업이 있고, 반복이 제격인 작업이 있다.

전통적인 for 문

1
2
3
4
5
6
7
8
9
10
// Collection
for (Iterator<String> iter = c.iterator(); iter.hasNext()) {
  	Element e = iter.next();
    // ...
}

// Array
for (int i = 0; i < a.length; i++) {
    // ...
}
  • 이 관용구들은 while 문보다는 낫지만 가장 좋은 방법은 아니다.
  • 이러한 경우, 원소에만 접근하면 되니 반복자나 인덱스 변수는 코드를 지저분하게 할 뿐이다.
  • 사용하는 요소 종류가 늘어나면 오류가 생길 가능성이 높아진다.
  • 컬렉션이냐 배열이냐에 따른 코드 형태 차이도 상당하므로 주의해서 사용해야 한다.

for-each 문

1
2
3
for (Element e : elements) {
    // ...
}
  • 앞서 나열한 for 문의 단점들이 for-each를 사용하면 모두 해결된다.
  • 반복자와 인덱스를 사용하지 않으니 코드가 깔끔해지고 오류가 날 일도 없다.
  • 하나의 관용구로 컬렉션 배열 처리 모두 가능하다. 어떤 컨테이너를 다루는지 신경쓸 필요가 없어진다.
  • 컬렉션을 중첩 순회하는 경우 for-each 문의 이점이 더 커진다고 볼 수 있다.

for-each 문을 사용할 수 없는 경우

  1. 파괴적인 필터링(destructive filtering)
    • 컬렉션을 순회하면서 선택된 원소를 제거해야 한다면 반복자의 remove 메서드를 사용해야 한다.
    • 자바 8부터는 Collection의 removeIf 메서드를 사용해 컬렉션의 명시적 순회를 피할 수 있게 되었다.
  2. 변형(transforming)
    • 리스트나 배열을 순회하면서 그 원소의 값 일부 혹은 전체를 교체해야 한다면 리스트의 반복자나 내열의 인덱스를 사용해야 한다.
  3. 병렬 반복(parallel iteration)
    • 여러 컬렉션을 병렬로 순회해야 한다면 각각의 반복자와 인덱스 변수를 사용해 엄격하고 명시적으로 제어해야 한다.
  • 이 세가지 경우에 해당한다면 일반적인 for 문을 사용하자.

Iterable

  • for-each 문은 컬렉션과 배열은 물론 Iterable 인터페이스를 구현한 객체라면 무엇이든 순회할 수 있다.
1
2
3
4
// 메서드가 단 하나뿐인 Iterable 인터페이스
public interface Iterable<E> {
  	Iterator<E> iterator(); // 이 객체의 원소들을 순회하는 반복자를 반환한다.
}
  • Iterable을 처음부터 구현하긴 까다롭지만, 원소들의 묶음을 표현하는 타입 작성 시 Iterable을 구현하는 것을 고려하자.
    • 그럼 그 타입을 사용하는 사용자가 for-each 문을 사용할 수 있고, 고마워할 것이다.

핵심 정리

  • 전통적인 for 문과 비교했을 때 for-each 문은 명료하고, 유연하고, 버그를 예방해준다.
  • 성능 저하도 없다.
  • 가능한 모든 곳에서 for 문이 아닌 for-each 문을 사용하자.
This post is licensed under younghwani by the author.

[Effective Java] Item57. 지역변수의 범위를 최소화하라!

[Effective Java] Item59. 라이브러리를 익히고 사용하라!

Comments powered by Disqus.