Home > OS >  How to apply multiple Conditions in Java streams
How to apply multiple Conditions in Java streams

Time:05-29

I have a list of Person.

I want to find a person either has employment with the maximum age, else return any person the with maximum age.

I have written the following piece of code.

Is this fine or can have better approach.

List <Person> personList;
    
Person person = personList.stream()
    .filter(p -> p.isEmployed())
    .max(Comparator.comparing(Person::getAge))
    .orElse(personList.stream()
                .max(Comparator.comparing(Person::getAge))
                .orElse(null));

CodePudding user response:

I have a list of Person. I want to find a person either have employment with maximum age else return person with maximum age.

It can be done in a single pass through the list by creating an intermediate map, using collector partioningBy() and providing collector maxBy() as the downstream.

This combination will create a map containing two entries with keys false and true and values of type Optional<Person>. Because maxBy() produces an optional result.

Firstly, we have to get rid of empty optional by applying filter().

Then we can sort these entries in reversed order by key, so that true will come before false (the natural order: false -> true). I.e. employed person having the greatest age will come first.

The last step is to apply findFirst() and extract the value from the resulting map entry.

Because we are sorting only two entries, it will not cause any tangible overhead and the code will run linear time (reminder: maxBy() runs in O(n) time, performing a single pass through the data set).

List<Person> personList =
    List.of(new Person(23, false), new Person(32, true),
            new Person(36, true), new Person(39, false),
            new Person(19, false), new Person(21, true));

Person person = personList.stream()
    .collect(Collectors.partitioningBy(Person::isEmployed, // intermediate map Map<Boolean, Optional<Person>>
        Collectors.maxBy(Comparator.comparing(Person::getAge))))
    .entrySet().stream()
    .filter(entry -> entry.getValue().isPresent())
    .sorted(Map.Entry.<Boolean, Optional<Person>>comparingByKey().reversed())
    .findFirst()              // Optional<Map.Entry<Boolean, Optional<Person>>>
    .map(Map.Entry::getValue) // Optional<Optional<Person>>
    .map(Optional::get)       // Optional<Person>
    .orElse(null);

System.out.println(person);

Output:

Person {  age = 36, isEmployed = true }

A link to the Online Demo

  • Related