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