Suddenly a project I have been working on is throwing a ConcurrentModificationException
when adding elements to a list and after trying to see what's going on for quite a while I am as confused as when this error first happened.
I have a Tournament
class and it is composed of Event
instances. Events have a list of timeslots List<Timeslot> timeslots
(when the matches are to be played). When creating an instance of a tournament, the tournament's timeslots are all the event's timeslots combined. Timeslots shared by different events are only added once.
See how I am instantiating a tournament (I am omitting the irrelevant arguments):
List<Localization> localizations = TournamentUtils.buildGenericLocalizations(1, "Court");
List<Timeslot> timeslots = TournamentUtils.buildSimpleTimeslots(8);
Event firstEvent = new Event(/*...*/, timeslots.subList(0, 2)););
Event secondEvent = new Event(/*...*/, timeslots);
Tournament tournament = new Tournament("Tournament", firstEvent, secondEvent);
And this is how the relevant part of the tournament constructor looks like:
public Tournament(String name, List<Event> categories) {
// ...
allPlayers = new ArrayList<>();
allTimeslots = new ArrayList<>();
allLocalizations = new ArrayList<>();
events = new ArrayList<>(categories);
for (Event event : events) {
event.getPlayers().stream().filter(p -> !allPlayers.contains(p)).forEach(allPlayers::add);
event.getTimeslots().stream().filter(t -> !allTimeslots.contains(t)).forEach(allTimeslots::add);
event.getLocalizations().stream().filter(l -> !allLocalizations.contains(l)).forEach(allLocalizations::add);
event.setTournament(this);
}
// ...
}
public Tournament(String name, Event... categories) {
this(name, new ArrayList<>(Arrays.asList(categories)));
}
The exception happens at the event.getTimeslots().stream().filter(t -> !allTimeslots.contains(t)).forEach(allTimeslots::add);
line, I have tried doing the same with a traditional foreach
instead of using streams, but the issue was exactly the same.
I honestly have no clue of why this is happening, since I am not modifying the list that's being iterated in any moment.
Edit. This is the other approach I tried, but I still get the same exception.
for (Event event : events) {
for (Player player : event.getPlayers())
if (!allPlayers.contains(player))
allPlayers.add(player);
for (Localization localization : event.getLocalizations())
if (!allLocalizations.contains(localization))
allLocalizations.add(localization);
for (Timeslot timeslot : event.getTimeslots())
if (!allTimeslots.contains(timeslot))
allTimeslots.add(timeslot);
event.setTournament(this);
}