Collect results of a map operation in a Map using Collectors.toMap or groupingBy

You can use the toMap collector with a bounded method reference to get what you need. Also notice that this solution assumes you don't have repeated A instances in your source container. If that precondition holds this solution would give you the desired result. Here's how it looks.

Map<A, Collection<B>> resultMap =
    .collect(Collectors.toMap(Function.identity(), repo::getListofB);

If you have duplicate A elements, then you have to use this merge function in addition to what is given above. The merge function deals with key conflicts if any.

Map<A, Collection<B>> resultMap =
       .collect(Collectors.toMap(Function.identity(), repo::getListofB, 
            (a, b) -> {
                return a;

And here's a much more succinct Java9 approach which uses the flatMapping collector to handle repeated A elements.

Map<A, List<B>> aToBmap =
                Collectors.flatMapping(a -> getListofB(a).stream(), 

It would be straight forward,, a -> getListofB(a)));

In this answer, I'm showing what happens if you have repeated A elements in your List<A> listofA list.

Actually, if there were duplicates in listofA, the following code would throw an IllegalStateException:

Map<A, Collection<B>> resultMap =

The exception might be thrown because Collectors.toMap doesn't know how to merge values when there is a collision in the keys (i.e. when the key mapper function returns duplicates, as it would be the case for Function.identity() if there were repeated elements in the listofA list).

This is clearly stated in the docs:

If the mapped keys contains duplicates (according to Object.equals(Object)), an IllegalStateException is thrown when the collection operation is performed. If the mapped keys may have duplicates, use toMap(Function, Function, BinaryOperator) instead.

The docs also give us the solution: in case there are repeated elements, we need to provide a way to merge values. Here's one such way:

Map<A, Collection<B>> resultMap =
                            a -> new ArrayList<>(repo.getListofB(a)),
                            (left, right) -> {
                                return left;

This uses the overloaded version of Collectors.toMap that accepts a merge function as its third argument. Within the merge function, Collection.addAll is being used to add the B elements of each repeated A element into a unqiue list for each A.

In the value mapper function, a new ArrayList is created, so that the original List<B> of each A is not mutated. Also, as we're creating an Arraylist, we know in advance that it can be mutated (i.e. we can add elements to it later, in case there are duplicates in listofA).