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?

1
  • Yes. Have edited the question. Commented Mar 14, 2017 at 14:10

3 Answers 3

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;
}
Sign up to request clarification or add additional context in comments.

3 Comments

I was trying to avoid the second stream. Is it possible?
And the map function can also be replaced with toMap(a -> a.id, identity())
And you can't use toMap in the second collect method, guess toMap is assuming that there are no duplicate keys, and in this case, there could be same activityType for different activities.
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())))));

5 Comments

Yeah. This would be perfect, but have to live with Java8 :/
@AswinAlagappan can you bring an additional library like StreamEx for example? You might need it for a lot more then just this example...
@Aswin Alagappan: You don’t have to wait for Java 9 to use flatMapping. At the end of this answer 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…
@Eugene: I will try using it. But Java 8 streams itself seems to be slow, is that the same with StreamEx?
@Holger: Cool !!
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())))));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.