criztovyl
criztovyl

Reputation: 819

A ConcurrentModificationException thrown without a modification

I have the following Java Code:

HashMap<Integer, Lesson> overflow = new HashMap<Integer, Lesson>();
HashMap<Integer, Lesson> new_lessons = this.lessons;
HashMap<Integer, Lesson> lessons = this.lessons;
for (Integer lesson : lessons.keySet()) {
    if(lessons.get(lesson).getLength().equals(LessonLength.DOUBLE)){
        if(lessons.containsKey(lesson + 1)){
            overflow.put(lesson + 1, lessons.get(lesson + 1));
            new_lessons.put(lesson+1, lessons.get(lesson));
            new_lessons.get(lesson).setLength(LessonLength.ONCE);
            new_lessons.get(lesson+1).setLength(LessonLength.ONCE);
        }
        else{
            new_lessons.put(lesson+1, lessons.get(lesson));
            new_lessons.get(lesson).setLength(LessonLength.ONCE);
            new_lessons.get(lesson+1).setLength(LessonLength.ONCE);
        }
    }
}

Why is there thrown an ConcurrentModificationException?

Upvotes: 0

Views: 96

Answers (3)

Luca Basso Ricci
Luca Basso Ricci

Reputation: 18423

Because new_lessons.put(lesson+1, lessons.get(lesson)); modify lessons' keySet() which is the keySet() you are iterate over.

HashMap<Integer, Lesson> new_lessons = this.lessons;
HashMap<Integer, Lesson> lessons = this.lessons;

doesn't create new HashMap<> objects, but simple let new_lessons and lessons pointing to this.lessons

Upvotes: 1

William Morrison
William Morrison

Reputation: 11006

new_lessons and lessons represent the same hashmap. You are altering new_lessons while iterating over lessons. Therefore you have a ConcurrentModificationException.

To fix this, try creating a copy of this.lessons.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1504172

Your new_lessons and lessons variable have the same value - they're referring to the same object. So anything like this:

new_lessons.put(lesson+1, lessons.get(lesson));

... is modifying lessons, which you're iterating over (via its key-set). Hence the problem.

It's possible that if you didn't change the key set (i.e. you only changed the value associated with any entry) then you could be okay, but that's clearly not the case, because if lessons doesn't contain a key for lesson + 1, you're adding it.

It sounds like you should probably copy the original map for new_lessons, so that you've got two independent maps. Or more simply, just take a copy of the keys to start with:

List<Integer> keys = new ArrayList<Integer>(lessons.keySet());
for (Integer lesson : keys) {
    ...
}

... and get rid of your new_lessons variable as it's basically pointless.

Upvotes: 3

Related Questions