컬렉션을 순회하면서 선택된 원소를 제거해야 한다면 반복자의 remove 메서드를 호출해야 한다.
자바8부터는 Collection의 removeIf 메서드를 사용해 컬렉션을 명시적으로 순회하는 일을 피할 수 있다
//rank가 ACE인 카드들은 모두 제거하는 코드
for (Card card : deck) {
if (card.rank == Rank.ACE) {
//ConcurrentModificationException 발생
deck.remove(card);
}
}
//그렇다면 올바른 방법은?
//1. 인덱스를 이용한 제거
for (int i = 0; i < deck.size(); i++) {
Card card = deck.get(i);
if (card.rank == Rank.ACE) {
deck.remove(i);
i--; // 삭제 후 리스트의 인덱스가 하나씩 땡겨지므로 i를 하나 감소시킴
}
}
//2. Iterator를 이용한 제거
for (Iterator<Card> iter = deck.iterator(); iter.hasNext();) {
Card card = iter.next();
if (card.rank == Rank.ACE) {
iter.remove();
}
}
//3. removeIf를 사용하여 제거(전통적인 for문과 명시적인 인덱스나 Iterator를 쓰지않고 제거 가능)
deck.removeIf(card -> card.rank == Rank.ACE);
변형(transforming)
리스트나 배열을 순회하면서 그 원소의 값 일부 혹은 전체를 교체해야 한다면 리스트의 반복자나 배열의 인덱스를 사용해야한다.
//rank가 ACE인 카드들을 모두 DIAMOND ACE카드로 변경하는 코드
for (Card card : deck) {
if (card.rank == Rank.ACE) {
card = new Card(Suit.DIAMOND, Rank.ACE);
}
}
//오류가 발생하진 않지만, deck의 내부 객체들은 전혀 변경되지 않는다.
System.out.println(deck); //기존 deck과 동일
병렬 반복(parallel iteration)
여러 컬렉션을 병렬로 순회해야 한다면 각각의 반복자와 인덱스 변수를 사용해 엄격하고 명시적으로 제어해야한다.
Chapter : 9. 일반적인 프로그래밍 원칙
Item : 58. 전통적인 for문보다는 for-each문을 사용하라
Assignee : jseok0917
🍑 서론
전통적인 for문
🍑 본론
for-each문(향상된 for문)
전통적인 for문에서 버그를 찾아보자
for-each문을 사용한다면?
for-each문을 사용할 수 없는 상황
말이 이해가 안돼서 많이 헷갈렸다...Iterable 구현하기
🍑 결론
대부분의 상황에서 for-each문이 전통적인 for문보다 간결하고 명료한데다가 성능저하도 없으므로, 위 상황들을 제외하고선 왠만하면 for-each문을 사용하자
referenced by