Java optional list to stream

Java streams: Optional to stream

You’re overcomplication things here. i.e you don’t actually need to wrap app.quotes into an optional only to check if it’s non-null (which actually abuses the main purpose of Optional) etc.

since you want a Stream> you can do so as follows:

application.filter(app -> app.getQuotes() != null) .map(Stream::of).orElseGet(Stream::empty) .flatMap(app -> app.getQuotes().stream().map(quote -> Pair.of(app, quote))); 
application.filter(app -> app.getQuotes() != null).stream() .flatMap(app -> app.getQuotes().stream().map(quote -> Pair.of(app, quote))); 

Optional.orElse

Ideally what you currently have is Optional>> optionalPairStream and what you might just be looking for just add a default case and get just the Stream as :

Stream> pairStream = application .map(app -> Pair.of(app, Optional.ofNullable(app.getQuotes()))) .filter(quote -> quote.getValue().isPresent()) .map(quote -> quote.getValue().get().stream().map(q -> Pair.of(quote.getKey(), q))) .orElse(Stream.empty()); 

Optional.stream

With Java9, you can update the same code as:

Stream> pairStream = application .map(app -> Pair.of(app, Optional.ofNullable(app.getQuotes()))) .filter(quote -> quote.getValue().isPresent()) .stream() // new API .flatMap(quote -> quote.getValue().orElse(Collections.emptyList()) .stream().map(q -> Pair.of(quote.getKey(), q))); 

Источник

Java stream of optionals to optional stream

I need to convert Stream to Optional> . The output Optional> should be an empty value when at least one value of Stream is empty. Do you know any functional way to solve the problem? I tried to use collect method, but without success.

4 Answers 4

Well, the tricky thing here is that if you’re just given a Stream , you can only use it once.

To be stateless and avoid redundant copying, one way is to just catch NoSuchElementException :

static Optional invert(Stream stream) < try < return Optional.of( stream.map(Optional::get) .collect(Collectors.toList()) .stream()); >catch (NoSuchElementException e) < return Optional.empty(); >> 

A simple inversion would be:

static Optional invert(Stream stream)

But to find out if it contains an empty element, you need to actually traverse it which also consumes it.

If you’re given the source of the stream, you can traverse it without collecting it:

static Optional invert( Supplier> supplier) < // taking advantage of short-circuiting here // instead of allMatch(Optional::isPresent) return supplier.get().anyMatch(o ->!o.isPresent()) ? Optional.empty() : Optional.of(supplier.get().map(Optional::get)); > 
List> myInts = Arrays.asList(Optional.of(1), Optional.of(2), Optional.of(3)); Optional> inverted = invert(myInts::stream); 

That’s probably a more interesting approach. (But it’s prone to a race condition because the stream() is taken twice. If some other thread adds an empty element in between and gets away with it, we have a problem.)

Though this has already been answered yet to add to the list, with Java-9 introducing Optional.stream , this should be achievable as:

// initialized stream of optional Stream> so = Stream.empty(); // mapped stream of T Stream s = so.flatMap(Optional::stream); // constructing optional from the stream Optional os = Optional.of(s); 

Not that my answer is particularly good either, but this doesn’t solve the problem as-stated: that the Stream should be empty if any Optional is empty. This answer just filters out the empty elements.

Similar to Radiodef’s answer, though this one avoids the exception handling and the intermediate list.

private static Optional invertOptional(Stream input) < return input.map(integer ->integer.map(Stream::of)) .collect(Collectors.reducing((l, r) -> l.flatMap(lv -> r.map(rv -> Stream.concat(lv, rv))))) .orElse(Optional.empty()); > 

The way this works is it maps to a Stream of Optional Streams of T. The Optional.map is used in this case, so each one of the Optional> items in the resultant stream is a either a Stream of 1, or an empty Optional.

Then it collects these streams by reducing them together. the l.flatMap will return an empty Optional if l is empty or the r.map returns an empty. if r.map isn’t empty, it calls the Stream.concat, which combines the left and right stream values.

The whole collect reduction produces an Optional>> , so we narrow that down with the .orElse(Optional.empty)

Note: Code is tested, and appears to work. The unspecified «edge case» of an empty input Stream is treated as an an empty Optional, but can be easily changed.

Источник

java lambda — how to traverse optional list/stream of optionals

How to traverse optionalList to print out the string’s ONE and TWO ? What about having an Optional Stream of Optionals?

Optional>> optionalStream = Optional.of( Stream.of( Optional.empty(), Optional.of("ONE"), Optional.of("TWO"))); 
optionalStream .orElseGet(Stream::empty) .filter(Optional::isPresent) .map(Optional::get) .forEach(System.out::println); 

You can also just map the Optional to a Stream instead of checking isPresent and getting the value yourself explicitly. Will be a bit more ‘functional style’.

You should avoid storing Optional in collections, see Uses for Optional and Is it Worth it to Use ‘Optional’ in Collections?

@DidierL true, however this is still a valid exercise for the case of Stream which is much more common when the items in your collection are being mapped to an Optional by some other function, so you end up with a Stream , which you then want to filter and convert to a Stream .

Indeed, for me this was a valid case as well. Note that there is an Optional.stream() method introduced in Java 9 to avoid that (to combine with flatMap() ). Finally, I would also avoid Optional and Optional as they are not very friendly to work with. Use empty lists/streams instead whenever possible as this makes far cleaner API’s.

6 Answers 6

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)); 

You can indeed stream the Option and filter only non empty values.

Optional>> 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.

It is right. But creating an empty ArrayList living in the scope of a stream execution costs also nothing.

@chrylis Yes. All these answers are so bloated, when all one needs to do is convert the Optional items in the list to a Stream and flatMap to it.

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)); 

What do you mean doesn’t work? Just tried the Java 8 version, with the first line replaced to: optionalStream.ifPresent(stream -> stream definitely works.

optionalList.stream().flatMap(List::stream).filter(Objects::nonNull).forEach(. ) 

This version is nice because it avoids the creation of an empty list and skips right to the empty stream (but is only possible in Java 9+ when Optional.stream was introduced).

  1. Check whether the optional list is present.
  2. Do a «for each» for all elements of the (now present) list.
  3. In each step check whether the optional string is present.
  4. If yes, print it.
optionalList.ifPresent(list -> list.forEach(s -> s.ifPresent(System.out::println))); 

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) < Optionalelement1 = Optional.of("test1"); Optional element2 = Optional.empty(); Optional element3 = Optional.of("test2"); Optional element4 = Optional.of("test3"); List list = Arrays.asList(element1, element2, element3, element4); System.out.println(extractStrings1(list)); System.out.println(extractStrings2(list)); > private static List extractStrings1(List list) < return list.stream() .filter(Optional::isPresent) .map(Optional::get) .collect(Collectors.toList()); >private static List extractStrings2(List list) < Listresult = new ArrayList<>(); list.forEach(element -> element.ifPresent(result::add)); return result; > > 

Источник

Читайте также:  javaScript Digital Clock with date
Оцените статью