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 Efficiency! Changing Course

Rob Bridges
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Bummer, are you sure you updated the videos title?

Hello, need to be pointed in the right direction with this one.

I first tried to iterate over the Map.Entry's and edit them there, I learned the hard way there is Concurrentmodificationexception this way.

So I tried to use just an if statment to see if the new map has the key, and to put in the update and remove the old key. However now it's telling me that it was never updated.

Any help on this would be appreciated.

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.List;
import java.util.TreeMap;

public class QuickFix {
  List<Video> videoList;
  Map<String, Video> videoMap;

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

  public void fixVideoTitle(Course course, String oldTitle, String newTitle) {
    Map<String, Video> newVideoMap = videosByTitle(course);
    if (newVideoMap.containsKey(oldTitle)) {
      newVideoMap.put(newTitle, newVideoMap.get(oldTitle));
      newVideoMap.remove(oldTitle);
    }
    newVideoMap.put(newTitle, newVideoMap.get(oldTitle));
  }
  public Map<String, Video> videosByTitle(Course course) {

    videoList = course.getVideos();
    Map<String, Video> videoMap = new TreeMap<>();
    for (Video video : videoList) {
      videoMap.put(video.getTitle(), videoList.get(1));
    }
    return videoMap;
  }
}
Rob Bridges
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Thanks Craig and James,

It's probably the easiest part of this challenge that I'm still stuck on, so I'm gonna give a break and come back to this in a bit, I tried

newTitle = newVideoMap.get(oldTitle).setTitle(newTitle); as a long shot, and that didn't do me any good.

I appreciate the help, I'll come back and work on this some more.

I will add one more suggestion/comment. Sometimes having code already written can make you lose sight of what you need to do like I did when first trying to help. Sometimes its easier to start over without what you've worked on.

Rob Bridges
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Thanks,

I took your advice and gutted the method code besides incorporating the videosByTitle

it gave me a new error that I was pretty happy to see,

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

How do I ensure that this removes the old title in setting the new Title, the error message was that both results were still there, even after doing.

newVideoMap.remove(oldTitle);

Thanks!

12 Answers

Craig Dennis
STAFF
Craig Dennis
Treehouse Teacher

Oh ha! Check this out! It's your videosByTitle method:

videoMap.put(video.getTitle(), videoList.get(1));

You are adding every videos title for the key and then placing the 2nd video for every single value. The value there should just be video.

Your final code is correct, you don't need to set the newTitle variable again.

Sorry for not catching your mistake in step 2 better. :( I'll see what I can do.

Rob Bridges
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Okay wait, now I'm confused I got the method for converting it properly to title, but how do I fix the videosByTitle method to let it go through?

Craig Dennis
Craig Dennis
Treehouse Teacher

The key is video.getTitle and the value is just video.

Craig Dennis
Craig Dennis
Treehouse Teacher

Congrats on completing the course Rob! Sorry for the rough last one ;)

Rob Bridges
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Oh man, that worked. I finally got that method to work at 3 am last night, and never looked back it once it worked. but you're right. This did fix It, I was really starting to hit my head on the desk against this one.

Thank you Craig and James

Glad you were able to get it in the end.

Craig Dennis
STAFF
Craig Dennis
Treehouse Teacher

Every Video object has a setTitle method. Pull the video out of the map using oldTitle and then set the title.

Hope it helps!

Edane Barton
Edane Barton
11,457 Points

But I thought you will be pulling the value out rather than the key (oldTitle) by using the 'get' method on it ?

https://docs.oracle.com/javase/7/docs/api/java/util/Map.html

"get(Object key) Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key."

My line of thought was to get the value out of the map and replace the map with the newTItle and old value.

 if(videoTitlesMap.containsKey(oldTitle)){
      // The Title is there, lets get the value
            Video videoValue = videoTitlesMap.get(oldTitle);
            //Use the value to set the new title
            //videoValue.setTitle(newTitle);
          videoTitlesMap.put(newTitle,videoValue);


    }

But if I do it this way, I would negate the fact of using setTitle. Is there the above correct and challenge is expecting us to use the setTitle and thus giving us an error? Or am I wrong in my line of thoughts?

Craig Dennis
Craig Dennis
Treehouse Teacher

Remember Edane Barton they are just object references. You don't need to put it back in the map. Just change the title, the one in the map points to the same place!

J.D. Sandifer
J.D. Sandifer
18,813 Points

Hey all, thanks to everyone here for the inspiration I needed to finish this challenge.

I thought I would post a little general, big-picture advice about the main thing that kept me confused for most of this challenge:

All Java Objects are accessed by references.

Here's an example:

Object obj = new Object();   // Creates a new object and then references it with "obj".
Object other = obj;   // How many objects are there now? Still 1. It's just referenced by two names now - "obj" and "other".

Object another = new Object();   //Now we have a new object referenced by "another" for a total of 2 objects.

I'm sure that was in a video somewhere, but I either missed it, forgot it, or never really understood the implications...

This means when Course.getVideos() returns a list of videos in that course, you don't have an identical list of videos - a copy of the list - you have an actual reference to the same list of videos. Anything you do to that changes the list in the Course object. (For a while I thought we were just creating a copy of the list and then not doing anything with it...)

This is the same for the other functions. The Map used in videosByTitle() should be created in that function so that there's a new map for each course passed in to the function. (At one point I was creating it in the class in the declaration of the variable at the top...)

Finally, this means that when you find the video in the Map, you have a reference to the actual video. Use the setTitle() method to change it's title.

I know Craig has been saying essentially the same thing in several comments above, but I thought I'd take a minute to expound a little. Sometimes the language we use - like pull the video out of the map, add the video to the list, etc. is confusing. It's really about getting and putting references to the objects from maps and into lists, etc.

Craig Dennis
Craig Dennis
Treehouse Teacher

Awesome post J.D!

Would you mind making this a post of its own, so it doesn't get lost? Object references was exactly what I was trying to nail down in this challenge. Awesome explanation!

Thanks!

Hey J.D. , anyone can correct me if I am wrong but in order for an object to not be a reference and actually be a new object is by using the "new" keyword. Using the new Keyword will always create an object.

Edane Barton
Edane Barton
11,457 Points

This is what I got for part 2 and 3 of the challenge. Rob your answer helped pointed me in the right direction

public void fixVideoTitle(Course course, String oldTitle, String newTitle) {
     //get all video map
     Map<String, Video> videoTitlesMap = new HashMap<String, Video>();
    //Get the titles for the video to place in videoTitleMap

    videoTitlesMap = videosByTitle(course);
    //Determine if the 'Old Title' is there in the first place
    if(videoTitlesMap.containsKey(oldTitle)){
      // The Title is there, lets get the value
            Video videoValue = videoTitlesMap.get(oldTitle);
            //Use the value to set the new title
            videoValue.setTitle(newTitle);


    }else{
     System.out.println("Title you want to change is not one of the available titles"); 
    }
    // method to use to add String new Title
    //put

  }

  public Map<String, Video> videosByTitle(Course course) {
   //use the counter for each time it pass through the for loop
    int count =0;
    //Create a new Map variable and have it sort in order by using TreeMap
    Map<String, Video> videoTitleMap = new TreeMap<String, Video>();
    //Get the titles for the video to place in videoTitleMap
    videoList=course.getVideos();
    //Need to assign the list of videos to videoTitleMap
    for ( Video video : videoList){
      //Where is the key going to be placed->counter
       videoTitleMap.put(video.getTitle(), videoList.get(count));
      count++;
    }


    return videoTitleMap;
  }

I tried this thing but it is still giving me an compioler error saying the course is already defined "public Map videosByTitle(Course course) {".

Hello,

You're so close to completing this challenge. You just need to change the title in the Video object that's contained in the map as well.

Rob Bridges
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Hey Thanks.. I think that more or less gave me better understand, I tried to change the code to

public void fixVideoTitle(Course course, String oldTitle, String newTitle) {
    Map<String, Video> newVideoMap = videosByTitle(course);
    Video video = newVideoMap.get(oldTitle);
    if (newVideoMap.containsKey(oldTitle)) {
      newVideoMap.put(newTitle, video.setTitle(newTitle));
      newVideoMap.remove(oldTitle);
    }

But it's still not working, any further advice on this?

Sorry to pester, was up too late trying to sort this out, definitely appreciate the help.

Craig Dennis
Craig Dennis
Treehouse Teacher

Don't worry about setting the map, they are object references. Just set the title and you are done!

Hi Rob,

I have no idea (really) what Craig was trying to tell you,

but I have a "feeling" you just have too much code for 'fixVideoTitle'..


I tried just part of your code:

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

..and it gave me no errors

It just complained:

Bummer! Are you sure you updated the video's title?

It did not say something like:

Are you sure you are setting the videosByTitle map

(which is good)

.

So I thinking the mapping part and the getting of the old title part is right (syntax error free)

and it's only these lines that needs something else (some other code):

      newVideoMap.put(newTitle, video.setTitle(newTitle));
      newVideoMap.remove(oldTitle);

I tired just adding just the first line to my error free code snippet above

but it was giving me an error:

Bummer! There is a compiler error.

Please click on preview to view your syntax errors!

..with the Preview output.html saying this:

./QuickFix.java:23: error: 'void' type not allowed here newVideoMap.put(newTitle, video.setTitle(newTitle)); ^ 1 error

(with the error caret on the parenthesis between 'video.setTitle' and 'newTitle')


Don't know really (I'm just guessing) --but the setting of the newTitle doesn't seem to be going right..

-- isn't there some way to put the newTitle IN PLACE OF the oldTitle (maybe in a single line of code...without having to use an 'IF')?

It seems like all that is all that is really needed to make the Code Challenge engine happy --just to set the newTitle somehow (as simply as possible).

Oh..and here's the quickie link to the Changing Courses Challenge (the last one for the Java Data Structures course):

http://teamtreehouse.com/library/java-data-structures/efficiency/changing-course

Note: I find sometimes it helps get (encourage) forum thread posts/responses if you actually include the challenge link..

faraz
faraz
Courses Plus Student 21,474 Points

James White,

For your future reference, whenever there is a question asked via the "Get Help" button on a challenge, such as this one, there is a green "View Challenge" button on the top right hand corner of the question that you can click on it to go back to the challenge. Hope that helps you! :)

Hi Rob,

Sorry you missed by my 'edit1' addendum in the cross-posting..

.

But you figured out how to pass part 3 of the challenge!

You are the man, Rob!

Woo-hoo!

Congrats! :thumbsup:


Hopefully Craig will be updating the checking for part 2 to be more strict...

...and hopefully maybe also have a code hint in case someone tries to use something like 'videoList.get(1)'

Craig (quote):

Sorry for not catching your mistake in step 2 better. :( I'll see what I can do.

Craig Dennis
Craig Dennis
Treehouse Teacher

Okay it's fixed now, step 2 will no longer pass with a bad mapping. Thanks for catching that!

I tried everything in the forum but I am still getting the same error

Craig Dennis
Craig Dennis
Treehouse Teacher

Hey Roshan Kashif !

Can you add a new post with your code please?

Rob Bridges
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Hey Roshan, this is the same error I made try to change your line to

videoMap.put(video.getTitle(), video) 

The above code was me trying to figure this out at 2 am.

Thanks Rob, but it's now giving me a compiler error on video

Tim Strand
Tim Strand
22,458 Points

why do i have to define videoList twice? it kept giving me invalid symbol until i defined videoList again beneath videosByTitle like you have in your example. Once i added that it let me complete. i also dont understand why we need a count and we are putting every video in there since we are initializing the count then why bother incrementing it? shouldnt there be an if that says if it doesnt already exist then add the video to the list?

  public void addForgottenVideo(Course course) {
    List<Video> videoList = course.getVideos();
    Video video = new Video("The beginning bits");
    videoList.add(1, video);
  }



  public void fixVideoTitle(Course course, String oldTitle, String newTitle) {

  }

  public Map<String, Video> videosByTitle(Course course) {
    int count =0;
    Map<String, Video> videoTitleMap = new TreeMap<String, Video>();
    List<Video> videoList = course.getVideos();
    for (Video video : videoList) {
     videoTitleMap.put(video.getTitle(), videoList.get(count));
      count++;
   } 
return videoTitleMap;
Craig Dennis
Craig Dennis
Treehouse Teacher

This should work fine...remember they are object references.

videoTitleMap.put(video.getTitle(), video);

videoList is an instance variable and is only in the method's scope.

You actually don't need it in videosByTitle you could just do this:

for (Video video : course.getVideos()) {

That make more sense?

Tim Strand
Tim Strand
22,458 Points

ok, but i still feel like i am missing the core concept of part 2 of the challenge. 1) i dont understand why i need the count piece. shouldnt it be more of a check if its there if not add otherwise skip? 2) i understand what you are saying with replacing it. by why if i already defined it in addForgottenVideo cant i use videoList again without redefining it in videsByTitle? that is a concept i struggle with because i defined it in a public class so i thought i could access it as long as i was in that same file?

Thanks for such a prompt reply.

Craig Dennis
Craig Dennis
Treehouse Teacher

You don't need the count piece. Just loop the videos, for each video set the title for the key and the video for the value. You are riffing on code you don't need, don't let it confuse you ;)

Secondly...so, see how it is defined in the method, you can tell because the Type is specified there, that makes it a local variable, it is not a field on the class. These methods we are working on here are made to work with many different Course objects, see how the course is passed in. If you did indeed make a class field that stored the videoList as an instance variable it would be wrong for each different course that was passed into the method.

So the local variable is created so you can use it. Like I said though, in my last comment, you actually don't need it.

Tim Strand
Tim Strand
22,458 Points

ok i understand what you mean about it being a local variable. It makes sense that if its defined beneath a piece like that then its only in use for that section. I have to set it as a member variable to make it available for all my sections.

now my struggle is a compiler error when i try to reference the videosByTitle map from task 2: java:17: error: cannot find symbol if (videosByTitle.containsKey(oldTitle)) {

My logic is using the previously built map i should be able to check for the oldTitle, add the newTitle (key) with the oldTitle's (value) then remove the old title.

 public void fixVideoTitle(Course course, String oldTitle, String newTitle) {
      if (videosByTitle.containsKey(oldTitle)) {
          videosByTitle.put(newTitle, videosByTitle.get(oldTitle));
            videosByTitle.remove(oldTitle);
  }

Thanks so much for your help, the videos are great but sometimes i feel like i am just typing what you type without getting comprehension so its nice to have the challenges test my comprehension and its nice to have the forums to help me grasp the concepts which i failed to grasp.

Tim Strand
Tim Strand
22,458 Points

Craig thanks for the help i was able to get challenge 3. I figured instead of calling videosByTitle i could just make that tree map a protected variable for the class. So i moved it up and got rid of the compiler error. 1) I tried to do the same with the videoList variable that we discussed previously in the post but it created a compiler error on not recognizing the symbol so i punted on that one. 2) i dont understand why its cleaner to use the setTitle method instead of just saying this? java videosByTitle.put(newTitle, videosByTitle.get(oldTitle));

Below is my end code result as clean as i could get it, but get it i did, thanks for the help really appreciate it.

import com.example.model.Course;
import com.example.model.Video;

import java.util.Map;
import java.util.List;
import java.util.TreeMap;

public class QuickFix {
  protected Map<String, Video> videoTitleMap = new TreeMap<String, Video>();

    public void addForgottenVideo(Course course) {
   List<Video> videoList = course.getVideos();
    Video video = new Video("The beginning bits");
    videoList.add(1, video);
  } 
  public void fixVideoTitle(Course course, String oldTitle, String newTitle) {
      if (videoTitleMap.containsKey(oldTitle)) {
          Video video = videoTitleMap.get(oldTitle);
            video.setTitle(newTitle);
        videoTitleMap.remove(oldTitle);
    }
  }
  public Map<String, Video> videosByTitle(Course course) {
    //Map<String, Video> videoTitleMap = new TreeMap<String, Video>();
    List<Video> videoList = course.getVideos();
    for (Video video : videoList) {
     videoTitleMap.put(video.getTitle(), video);
       } 
return videoTitleMap;
  }
}

Craig,

Here is the code (excerpted from Rob's first set of code posted above) that I used to pass part 2 of 3 for the challenge,

(are you saying it shouldn't have passed because of that one line in public Map?)

import com.example.model.Course;
import com.example.model.Video;

import java.util.Map;
import java.util.List;
import java.util.TreeMap;

public class QuickFix {
  List<Video> videoList;
  Map<String, Video> videoMap;

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

  public void fixVideoTitle(Course course, String oldTitle, String newTitle) {

  }

  public Map<String, Video> videosByTitle(Course course) {

    videoList = course.getVideos();
    Map<String, Video> videoMap = new TreeMap<>();
    for (Video video : videoList) {
      videoMap.put(video.getTitle(), videoList.get(1));
    }
    return videoMap;
  }

}
Craig Dennis
Craig Dennis
Treehouse Teacher

Yeah the map is being built is wrong. It's all the videos titles pointing to a single video, instead of the actual video. Right? videoList.get(1) will insert the 2nd video in the list for each video title. He just wants video there for the value.

Hi Craig,

Now I'm confused..

I tried replacing this line:

      videoMap.put(video.getTitle(), videoList.get(1));

..with either of these two lines:

      videoMap.put(video.getTitle, video);
      videoMap.put(video, video.getTitle);

..and neither of them passes part 2 of 3 for the challenge.

Edit1:

Oh wait..this line passes:

videoMap.put(video.getTitle(), video);

Now the code Rob gave earlier will pass 3 of 3:

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

Thanks for your help Craig!

import com.example.model.Course; import com.example.model.Video; import java.util.HashMap; import java.util.Set; import java.util.Map; import java.util.List; import java.util.TreeMap;

public class QuickFix { List<Video> videoList; Map<String, Video> videoMap;

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

}

public void fixVideoTitle(Course course, String oldTitle, String newTitle) { Map<String, Video> newVideoMap = videosByTitle(course); Video video = newVideoMap.get(oldTitle); video.setTitle(newTitle); videoMap.put(video.getTitle(), video); }

public Map<String, Video> videosByTitle(Course course) {

videoList = course.getVideos();
Map<String, Video> videoMap = new TreeMap<>();
for (Video video : videoList) {
  videoMap.put(video.getTitle(), videoList.get(1));
}
return videoMap;

}

} This is my code ......It is giving me an error saying bummer key Array point to video with the title beginning bits. It should be a map of the title with the same title.