4

To protect the question from "duplicate hunters", I need to mention that I did not think that the solution I am looking for is filtering. I did my search, never encounter an answer mentioning filtering.

I have a list of objects with a class like that:

class Person {
  String gender;
  String income;
  String petName;
}

I want to collect this List into a map, groupingBy gender, and counting the pets they have, and of course need to pass 0 if petName is null.

Map<String, Long> mapping = people
  .stream()
  .collect(Collectors.groupingBy(Person::gender, Collectors.counting());

Without implementing the Collector interface and it's 5 methods( Because I am already trying to get rid of another custom collector) How can I make this to not count the object if it's petName field is null.

I can benefit from Java-11

Melih
  • 666
  • 1
  • 9
  • 24
  • 1
    Possible duplicate of [How to apply Filtering on groupBy in java streams](https://stackoverflow.com/questions/48273090/how-to-apply-filtering-on-groupby-in-java-streams) – Naman Oct 09 '19 at 11:35
  • Never thought applying some filtering to my collection before seeing the answer. I already did my search. Don't mark everything as duplicate to get points... – Melih Oct 09 '19 at 15:22

2 Answers2

7

First, group all the people by their gender, and then use the filtering collector to filter out the people with null names. Finally, use the counting downstream collector to count the number of elements belong to each category. Here's how it looks.

Map<String, Long> peopleCntByGender = people.stream()
    .collect(Collectors.groupingBy(Person::getGender, 
        Collectors.filtering(p -> p.getPetName() != null, 
            Collectors.counting())));

However, the filtering collector is only available in Java9, hence if you are using Java8 and can't migrate to Java9 that easily, consider writing your own custom filtering collector and use it here. This answer or JDK 9 source code may help.

Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
  • 4
    Just a call out, the `Collectors.filtering` works with Java-9 and above. – Naman Oct 09 '19 at 11:30
  • Interesting, I do use Java9, so in that case OP would need to write one for Java8. – Ravindra Ranwala Oct 09 '19 at 11:33
  • 6
    For an implementation with Java-8 refer to [How to apply Filtering on groupBy in java streams](https://stackoverflow.com/questions/48273090/how-to-apply-filtering-on-groupby-in-java-streams) – Naman Oct 09 '19 at 11:36
  • 1
    We are using Java-11, no problem there. Instead of suggesting a new dependency or upgrade, providing a solution for Java-8 is appreciated – Melih Oct 09 '19 at 15:30
2

With regards to the comment above (about needing a 0 in the case that gender has no pets) I believe the following covers your requirements:

people.stream()
      .collect(Collectors.toMap(Person::getGender,
                person -> person.getPetName() == null ? 0L : 1L,
                Long::sum));
Naman
  • 27,789
  • 26
  • 218
  • 353
BeUndead
  • 3,463
  • 2
  • 17
  • 21