Functional approach to storing element counts in Map

70 Views Asked by At

I came across a problem where I needed to count the number of Strings in an Iterable and store the sums in a Map. I came up with the following imperative solution:

private static Map<String, Integer> generateCounts(Iterable<String> words) {
    Map<String, Integer> wordCounts = new HashMap<>();
    for (String word : words) {
        if (wordCounts.containsKey(word)) {
            Integer count = wordCounts.get(word);
            wordCounts.replace(word, count + 1);
        } else {
            wordCounts.put(word, 1);
        }
    }
    return wordCounts;
}

What would be a solution that leverages a functional approach instead of an imperative one like the one above?

1

There are 1 best solutions below

0
Gautham M On

If you are good with returning Map<String, Long> then you could do the below:

StreamSupport.stream(words.spliterator(), false /*sequential*/)
             .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

OR, without using stream, you could do as:

Map<String, Integer> wordCounts = new HashMap<>();
words.forEach(word -> wordCounts.merge(word, 1, Integer::sum));
return wordCounts;

Here the below if-else in your code is replaced by the merge function:

if (wordCounts.containsKey(word)) {
    Integer count = wordCounts.get(word);
    wordCounts.replace(word, count + 1);
} else {
    wordCounts.put(word, 1);
}