아이템 45에서 다루었다시피 stream이 제격인 작업이 있고 반복이 제격인 작업이 있습니다.
앞서 아이템 57에서도 언급했듯이 for문과 같은 광용구들은 while문보다는 낫지만 다음 이유 때문에 최선의 방법은 아닙니다.
- 진짜 필요한 것은 원소들 뿐이지만 위 코드처럼 작성할 경우 반복자와 인덱스 변수 모두 선언해야 하기 때문에 코드가 지저분해짐
- 컬렉션이나 배열이여냐에 따라 코드 형태가 달라짐
for-each문
- 정식 이름은 `향상된 for문(enhanced for statement)`
- for-each 문은 컬렉션과 배열은 물론 Iterable 인터페이스를 구현한 객체라면 무엇이든 순회 가능
- 반복자와 인덱스 변수를 사용하지 않기 때문에 코드가 깔끔해지고 오류가 날 일이 없음
- 하나의 관용구로 되어있어 컬렉션과 배열 모두 같은 코드 형태이며 성능도 동일
- 콜론(:)은 안의(in) 라고 읽으면 됨
- 따라서 아래 코드의 반복문은 `elements 안의 각 원소 e에 대해`라고 해석하면 됨
1. 중첩 컬렉션에서 for-each문의 이점 극대화
코드 부연 설명
- 위 코드에서 Iterator를 사용할 경우 `deck.add(new Card(i.next(), j.next()));`에서 NoSuchElementException 예외 발생
- next()가 Suit 하나당 한 번식만 불려야 하는데
- 안쪽 반복문에서 호출되는 바람에 Rank 하나당 한 번씩 불렸기 때문
- 위 코드를 고친다고 해도 코드가 지저분해지는 단점 존재
- 반면 for-each문을 사용하면 깔끔하고 간단하게 오류를 유발하지 않는 코드를 작성할 수 있음
2. for-each문을 사용할 수 없는 케이스
2.1 파괴적인 필터링(destructive filtering)
- 리스트를 순회하면서 원소를 제거할 때, 리스트의 구조가 변경되면서 ConcurrentModificationException이 발생
- 컬렉션을 순회하면서 선택된 원소를 제거해야 할 경우 반복자의 remove 메서드를 호출해야 함
- 자바 8버전부터 Collection의 removeIf 메서드를 사용해 컬렉션을 명시적으로 순회하지 않아도 됨
2.2 변형(transforming)
- 리스트나 배열을 순회하면서 원소 값 일부 혹은 전체를 교체하는 경우에는 인덱스를 사용해야 함
- ex) arr[i] = 1;
2.3 병렬 반복(parallel iteration)
- 여러 컬렉션을 병렬로 순회해야 할 경우 각각의 반복자와 인덱스 변수를 사용해 엄격하고 명시적으로 제어해야 함
- for-each문은 각각의 요소에 대해 반복할 때마다 내부적으로 반복자(iterator)를 사용하여 요소를 가져오는데, 이러한 반복자는 병렬 처리를 지원하지 않음
참고
이펙티브 자바
반응형
'JAVA > Effective Java' 카테고리의 다른 글
[아이템 60] 정확한 답이 필요하다면 float와 double은 피하라 (0) | 2024.03.17 |
---|---|
[아이템 59] 라이브러리를 익히고 사용하라 (0) | 2024.03.17 |
[아이템 57] 지역변수의 범위를 최소화하라 (0) | 2024.03.16 |
[아이템 56] 공개된 API 요소에는 항상 문서화 주석을 작성하라 (0) | 2024.03.13 |
[아이템 55] 옵셔널 반환은 신중히 하라 (0) | 2024.03.12 |