Search code examples
javalistcollectionsstreamhashmap

Count occurrences by stream


LinkedList<Double> list = new LinkedList<Double>();
list.add(9.5);
list.add(4.9);
list.add(3.2);
list.add(4.9);

I want to count the duplicate element in the list through a stream and put them into a HashMap which represent the occurrence of each number in the list: e.g: (9.5=1, 4.9=2, 3.2=1) Does anybody know how this works?


Solution

  • Using Collections.frequency

    Make a list of all the distinct values, and for each of them, count their occurrences using the Collections.frequency method. Then collect into a Map

    Map<Double, Integer> result = list.stream()
            .distinct()
            .collect(Collectors.toMap(
                Function.identity(),
                v -> Collections.frequency(list, v))
            );
    

    Using Collectors.groupingBy

    I think it is not as nice as the example above.

    Map<Double, Integer> result2 = list.stream()
        .collect(Collectors.groupingBy(Function.identity())) // this makes {3.2=[3.2], 9.5=[9.5], 4.9=[4.9, 4.9]}
        .entrySet().stream()
        .collect(Collectors.toMap(
            Map.Entry::getKey,
            e -> e.getValue().size())
        );
    

    Plain for loop

    A plain for loop is quite short, you might not need streams and lambdas

    Map<Double, Integer> map = new HashMap<>();
    for(Double d : list)
      map.put(d, map.containsKey(d) ? map.get(d)+1 : 1);
    

    Using forEach

    Even shorter with forEach

    Map<Double, Integer> map = new HashMap<>();
    list.forEach(d -> map.put(d, map.containsKey(d) ? map.get(d)+1 : 1));