문제를 해결할 직관적인 방법은 리스트를 순회하며 변질된 제품을 찾고 그 후 앞에서 발견했던 제품을 모두 제거하는 것입니다. 먼저 순회하고 나중에 수정하는 두 단계 접근법이죠.
잘 동작하지만 코드 몇 줄이 더 필요합니다. 게다가 순회하는 동안 변질된 제품을 임시 자료 구조에 저장해야 합니다. 시간과 메모리가 더 드네요.
위 해법에서는 supplies 컬렉션의 Iterator를 활용하는 while 루프라는 새로운 순회 방식을 사용합니다. 핵심은 Iterator입니다. Iterator는 첫 번째 원소부터 시작해 리스트 내 원소를 가리키는 포인터처럼 동작합니다. hasNext()를 통해 원소가 남아 있는지 묻고 next()로 다음 원소를 얻고 반환된 마지막 원소를 remove()로 안전하게 제거합니다.
List를 직접 수정할 수는 없지만 iterator가 이것을 완벽히 대신합니다. iterator는 순회 중에도 모든 작업을 올바르게 수행합니다.
엄밀히 말해 이전 예제의 for-each 루프도 iterator에 기반하지만 프로그래머에게 그 사실을 숨깁니다. 코드의 복잡도를 줄여주니 반가운 일이죠. 하지만 덕분에 iterator의 remove() 메서드도 쓸 수 없습니다.
CopyOnWriteArrayList와 같은 특수 List 구현은 순회하며 수정하기도 합니다. 하지만 대가가 따릅니다. 리스트에 원소를 추가하거나 제거할 때마다 매번 전체 리스트를 복사하고 싶은가요? 자바 8부터는 람다를 사용하는 Collection.removeIf() 메서드도 사용할 수 있습니다. 하지만 이 메서드를 사용하기 전에 8장 데이터 흐름을 꼭 읽어보세요!