Suppose we have a generator that might produce null values. If we create a stream of these using that generator, we’ll naturally want to wrap the elements in Optionals. Here’s what it looks like:
// streams/Signal.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class Signal {
private final String msg;
public Signal(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
@Override
public String toString() {
return "Signal(" + msg + ")";
}
static Random rand = new Random(47);
public static Signal morse() {
switch (rand.nextInt(4)) {
case 1:
return new Signal("dot");
case 2:
return new Signal("dash");
default:
return null;
}
}
public static Stream<Optional<Signal>> stream() {
return Stream.generate(Signal::morse).map(signal -> Optional.ofNullable(signal));
}
}
static <T> Stream<T> generate(Supplier<T> s)
Returns an infinite sequential unordered stream where each element is generated by the provided Supplier
. This is suitable for generating constant streams, streams of random elements, etc.
Type Parameters:
T
- the type of stream elements
Parameters:
s
- the Supplier
of generated elements
Returns:
a new infinite sequential unordered Stream
<R> Stream<R> map(Function<? super T,? extends R> mapper)
Returns a stream consisting of the results of applying the given function to the elements of this stream.
This is an intermediate operation.
Type Parameters:
R
- The element type of the new stream
Parameters:
mapper
- a non-interfering, stateless function to apply to each element
Returns:
the new stream
When we use this stream, we’ll have to figure out how we want to unpack the Optionals:
// streams/StreamOfOptionals.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
import java.util.*;
import java.util.stream.*;
public class StreamOfOptionals {
public static void main(String[] args) {
Signal.stream()
.limit(10)
// .peek(e -> System.out.println("Morse value: " + e))
.forEach(System.out::println);
System.out.println(" ---");
Signal.stream()
.limit(10)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println);
}
}
/* Output:
Optional[Signal(dash)]
Optional[Signal(dot)]
Optional[Signal(dash)]
Optional.empty
Optional.empty
Optional[Signal(dash)]
Optional.empty
Optional[Signal(dot)]
Optional[Signal(dash)]
Optional[Signal(dash)]
---
Signal(dot)
Signal(dot)
Signal(dash)
Signal(dash)
*/
public boolean isPresent()
Return true
if there is a value present, otherwise false
.
Returns:
true
if there is a value present, otherwise false
public <U> Optional<U> map(Function<? super T,? extends U> mapper)
If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional
describing the result. Otherwise return an empty Optional
.
API Note:
This method supports post-processing on optional values, without the need to explicitly check for a return status. For example, the following code traverses a stream of file names, selects one that has not yet been processed, and then opens that file, returning an Optional<FileInputStream>
:
Optional<FileInputStream> fis =
names.stream().filter(name -> !isProcessedYet(name))
.findFirst()
.map(name -> new FileInputStream(name));
Here, findFirst
returns an Optional<String>
, and then map
returns an Optional<FileInputStream>
for the desired file if one exists.
Type Parameters:
U
- The type of the result of the mapping function
Parameters:
mapper
- a mapping function to apply to the value, if present
Returns:
an Optional
describing the result of applying a mapping function to the value of this Optional
, if a value is present, otherwise an empty Optional
Throws:
NullPointerException
- if the mapping function is null
references:
1. On Java 8 - Bruce Eckel
2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/streams/Signal.java
3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/streams/StreamOfOptionals.java
6. https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#isPresent--
7. https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#map-java.util.function.Function-