DevoxxUK Lambdas Lab
Paul Sandoz
paul.sandoz at oracle.com
Wed Apr 3 05:25:18 PDT 2013
On Apr 3, 2013, at 1:13 PM, Stephen Colebourne <scolebourne at joda.org> wrote:
> My experience (part 2):
> I found the API for the word frequency use case to be remarkably
> tricky to find. The proposed "correct" solution is certainly
> non-obvious, and IMO less clear than writing the code out in
> non-lambda Java.
>
> Following a relatively simpe approach to trying to solve a problem -
> just keep adding steps until it works - I ended up with something
> pretty horrendous:
>
> try (BufferedReader br = new BufferedReader(
> new InputStreamReader(
> CountWordFreq.class.getResourceAsStream("book.txt")))) {
>
> Map<String, List<String>> initial = br.lines()
> .flatMap(s -> Arrays.stream(s.split(" ")))
> .collect(Collectors.groupingBy(s -> s));
>
The source of the problem here is the initial selection of a collector and a redundant intermediate representation that is leading you down the wrong path. We need certainly more documentation with examples and guidance.
Notice that groupingBy wants to classify the key using a mapping function. Where as what you want to do is map the key to a value that is combined with an existing map value (if present).
Essentially you want to collect String<String> to a Map<String, Integer>. You can use toMap for that:
br.lines().
flatMap(s -> Arrays.stream(s.split(" "))).
collect(toMap(s -> 1, HashMap::new, Integer::sum));
You can also do it using groupingBy as you have found out, but that is less obvious (and less efficient too).
Frequencies is a common enough use-case that we should consider having a toFrequencies method.
Paul.
More information about the lambda-dev
mailing list