Can a groupingBy
operation on a stream produce a map where the values are arrays rather than lists or some other collection type?
For example: I have a class Thing
. Things have owners, so Thing
has a getOwnerId
method. In a stream of things I want to group the things by owner ID so that things with the same owner ID end up in an array together. In other words I want a map like the following where the keys are owner IDs and the values are arrays of things belonging to that owner.
Map<String, Thing[]> mapOfArrays;
In my case, since I need to pass the map values to a library method that requires an array, it would be most convenient to collect into a Map<String, Thing[]>
.
Collecting the whole stream into one array is easy (it doesn’t even require an explicit collector):
Thing[] arrayOfThings = Stream.of(new Thing("owner1"), new Thing("owner2"), new Thing("owner1"))
.toArray(Thing[]::new);
[Belongs to owner1, Belongs to owner2, Belongs to owner1]
Groping by owner ID is easy too. For example, to group into lists:
Map<String, List<Thing>> mapOfLists = Stream.of(new Thing("owner1"), new Thing("owner2"), new Thing("owner1"))
.collect(Collectors.groupingBy(Thing::getOwnerId));
{owner1=[Belongs to owner1, Belongs to owner1], owner2=[Belongs to owner2]}
Only this example gives me a map of lists. There are 2-arg and 3-arg groupingBy
methods that can give me a map of other collection types (like sets). I figured, if I can pass a collector that collects into an array (similar to the collection into an array in the first snippet above) to the two-arg Collectors.groupingBy(Function<? super T,? extends K>, Collector<? super T,A,D>)
, I’d be set. However, none of the predefined collectors in the Collectors
class seem to do anything with arrays. Am I missing a not too complicated way through?
For the sake of a complete example, here’s the class I’ve used in the above snippets:
public class Thing {
private String ownerId;
public Thing(String ownerId) {
this.ownerId = ownerId;
}
public String getOwnerId() {
return ownerId;
}
@Override
public String toString() {
return "Belongs to " + ownerId;
}
}