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

이월(0216tw)·2024년 6월 12일
0

effective java

목록 보기
1/7

for-each (향상된 for문)

for문과 똑같이 특정 동작을 반복하거나, 특정 객체(배열이나 컬렉션 등) 의 요소들을 반복적으로 순회하여 데이터를 가져오는데 사용한다.

다만, for문이 가지고 있던 아쉬운 점을 개선한 향상된 for문이다.


for문의 아쉬운 점과 for-each의 가독성

반복자와 인덱스 변수로 지저분해보임

예제1


for(int i = 0 ; i< arr.length; i++) {
	if(arr[i] == 2) { 
    	System.out.println("네가 숫자 2구나"); 
    }
}

//향상된 for문 버전
//코드 수는 큰 차이 없지만 가독성이 향상되고 덜 지저분하다
for(int num : arr ) {
	if(num == 2) {
    	System.out.println("네가 숫자 2구나"); 
    }
}

예제2

//iterator와 함께 쓰일경우 hasNext로 조건을 확인하고
//next로 가져오면서 따로 저장을 해야한다. 안그러면 포인터가 그냥 넘어간다
for (Iterator<First> i = first.iterator(); i.hasNext(); ) {
	First firstData = i.next(); 
    
    for(Iterator<Second> j = second.iterator(); j.hasNext(); ) {
    	adder.add(new Adder(firstData , j.next()));
    }
}

//향상된 for문 버전 
//훨씬 가독성이 증가한 것을 볼 수 있음
for(First firstData : first) {
	for(Second secondData : second) {
    	adder.add(new Adder(firstData , secondData)); 
    }
}

for-each 사용이 어려운 경우

특정원소를 파괴(remove)해야하는 파괴적 필터링인 경우

foreach문 내부에서 요소를 제거하려고 하면 ConcurrentModificationException 발생
왜냐하면 해당 컬렉션이 반복되는 동안 컬렉션이 변경되지 않도록 설계된 메커니즘때문임

  • 해결방법
    (1) 전통적인 for문을 사용해서 인덱스 기반으로 접근 및 제거를 한다.
 // 전통적인 for문을 사용하여 파괴적인 필터링 수행
        for (int i = 0; i < numbers.size(); i++) {
            if (numbers.get(i) % 2 != 0) {
                numbers.remove(i);
                i--; // 요소 제거 후 인덱스 조정
            }
        }
        ...

(2) Iterator의 remove로 안전하게 제거한다.

  // Iterator를 사용하여 파괴적인 필터링 수행
        Iterator<Integer> iterator = numbers.iterator();
        while (iterator.hasNext()) {
            int num = iterator.next();
            if (num % 2 != 0) {
                iterator.remove();
            }
        }
        ...

파괴뿐 아니라 특정 원소를 변경하고 싶을때 반복자나 인덱스가 필요한데 이 부분에 한계가 있음


결론

가급적 for-each문을 사용해서 가독성을 확보하자
만약 for-each를 사용할 수 없는 케이스라면 그 때는 for를 쓰자

profile
Backend Developer (Financial)

0개의 댓글