less code (words frequency)

A blog that solves a programming puzzle (words frequency kata) in three ways.
The goal is first to write a correct program, then at each solution
to reduce the total lines of the program.
The kata
The problem has as an input a string with characters and as an output a map
that the key is a character and a value how many times this character appeared.
input/output example
input: "aaabb"
output: {a: 3, b: 2} // in java map the keys are the a, b and the corresponding values 3, 2
method signature
Map<Character, Integer> computeFrequencies(String input)
Solution 1 (no use of functional java)
public static Map<Character, Integer> computeFrequenciesV1(String input) {
        Map<Character, Integer> result = new HashMap<>();
        for (int index = 0 ; index < input.length(); index++) {
            char c = input.charAt(index);
            if (result.containsKey(c)) {
                Integer oldValue = result.get(c);
                result.put(c, ++oldValue);
            } else {
                result.put(c, 1);
            }
        }
        return result;
    }
solution explanation
  • Map instantiation (1 line)
  • classic for loop with index (1 line)
  • get the current character (1 line)
  • check if the character if it is contained in the map (with if statement) (1 line) if it is get the previous counter value and increase it (!! notice the ++ as prefix if you write it as suffix the counter will not increase the number) and put the new value in the map (2 lines)
  • else, put the new character with the value 1 (3 lines, else and curly brace included)
  • for termination (1 line)
  • finally, return map (1 line)
  • solution total lines: 11
    Solution 2 (with functional java)
    public static Map<Character, Integer> computeFrequenciesV2(String input) {
            Map<Character, Integer> result = new HashMap<>();
            for (int index = 0 ; index < input.length(); index++) {
                char c = input.charAt(index);
                result.compute(c, (key, value) -> value == null ? value = 1 : ++value);
            }
            return result;
        }
    solution explanation
  • Map instantiation (1 line)
  • classic for loop with index (1 line)
  • get the current character (1 line)
  • at this line compute method is used (magic happens here!). compute method has two arguments: The first is the key of the map. The second is a function (or BiFunction) with the key and the value. If there is a value that value increased and this is the new value for the key (character). Otherwise, the value (counter) is initialized to 1. (1 line!!) 1 line instead of 6 of the first solution
  • curly brace (1 line)
  • finally, return map (1 line)
  • solution total lines: 6 from 11, not bad and still readable I think
    Solution 3 (only functional java)
    public static Map<Character, Long> computeFrequenciesV3(String input) {
            return input.chars()
                    .mapToObj(c -> (char) c)
                    .collect(groupingBy(c -> c, Collectors.counting()));
        }
    solution explanation
  • with chars method we get an IntStream
  • with mapToObj we map the int value to char
  • finally, by using the collect method with the groupingBy we get the map that we want!
  • solution total lines: 3, we have a winner!
    groupingBy explanation:
  • takes two arguments, the first specifies the key of group (e.g. c -> c).
  • for example (in our case): "aaabb"
    the keys will be: a, b two groups in total
  • the second is the action that is performed in the group. In the specific kata the action is to count (e.g. Collectors.counting()) the elements of the group.
  • for example (in our case): "aaabb"
    the group with "a" we count three elements,
    while in the "b" group we count two element.
    If you haven't specified an action you will had a map with two keys and values:
    key: 'a'
    value: ['a', 'a', 'a']
    key: "b"
    value: ['a', 'a']
    the action operates in the lists (the reduction step).

    25

    This website collects cookies to deliver better user experience

    less code (words frequency)