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

I don't fully understand the byArtist method() in the SongBook class. More details inside.

Hi,

this video is a bit overwhelming but I will give my best to get into it. What I don't understand is following. First the code:

private Map<String, List<Song>> byArtist() {

   Map<String, List<Song>> byArtist = new HashMap<>(); 
   for(Song song: mSongs) {

     List<Song> artistSongs = byArtist.get(song.getArtist());

     if(artistSongs == null) {

      List<Song> artistSongs = new ArrayList<>();
      byArtist.put(song.getArtist(), artistSongs);

     }
     artistSongs.add(song);

   }  
    return byArtist; 
  }

So here is how I think it's working:

First it creates a new empty map. Then we loop through every song in mSongs. We try to assign the Artist to a list but this doesn't exist yet so the value is null and the if statement runs:

It creates a new List of Type Song. Then we put in the Artist of the current song and the empty List. Then we add the current Song into the list. And here is my confusion. Why do we add the song to this list and not the song.getTitle() ?

Or if for example it comes to the 2nd loop so Song 2 and it's for example the same artist the song get's added to the list and then it goes to artistSongs.add(song). Why is it adding the whole song too?

Doesn't that mean on first run through we can't get the title of the first artist? Can anyone explain me this in great detail plz? I'm so overwhelmed right now.

is the list "attached" to the map? Because if we for example come to song3 in the loop and it's no title in the list yet it jumpes again to the if statement. here it creates the list again with the same name. Doesn't it override it every time?

Oh man plz help :D I was so good until now :P

2 Answers

oh! ok i think i got it.

The new keyword is used to create, of course, a new instance of an object, so when you say List<Song>artistSongs = new ArrayList<Song>(); you're creating a new and empty list. In this scenario, what you want is to store an already existing ArrayList instead of creating one from scratch, so we omit using new. In the case that we get a null result, we know we actually need to create a new List since there was not one previously there.

Remember: List<Song>artistSongs; on its own creates a variable of type List. A variable is nothing more than a means to store an instance of an object, be it a new instance: artistSongs = new ArrayList<>(); or an already existing one: artistSongs = someOtherListOfSongs;

if you were to do this: List<Song>artistSongs = new ArrayList<Song>(); artistSongs = byArtist.get(song.getArtist()); and there was already an instance of ArrayList returned by byArtist.get(...) method, no error would occur and the program would run as intended, but it's unnecessary since you'd end up with something like:

List<Song> artistSongs = new ArrayList<>(); artistSongs is now storing a new and empty list of type Song you're creating artistSongs = byArtist.get(song.getArtist()); you replace the newly created list on the previous line by whatever gets returned by byArtist.get(...) method.

So by doing this you'd just be creating an empty List and then dropping it!

So yes, the program will always execute the code inside of the if block at least once since there's no actual instance of list for you to store in artistSongs, you need to create a new one.

Ok nice explaination there! Thx now I got it. Thx so much!

I will now go on with the video I saw there are more complex things comming :P

Hello, Dominik!

i'm not entirely sure if i understand your question correctly but here goes.

Remember a map is a essentially a way of relating one Key to a specific value in this case you're relating the artist's name(String) to all of it's songs(a collection). An example of this would end up looking somewhat like: { "Elvis Prestley" => ["Can't help falling in love", "Always on my mind"] }

now, what would happen if you tried to access a list related to an artist you haven't added to your map? i.e byArtist.get("Michael Jackson")? you'd get a null value in return. Since you are getting back "nothing", you can't access the collection's add method, resulting in an exception if you try to do it. To prevent this from happening, you first need to check for the existence of the element you tried to access and then use its methods. If it doesn't exist yet, you simply instantiate a new collection on to the map that's related to the new artist's name and then add to it.

No it's not exactly what I meant. It's hard to describe.

Just the line: List<Song> artistSongs = byArtist.get(song.getArtist());

For example 1 thing I don't get. i thought we hat to actually make a List first with new ArrayList<Song>(); But here we somehow want to instantiate it with either a song if it has found the key (getAuthor) or Null when we don't found anything. Doesn't we have to create the List at first like so:

List<Song>artistSongs = new ArrayList<Song>(); artistSongs = byArtist.get(song.getArtist());

This is just the first thing I don't understand. If you would explain that too me this would be very nice :) I will point out the next thing which has not clicked yet if fully understand that line of code.

Thx

/edit: I thought of this problem now for over 2 hours and I made a progress. Now I think I'm almost getting it. But the question above is again still open. Does this mean when the program runs the first time the if block will always run at least once because of course we don't have an artist in the map yet? And so the statement can see that there is no artistSongs List bound to the key getArtist and therefore it creates a list automatically and sets it to null? But why is the program doing this? First time I saw that it creates a list automatically without new keywoad. I hope you understand what I mean.