DhiwaTdG DhiwaTdG - 3 months ago 21
Java Question

Java count occurrence of each element in an integer array

I've written the following snippet to count the number of occurrences of each element. Is it possible to achieve this in a much shorter way?

int[] arr = {1, 6, 2, 8, 5, 4, 7, 7, 5, 7};
Arrays.stream(arr)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll)
.stream()
.collect(Collectors.groupingBy(s -> s))
.forEach((k, v) -> System.out.println(k+" "+v.size()));


Also I would like to display only the elements which occur more than 1 time. So I tried modifying as below which resulted in an error.

.forEach((k, v) -> if(v.size() > 1) System.out.println(k+" "+v.size()));


What is the correct way to do this?

Answer

For the latter question, you have to change

.forEach((k, v) -> if(v.size() > 1) System.out.println(k+" "+v.size()));

to

.forEach((k, v) -> {if(v.size() > 1) System.out.println(k+" "+v.size());});

For the first part, it's not clear why you need the first collect followed by a second Stream pipeline. If the purpose was to convert an IntStream to a Stream<Integer>, use boxed():

Arrays.stream(arr)
      .boxed()
      .collect(Collectors.groupingBy(s -> s))
      .forEach((k, v) -> System.out.println(k+" "+v.size()));

As Dici suggested, you can also chain Collectors to group each number with its number of occurrences :

Map<Integer,Integer> occurrences = 
    Arrays.stream(arr)
          .boxed()
          .collect(Collectors.groupingBy(s -> s, Collectors.counting()));