Problem
I have a List of Request objects, where each request contains the origin host and the requested URL. I want to transform this into Map<String, Set<String>>, where the keys are the hosts and the values are the unique URLs that have been called by the host.
My own solution
I found that you could use Collectors.groupingBy to transform a List into a Map. This seemed like the method for the job, but it didn't fit my total needs. I had to create an extra function:
private static <T, K> Collector<T, ?, Set<K>> toSet(Function<? super T, ? extends K> mapper) {
return Collector.of(
HashSet::new,
(list, item) -> list.add(mapper.apply(item)),
(list1, list2) -> {
list1.addAll(list2);
return list1;
}
);
}
Using this function, I could do it like this:
Map<String, Set<String>> hostUrls = getRequests().stream()
.map(r -> new ImmutablePair<>(r.getOriginHost(), r.getRequestUrl()))
.collect(Collectors.groupingBy(ImmutablePair::getLeft, toSet(ImmutablePair::getRight)));
Question
Is there some way to do this transforming without creating this extra toSet function?
My wish doesn't seem that extreme. I want some extra kind of mapping before collecting everything into one Set (could also be any other kind of collection of course). I have the feeling that I am missing some function, but I cannot see which.