java lambda - how to traverse optional list/stream of optionals
Solution 1
First, check if the Optional
is present. If yes, then stream the list and filter the non-empty ones and print each of them.
optionalList.ifPresent(list -> list.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println));
Almost similar for the stream case too
optionalStream.ifPresent(stream -> stream
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println));
Solution 2
If you can use Java 9, it can be done like this:
optionalList.ifPresent(list -> list.stream()
.flatMap(Optional::stream)
.forEach(System.out::println));
For a stream of optionals it would be the same, without the first .stream()
call.
With Java 8 you don't have the Optional::stream
method available so you can do it yourself:
optionalList.ifPresent(list -> list.stream()
.flatMap(opt -> opt.map(Stream::of).orElseGet(Stream::empty))
.forEach(System.out::println));
And for a Stream
of Optional
s it would look like this:
optionalStream.ifPresent(stream -> stream
.flatMap(opt -> opt.map(Stream::of).orElseGet(Stream::empty))
.forEach(System.out::println));
Solution 3
You can indeed stream the Option<String>
and filter only non empty values.
Optional<List<Optional<String>>> optionalList = Optional.of(Arrays.asList(Optional.empty(), Optional.of("ONE"), Optional.of("TWO")));
optionalList.orElseGet(ArrayList::new)
.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println);
You can also use Optional.ifPresent()
as suggested in another answers :
optionalList.ifPresent(l -> l.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println));
Personally I prefer the first way because it removes a nested level : I find it more pleasant to read.
Solution 4
As I see there are two ways, second one look a bit more pretty to me, take a look:
class Scratch {
public static void main(String[] args) {
Optional<String> element1 = Optional.of("test1");
Optional<String> element2 = Optional.empty();
Optional<String> element3 = Optional.of("test2");
Optional<String> element4 = Optional.of("test3");
List<Optional<String>> list = Arrays.asList(element1, element2, element3, element4);
System.out.println(extractStrings1(list));
System.out.println(extractStrings2(list));
}
private static List<String> extractStrings1(List<Optional<String>> list) {
return list.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
}
private static List<String> extractStrings2(List<Optional<String>> list) {
List<String> result = new ArrayList<>();
list.forEach(element -> element.ifPresent(result::add));
return result;
}
}
Solution 5
Well ...
- Check whether the optional list is present.
- Do a "for each" for all elements of the (now present) list.
- In each step check whether the optional string is present.
- If yes, print it.
A one-liner can do that:
optionalList.ifPresent(list -> list.forEach(s -> s.ifPresent(System.out::println)));
Sara Vino
Updated on July 09, 2022Comments
-
Sara Vino almost 2 years
Having an Optional List of Optional's like:
Optional<List<Optional<String>>> optionalList = Optional.of( Arrays.asList( Optional.empty(), Optional.of("ONE"), Optional.of("TWO")));
How to traverse
optionalList
to print out the string'sONE
andTWO
?What about having an Optional Stream of Optionals?
Optional<Stream<Optional<String>>> optionalStream = Optional.of( Stream.of( Optional.empty(), Optional.of("ONE"), Optional.of("TWO")));
Update: Thanks for answers, solution for optionalStream (non nested):
optionalStream .orElseGet(Stream::empty) .filter(Optional::isPresent) .map(Optional::get) .forEach(System.out::println);
-
Sara Vino over 5 yearsadding a
.map(Optional::get)
will print the string -
jbx over 5 yearsThe first way will create an empty
ArrayList
for nothing if the list does not exist. -
davidxxx over 5 yearsIt is right. But creating an empty
ArrayList
living in the scope of a stream execution costs also nothing. -
Sara Vino over 5 yearstried for a stream of optionals omitting first
.stream()
call - but not working (java 8) -
chrylis -cautiouslyoptimistic- over 5 yearsI don't have an IDE handy, but wouldn't a
flatMap
squash the need for all of theisPresent
checks? -
jbx over 5 yearsWhat do you mean doesn't work? Just tried the Java 8 version, with the first line replaced to:
optionalStream.ifPresent(stream -> stream
definitely works. -
jbx over 5 years@chrylis Yes. All these answers are so bloated, when all one needs to do is convert the
Optional
items in the list to aStream
andflatMap
to it.