-1

I have 2 methods for getting average age of woman, and second for getting average age of man. I need to do one method to agregate this 2 methods.

This method as first parameter should have list of person, and as a second parameter function what will decide if we are looking for man or woman average age.

This is my methods:

public double getMenAverageAge(List<Person> personList){
    return Optional.ofNullable(personList)
            .orElseGet(ArrayList::new)
            .stream()
            .filter(Objects::nonNull)
            .filter(p -> !Boolean.parseBoolean(String.valueOf(p.getFirstName().endsWith("a"))))
            .mapToDouble(Person::getAge)
            .average()
            .orElse(0);
}

public double getAverageWomenAge(List<Person> personList){
    return Optional.ofNullable(personList)
            .orElseGet(ArrayList::new)
            .stream()
            .filter(Objects::nonNull)
            .filter(p-> Boolean.parseBoolean(String.valueOf(p.getFirstName().endsWith("a"))))
            .mapToDouble(Person::getAge)
            .average()
            .orElse(0);
}

Any ideas?

  • create an interface with one method and pass it as argument to your desired function then call it's method inside this function – Morph21 Mar 16 '22 at 12:47
  • Does this answer your question? [Java Pass Method as Parameter](https://stackoverflow.com/questions/2186931/java-pass-method-as-parameter) – Morph21 Mar 16 '22 at 12:49
  • Unrelated, but I'm not convinced that "first name ends with -a" reliably tells you whether it's a male or female name. – jsheeran Mar 16 '22 at 12:50
  • 1
    @jsheeran in Poland that's 99.9% true – Morph21 Mar 16 '22 at 12:54
  • 3
    Why are you using `p -> Boolean.parseBoolean(String.valueOf(p.getFirstName().endsWith("a")))` and not just `p -> p.getFirstName().endsWith("a")`? The conversion of boolean to String to boolean is unnecessary. – Rob Spoor Mar 16 '22 at 12:59

1 Answers1

1
Predicate<Person> p = p-> Boolean.parseBoolean(String.valueOf(p.getFirstName().endsWith("a")));

Predicate<Person> is just a type. There's not much difference between the above and String x = "hello";. You can make a method that accepts that type as param:

public double getAverageAge(List<Person> list, Predicate<Person> filter) {
  return list
            .stream()
            .filter(filter) 
            .mapToDouble(Person::getAge)
            .average()
            .orElse(0);

NB: You have null tourette, it's a formula for writing lots of code that is impossible to test. Don't do it. Love the NPE. The correct response to someone invoking this method passing in null for a list is to crash with an NPE: null is best treated as 'unset' / 'unknown', and it is not possible to get the average age of an unknown list. The answer is not 0. The answer is ¯\(ツ)/¯.

Similarly, if somehow a null got into your list of persons, then the age of that person is also unknown. It is not possible to determine the average age of a batch of persons when one of the persons in there is a complete unknown, again, just NPEing is in fact the right response.

The best way to deal with null in java is to use the tools to your advantage: If the NullPointerException is in fact the best thing that could happen, you're doing it right.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72