javajava-8reducinggroupingby

How do I use Java 8 groupingBy to collect into a list of a different type?


I'm trying to take a map of type A -> A, and group it into a map of A to List<A>. (Also reversing the key-value relationship, but I don't think that is necessarily relevant).

This is what I have now:

private static Map<Thing, List<Thing>> consolidateMap(Map<Thing, Thing> releasedToDraft) {

    // Map each draft Thing back to the list of released Things (embedded in entries)
    Map<Thing, List<Map.Entry<Thing, Thing>>> draftToEntry = releasedToDraft.entrySet().stream()
            .collect(groupingBy(
                    Map.Entry::getValue,
                    toList()
            ));

    // Get us back to the map we want (Thing to list of Things)
    return draftToEntry.entrySet().stream()
            .collect(toMap(
                    Map.Entry::getKey,
                    ThingReleaseUtil::entriesToThings
            ));
}

private static List<Thing> entriesToThings(Map.Entry<Thing, List<Map.Entry<Thing, Thing>>> entry) {
    return entry.getValue().stream()
            .map(Map.Entry::getKey)
            .collect(toList());
}

I'd like to do this in a single statement, and I feel like it must be possible to transform the Map<Thing, List<Map.Entry<Thing, Thing>>> to Map<Thing, List<Thing>> as part of the groupingBy operation.

I've tried using reducing(), custom collectors, everything I can find; but I'm stymied by the lack of complex examples out there, and the fact that the few similar ones I can find have List.of(), which doesn't exist in Java 8 (Collections.singletonList() does not appear to be a good replacement).

Could someone help me with what is probably the obvious?


Solution

  • Must be on the line of

    private static Map<Thing, List<Thing>> consolidateMap(Map<Thing, Thing> releasedToDraft) {
            return releasedToDraft.entrySet().stream()
                    .collect(groupingBy(
                            Map.Entry::getValue,
                            mapping(Map.Entry::getKey, toList())
                    ));
        }