Is there a better way to count int occurrences with Java8
int[] monthCounter = new int[12];
persons.stream().forEach(person -> monthCounter[person.getBirt
If you would like to get Integer to Integer map, you can do the following.
Map<Integer, Integer> counters = persons.stream()
.collect(Collectors.groupingBy(
p -> p.getBirthday().getMonthValue(),
Collectors.reducing(0, e -> 1, Integer::sum)));
Try:
Map<Integer, Long> counters = persons.stream()
.collect(Collectors.groupingBy(p -> p.getBirthday().getMonthValue(),
Collectors.counting()));
Already answered. Small Suggestion from my side inorder to eliminate null pointer exception ie From the stream null will throw java.lang.UnsupportedOperationException, java.lang.NullPointerException
Map<Integer, Long> birthdayCount = persons.stream()
.filter(Objects::nonNull) // filter out null object
.filter(p->Objects.nonNull(p.getBirthday())) // filter out null birthdays
.collect(Collectors.groupingBy(p ->
p.getBirthday().getMonthValue(),
Collectors.counting()));
With Eclipse Collections (formerly GS Collections), you can make use of a data structure called Bag
that can hold the number of occurrences of each element.
Using IntBag
, the following will work:
MutableList<Person> personsEC = ListAdapter.adapt(persons);
IntBag intBag = personsEC.collectInt(person -> person.getBirthDay().getMonthValue()).toBag();
intBag.forEachWithOccurrences((month, count) -> System.out.println("Count of month:" + month + " is " + count));
If you want to make use of an array to keep track of the count, you can combine with the Arrays.setAll()
approach Brian pointed out in another answer.
int[] monthCounter = new int[12];
MutableList<Person> personsEC = ListAdapter.adapt(persons);
IntBag bag = personsEC.collectInt(person -> person.getBirthDay().getMonthValue()).toBag();
Arrays.setAll(monthCounter, bag::occurrencesOf);
System.out.println(IntLists.immutable.with(monthCounter));
This code will also work with Java 5 – 7 if you use anonymous inner classes instead of lambdas.
Note: I am a committer for Eclipse Collections
int size = persons.stream().count()
There's a few variations this could take.
You can use Collectors.summingInt()
to use Integer
instead of the Long
in the count.
If you wanted to skip the primitive int
array, you could store the counts directly to a List
in one iteration.
Count the birth months as Integers
Map<Integer, Integer> monthsToCounts =
people.stream().collect(
Collectors.groupingBy(p -> p.getBirthday().getMonthValue(),
Collectors.summingInt(a -> 1)));
Store the birth months in a 0-based array
int[] monthCounter = new int[12];
people.stream().collect(Collectors.groupingBy(p -> p.getBirthday().getMonthValue(),
Collectors.summingInt(a -> 1)))
.forEach((month, count) -> monthCounter[month-1]=count);
Skip the array and directly store the values to a list
List<Integer> counts = people.stream().collect(
Collectors.groupingBy(p -> p.getBirthday().getMonthValue(),
Collectors.summingInt(a -> 1)))
.values().stream().collect(Collectors.toList());