Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Java Java Data Structures - Retired Efficiency! Changing Course

fixVideoTitle

What is wrong with my Code? I get a Runtime Exception: java.util.ConcurrentModificationException

com/example/model/Course.java
package com.example.model;

import java.util.List;

public class Course {
  private String mName;
  private List<Video> mVideos; 

  public Course(String name, List<Video> videos) {
    mName = name;
    mVideos = videos;
  }

  public String getName() {
    return mName;
  }

  public List<Video> getVideos() {
    return mVideos;
  }

}
com/example/model/Video.java
package com.example.model;

public class Video {
  private String mTitle;

  public Video(String title) {
    mTitle = title;
  }

  public String getTitle() {
    return mTitle;
  }

  public void setTitle(String title) {
    mTitle = title;
  }

}
QuickFix.java
import com.example.model.Course;
import com.example.model.Video;


import java.util.Map;
import java.util.HashMap;
import java.util.List;

public class QuickFix {

  public void addForgottenVideo(Course course) {
    // TODO(1):  Create a new video called "The Beginning Bits"
      Video video = new Video("The Beginning Bits");
    // TODO(2):  Add the newly created video to the course videos as the second video.
      course.getVideos().add(1,video);
  }

  public void fixVideoTitle(Course course, String oldTitle, String newTitle) {
    Video v = new Video(newTitle);
    Map<String, Video> m = new HashMap<>(videosByTitle(course));
    for (Map.Entry<String, Video> entry: m.entrySet()){
      if(entry.getKey().equals(oldTitle)){
        m.remove(entry.getKey(), entry.getValue());
      }
    }
    m.put(newTitle, v);
  }

  public Map<String, Video> videosByTitle(Course course) {
    Map<String, Video> m = new HashMap<>();
    for(Video v : course.getVideos()){
      m.put(v.getTitle(), v);
    }
    return m;
  }

}
Simon Coates
Simon Coates
28,694 Points

I had a quick look here. I think the problem is iterating over a collection and simultaneously altering it. The explanation for why this happens is pretty complex. However, fixVideoTitle is way more complex than it needs to be. You can just avoid the error.

3 Answers

Simon Coates
Simon Coates
28,694 Points

The following seems to work:

  public void fixVideoTitle(Course course, String oldTitle, String newTitle) {
    Map<String, Video> m = videosByTitle(course);
    Video vid = m.get(oldTitle);
    vid.setTitle(newTitle);
  }

Thanx Simon for quick explanation, your solution is way much cleaner... What I was trying to accomplish was to remove the Key and insert a new one; I also tried the replace() function version defined in HashMap as well but ended up with errors...

Just before finishing, I have one more question on your solution... I know get(Object k) function returns value related to that particular key, and you intend to change that value itself does that mean the next time we open videosByTitle and search via new Title it will find the video.. I know its a silly Question at this point, but just making sure

Simon Coates
Simon Coates
28,694 Points

videosByTitle rebuilds the map on the basis of the course, so the next time you call it, it should reflect the updated title, i think.

thanx

Deano k
PLUS
Deano k
Courses Plus Student 5,872 Points

You will have a problem incase the oldTitle is not found in the video by artist Map you created (m), the get method will return null.

You should use an if statement to check if the video is in the Map and only then set the new video title

if (m.containsKey(oldTitle)) { v.setTitle(newTitle); }