2

I have

class Activity {
    int id;
    ActivityType activityType;
}
class ActivityType {
    int id;
}
class Tournament {
    int id;
    List<Activity> activities;
}

I have a

List<Tournament> tournaments;

And from that I need

Map<Tournament, Map<ActivityType, Map<Integer, Activity>>>

(where the Integer is the activityId)

How do I get that using Java 8?

khelwood
  • 55,782
  • 14
  • 81
  • 108
Aswin Alagappan
  • 173
  • 1
  • 1
  • 11

3 Answers3

1

If I understand correctly, the Map<Integer, Activity> always contains only one element. In which case it looks more like a toMap than a groupingBy. Something like:

Map<Tournament, Map<Activity, Map<Integer, Activity>>> map = tournaments.stream()
               .collect(toMap(t -> t,
                     t -> t.getActivities().stream().collect(toMap(a -> a, a -> map(a)))));

Using this helper method:

private static Map<Integer, Activity> map(Activity a) {
  Map<Integer, Activity> m = new HashMap<> ();
  m.put(a.getId(), a);
  return m;
}
assylias
  • 321,522
  • 82
  • 660
  • 783
1

If you have a way to get the Collectors.flatMapping from jdk-9 (I think it is present in StreamEx library), then it could look like this:

Stream.of(new Tournament()).collect(Collectors.groupingBy(Function.identity(),
            Collectors.flatMapping(t -> t.getActivities().stream(), 
                    Collectors.groupingBy(Activity::getActivityType,
                          Collectors.toMap(Activity::getId, Function.identity()))
                    )));

With StreamEx it could look like this:

 Stream.of(new Tournament()).collect(Collectors.groupingBy(Function.identity(),
            MoreCollectors.flatMapping(t -> t.getActivities().stream(),
                    Collectors.groupingBy(Activity::getActivityType,
                            Collectors.toMap(Activity::getId, Function.identity())))));
Eugene
  • 117,005
  • 15
  • 201
  • 306
  • Yeah. This would be perfect, but have to live with Java8 :/ – Aswin Alagappan Mar 14 '17 at 14:40
  • 1
    @AswinAlagappan can you bring an additional library like `StreamEx` for example? You might need it for a lot more then just this example... – Eugene Mar 14 '17 at 14:48
  • 3
    @Aswin Alagappan: You don’t have to wait for Java 9 to use `flatMapping`. At the end of [this answer](http://stackoverflow.com/a/39131049/2711488) is a Java 8 compatible implementation of the `flatMapping` collector which you can copy to your code base, as it’s quiet small. And it’s so straight-forward, that it turned out to be identical to Java 9’s implementation… – Holger Mar 14 '17 at 16:18
  • @Eugene: I will try using it. But Java 8 streams itself seems to be slow, is that the same with StreamEx? – Aswin Alagappan Mar 14 '17 at 17:19
  • @Holger: Cool !! – Aswin Alagappan Mar 14 '17 at 17:23
0

This was the best I was able to come up with java8.

Map<Tournament, Map<Activity, Map<Integer, Activity>>> map = tournaments.stream()
           .collect(toMap(identity(),
                          t -> t.getActivities().stream()
                               .collect(groupingBy(A::getActivityType(), 
                                        a -> toMap(A::getId, identity())))));
Aswin Alagappan
  • 173
  • 1
  • 1
  • 11