문제 상황
도서와 나눔 이벤트 간의 연관 관계를 삭제하는 과정에서 ConcurrentModificationException이 발생하였다.
이 오류는 컬렉션을 순회하는 동안 해당 컬렉션의 구조가 변경될 때 발생한다.
원인
bookDonationEvent.getBooks().stream().forEach(book->{
book.changeStatus(BookStatusEnum.POSSIBLE);
book.removeBookApplyDonation();
});
Java
복사
코드에서 bookDonationEvent.getBooks().forEach() 를 사용하여 도서 리스트를 순회하면서 각 도서의 상태를 변경하고 연관 관계를 제거하는 bookDonationEvent.removeBook(book)를 호출하였다.
이 때문에 순회 중인 리스트의 구조가 변경되면서 ConcurrentModificationException이 발생하였다.
해결 방법
•
일반 for문 사용하여 해결한다.
리스트의 크기를 미리 얻어와서 반복하는 동안 해당 리스트의 구조가 변경되지 않도록 처리할 수 있다.
그러나 리스트의 중간 요소를 삭제할 때 인덱스의 변화를 주의해야 한다.
이를 해결하기 위해 가장 끝부터 for문을 반복하면 해결이 가능하다.
/**
* 연관 관계 삭제
* 도서와 나눔 이벤트 간의 연관 관계 삭제
*/
int bookSize = bookDonationEvent.getBooks().size();
for (int i = bookSize - 1; i >= 0; i--) {
bookDonationEvent.getBooks().get(i).changeStatus(BookStatusEnum.POSSIBLE);
bookDonationEvent.removeBook(bookDonationEvent.getBooks().get(i));
}
/**
* 도서와 나눔 신청 간의 연관 관계 삭제
*/
int applysize = bookDonationEvent.getBookApplyDonations().size();
for (int i = applysize - 1; i >= 0; i--) {
Book book = bookRepository.findById(bookDonationEvent.getBookApplyDonations().get(i).getBook().getBookId()).orElseThrow(
() -> new IllegalArgumentException("해당 책이 존재하지 않습니다.")
);
BookApplyDonation bookApplyDonation = bookApplyDonationRepository.findById(bookDonationEvent.getBookApplyDonations().get(i).getApplyId()).orElseThrow(
() -> new IllegalArgumentException("해당 신청이 존재하지 않습니다.")
);
bookApplyDonation.removeBook(book);
int a;
}
Java
복사
정리
컬렉션을 순회하면서 동시에 해당 컬렉션의 구조를 변경할 때는 ConcurrentModificationException이 발생할 위험이 있다.