Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optional<List> Java 8 lambda expressions get first element

I am newbie here and trying my way hard through java 8 streams + lambda. Can someone help me with the below piece of code? Need to find the age of first person from the list which is optional. This list could be null.

Missing from the code - null check for the first element of the list. Would like to have this check as well.

Something equivalent to below piece of code.

//input parameter 
//Optional<List<Person>> persons
public Integer getAgeOfFirstPerson(Optional<List<Person>> persons) {
    if (!persons.isPresent()) {
        return null;
    }

    Integer age = persons.get()
        .get(0)
        .getAge();

    return age;
}

//Person.java
class Person {
    Integer age;
    //getters and setters
}
like image 740
meso Avatar asked Aug 22 '18 17:08

meso


People also ask

Which of the following Java stream operations return an optional containing the first element of a non empty stream?

The findFirst() method returns an Optional describing the first element of the given stream if Stream is non-empty, or an empty Optional if the stream is empty.

What does findFirst () do in Java?

The findFirst() method finds the first element in a Stream. So, we use this method when we specifically want the first element from a sequence. When there is no encounter order, it returns any element from the Stream. According to the java.


2 Answers

Assuming the List inside your Optional can be empty, then you should account for this case as well. The easiest would thus be:

return persons.flatMap(list -> list.stream().findFirst()).map(Person::getAge).orElse(null);

This unfortunately does not handle a null first list entry as findFirst() throws a NullPointerException when the first element of a Stream is null (as Holger noted in the comments).

So if you want to skip null list entries and take the first non-null one, do as follows:

return persons.flatMap(list -> list.stream().filter(Objects::nonNull).findFirst())
              .map(Person::getAge)
              .orElse(null);

Otherwise, if instead you always want the first entry even when it is null, you could adapt it like this:

return persons.flatMap(list -> list.stream().limit(1).filter(Objects::nonNull).findFirst())
              .map(Person::getAge)
              .orElse(null);

however this really becomes quite convoluted, so it is simpler to just get back to testing whether the list is empty:

return persons.filter(list -> !list.isEmpty())
              .map(list -> list.get(0))
              .map(Person::getAge)
              .orElse(null);
like image 188
Didier L Avatar answered Sep 20 '22 13:09

Didier L


You could use Optional.map

public int getAgeOfFirstPerson(Optional<List<Person>> persons){ 
    return persons.map(people -> people.get(0).getAge()).orElse(0);
}

Do note, primitives do not have null(they are not objects), hence have replaced that with 0.

Or further improved as answered by @Alexey, if need be to check for Person being null as well.

like image 25
Naman Avatar answered Sep 18 '22 13:09

Naman