Java8 counting collector with additional information

Viewed 872

I'm using counting collector of java 8 to get information about the count of values.

For ex; If I have bunch of streams like

Stream<String> doc1 = Stream.of("a", "b", "c", "b", "c");
Stream<String> doc2 = Stream.of("b", "c", "d");
Stream<Stream<String>> docs = Stream.of(doc1, doc2);

I am able to count the occurrences of each word in a doc by doing

List<Map<String, Long>> collect = docs
    .map(doc -> doc.collect(Collectors.groupingBy(Function.identity(), Collectors.counting())))
    .collect(Collectors.toList());

This results in a structure as

[
{a=1, b=2, c=2}, 
{b=1, c=1, d=1}
]

However, I would like to have the count be associated with the docId from which it originated from. For example I would like to have a structure as

[
{a=(randId1, 1), b=(randId1, 2), c=(randId1, 2)}, 
{b=(randId2, 1), c=(randId2, 1), d=(randId2, 1)}
]

where randId1 and randId2 can be generated at runtime(I just need a way to trace back to a unique source) and () represents a Pair class from Apache.

I have tried to wrap the doc in a Pair of (docId, doc) but I am stuck at modifying the Collectors.counting() substitution

List<Map<String, Long>> collect = docs.map(doc -> Pair.of(UUID.randomUUID(), doc))
    .map(p -> p.getRight().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())))
    .collect(Collectors.toList());

How do I get the output in the format needed ?

3 Answers
Related