0

Firstly, I'm not very good at this java lark, so bear with me...

I have a map where the keys are Strings representing the title of a film and the values are Sets of actors, represented by objects of class Actor which each have their own attributes.

What I want to do is iterate over the map, returning the film title and the actors in a meaningful way.

I've got the map iteration part but I can't figure out how to do the next loop which produces the values from the Set of Actors.

Here's what I have:

Map <String, Set> filmCollection = new HashMap<>();
Actor a1 = new Actor("Joe Smith", "20071977");
Actor a2 = new Actor("Kate Jones", "01011980");
Actor a3 = new Actor("Frank DeFrank", "02021945");
Set <Actor> s1 = new HashSet<>();
Set <Actor> s2 = new HashSet<>();
s1.add(a1);
s1.add(a2);
s2.add(a3);
s2.add(a1);
filmCollection.put("The Best Film", s1);
filmCollection.put("The Nearly Best Film", s2);

Set<String> collectionKeys = filmCollection.keySet();
for (String eachFilm : collectionKeys)
{
    System.out.println(eachFilm + " stars the actors ");
}

I know this is basic stuff and is probably very simple, but i'm learning and I've been searching and trying things all day - my head feels like it might explode soon! Any guidance would be appreciated.

Stiltinho
  • 3
  • 1

5 Answers5

1

So what you did is looping over the set of keys of the map. Since you have the keys, now you need to get the value of each key stored in the map. To do so, you have to call filmCollection.get(eachFilm).

Full code

Map <String, Set<Actor>> filmCollection = new HashMap<String, Set<Actor>>();
Actor a1 = new Actor("Joe Smith", "20071977");
Actor a2 = new Actor("Kate Jones", "01011980");
Actor a3 = new Actor("Frank DeFrank", "02021945");
Set <Actor> s1 = new HashSet<>();
Set <Actor> s2 = new HashSet<>();
s1.add(a1);
s1.add(a2);
s2.add(a3);
s2.add(a1);
filmCollection.put("The Best Film", s1);
filmCollection.put("The Nearly Best Film", s2);

Set<String> collectionKeys = filmCollection.keySet();
for (String eachFilm : collectionKeys)
{
    System.out.println(eachFilm + " stars the actors ");
    for (Actor actor : filmCollection.get(eachFilm)) {
        System.out.println(actor + ", ");
    }
}
Bilal EL CHAMI
  • 414
  • 1
  • 3
  • 14
0

If I understand you properly, you just lack a loop: the first one loops over the films, and you should have another one for their actors. Use entrySet instead of keySet if you need both key and value at the same time. I tweaked your code a little bit to show you what I mean:

    Map <String, Set<Actor>> filmCollection = new HashMap<>();
    Actor a1 = new Actor("Joe Smith", "20071977");
    Actor a2 = new Actor("Kate Jones", "01011980");
    Actor a3 = new Actor("Frank DeFrank", "02021945");
    Set <Actor> s1 = new HashSet<>();
    Set <Actor> s2 = new HashSet<>();
    s1.add(a1);
    s1.add(a2);
    s2.add(a3);
    s2.add(a1);
    filmCollection.put("The Best Film", s1);
    filmCollection.put("The Nearly Best Film", s2);

    for (Entry<String, Set<Actor>> eachFilm : filmCollection.entrySet()) {
        // The key -> a movie
        System.out.println(eachFilm.getKey() + " stars the actors "); 

        // The value -> the actors
        for (Actor actor : eachFilm.getValue()) {
         System.out.println(actor);
        }
    }
HBo
  • 635
  • 6
  • 16
0

Your problem is that the key set does not contain any information about the actors. The key set just contains the keys.

You can loop over the map entries which are key -> value pairs. Once you have the set of actors, you can concatenate their names with String.join

for (Map.Entry<String, Set<Actor>> film : filmCollection.entrySet())
{
    // get all the names for this film (I would usually use streams for this, but 
    // they're a bit more advanced)
    Set<String> actorsNames = new HashSet<>();
    for (Actor actor : film.getValue())
    {
        actorsNames.add(actor.getName());
    }

    // concatenate the names with String.join
    System.out.println(
        film.getKey() + " stars the actors " + String.join(", ", actorsNames)
    );
}

You will also need to change the definition of your map to:

Map<String, Set<Actor>> filmCollection = new HashMap<>();

because this states that the set is a set of actors. Without this, it's just a set of objects.


Little bonus for how I'd do this with streams:

filmCollection.entrySet().stream()
    .map(film -> film.getKey() + " stars the actors "
        + film.getValue().stream().map(Actor::getName).collect(Collectors.joining(", "))
    )
    .forEach(System.out::println);
Michael
  • 41,989
  • 11
  • 82
  • 128
  • Thank you for your reply. I'm getting a cannot find symbol error with the String.join but I'll have a play around and see what I can come up with :) – Stiltinho Apr 30 '18 at 15:17
  • @Stiltinho It's only in Java 8 and up. There's [a few other alternatives](https://stackoverflow.com/questions/1751844/java-convert-liststring-to-a-string). – Michael Apr 30 '18 at 15:43
  • Thanks for that. I've just started reading about streaming too, so thanks for the little extra :) – Stiltinho May 01 '18 at 10:43
0

Since you are using both the film and actors then just iterate over the entries of your film-to-actors map, since the entries contains both the key and the value. Then, for each entry, print the name of the film (entry.getKey()) and get the set of actors (entry.getValue()) and print each one.

Map <String, Set<String>> filmCollection = new HashMap<>();
// ...
for (Map.Entry<String, Set<String>> entry : filmCollection.entrySet()){
    System.out.println(entry.key() + " stars the actors " + entry.value());
    // or
    for(String actor : entry.value()){
        System.out.println(actor);
    }
}
xtratic
  • 4,600
  • 2
  • 14
  • 32
0

There you go: Your filmCollection should be a Map<String, Set<Actor>>

Map<String, Set<Actor>> filmCollection = new HashMap<>();
Actor a1 = new Actor("Joe Smith", "20071977");
Actor a2 = new Actor("Kate Jones", "01011980");
Actor a3 = new Actor("Frank DeFrank", "02021945");
Set<Actor> s1 = new HashSet<>();
Set<Actor> s2 = new HashSet<>();
s1.add(a1);
s1.add(a2);
s2.add(a3);
s2.add(a1);
filmCollection.put("The Best Film", s1);
filmCollection.put("The Nearly Best Film", s2);

Set<String> collectionKeys = filmCollection.keySet();
for (String eachFilm : collectionKeys) {
    System.out.print(eachFilm + " stars the actors : ");
    for (Actor actor : filmCollection.get(eachFilm)) {
        System.out.print(" [ " + actor.name + " ] ");
    }
    System.out.println();

Sample output:

The Best Film stars the actors :  [ Kate Jones ]  [ Joe Smith ] 
The Nearly Best Film stars the actors :  [ Frank DeFrank ]  [ Joe Smith ] 
Shanu Gupta
  • 3,699
  • 2
  • 19
  • 29
  • Thank you very much for taking the time to reply. This kind of thing is exactly what I've been trying all day, I just couldn't get it right. Thank you :) – Stiltinho Apr 30 '18 at 15:25