irobotxx
irobotxx

Reputation: 6063

Return a List of present objects from a List of Optional objects using Lightweight-Stream-API

Consider I have an array list of Optional objects like List<Visit> visit = {Optional[Visit], Optional[Visit], ...}. How do i get the Visit object from the Optional and just return those objects as a List?

I tried something like this:

return Stream.of(visits).filter(value -> Optional.isPresent(value))
    .map((Visit t) -> Optional.get(t))
    .collect(Collectors.toList());

and this:

return Stream.of(visits)
   .map(visit -> Optional.of(visit).get())
   .collect(Collectors.toList());

But this doesn't compile.

I am trying to use Lightweight-Stream-API as the stream library.

Upvotes: -1

Views: 3021

Answers (2)

Harmlezz
Harmlezz

Reputation: 8068

You may do it this way:

return visits.stream()
             .map(visit -> visit.orElse(null))
             .filter(Objects::nonNull)
             .collect(Collectors.toList());

Assuming visits is of type List<Optional<Visit>>.

Causes Of Your Code Not Compiling

Assuming that the variable visits is of type List<Optional<Visit>> the statement you posted:

Stream.of(visits).filter(value -> Optional.isPresent(value))
                 .map((Visit t) -> Optional.get(t))
                 .collect(Collectors.toList());

has the following problems:

  1. Stream.of() takes either one element or many elements of type T and creates a Stream. You use visits as one element of type List<Optional<Visit>> and I think you intend to get a Stream of Optional<Visit> which you may achieve by using visits.stream().

  2. filter(value -> Optional.isPresent(value)) does invoke isPresent(T t) in a static way while the method isPresent(T t) doesn't exist, neither statically nor as an instance method. I think what you intend to do is: filter(value -> value.isPresent()) which is equal to filter(Optional::isPresent). The difference of the second is that Optional::isPresent does not invoke a static method but results in a method reference.

  3. map((Visit) t -> Optional.get(t)) does as well invoke a method get(T t) in a static way which doesn't exist, neither statically nor as an instance method. I think you intended to invoke map((Visit) t -> t.get()) which is equal to map(Optional::get).

Fixing those issues would result in the new statement:

visits.stream().filter(Optional::isPresent)
               .map(Optional::get)
               .collect(Collectors.toList());

The difference to my solution is only that you map after filter. As a reader to get it right you need to remember that Optional::get will always return a non-null value. If you map first and filter second you do not have to remember there are no null values because you filter them out in the second step.

Upvotes: 5

fps
fps

Reputation: 34460

You could do it as follows:

List<Visit> visitsWithoutOptionals = visits.stream()
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(Collectors.toList());

Upvotes: 4

Related Questions