Filter, FlatMap andUsing Optional containers for primitive number types


Filter

filter() is used to indicate that you would like the value only if it matches your predicate.

Think of it like if (!somePredicate(x)) { x = null; }.

Code examples:

String value = null;
Optional.ofNullable(value) // nothing
        .filter(x -> x.equals("cool string"))// this is never run since value is null
        .isPresent(); // false
 
String value = "cool string";
Optional.ofNullable(value) // something
        .filter(x -> x.equals("cool string"))// this is run and passes
        .isPresent(); // true
 
String value = "hot string";
Optional.ofNullable(value) // something
        .filter(x -> x.equals("cool string"))// this is run and fails
        .isPresent(); // false

Using Optional containers for primitive number types

OptionalDouble, OptionalInt and OptionalLong work like Optional, but are specifically designed to wrap primitive types:

OptionalInt presentInt = OptionalInt.of(value);
OptionalInt absentInt = OptionalInt.empty();

Because numeric types do have a value, there is no special handling for null. Empty containers can be checked with:

presentInt.isPresent(); // Is true.
absentInt.isPresent(); // Is false.

Similarly, shorthands exist to aid value management:

// Prints the value since it is provided on creation.
presentInt.ifPresent(System.out::println);
 
// Gives the other value as the original Optional is empty.
int finalValue = absentInt.orElseGet(this::otherValue);
 
// Will throw a NoSuchElementException.
int nonexistentValue = absentInt.getAsInt();

Run code only if there is a value present

Optional<String> optionalWithValue = Optional.of("foo");
optionalWithValue.ifPresent(System.out::println);//Prints "foo".
 
Optional<String> emptyOptional = Optional.empty();
emptyOptional.ifPresent(System.out::println);//Does nothing.

FlatMap

flatMap is similar to map. The difference is described by the javadoc as follows:

  • This method is similar to map(Function), but the provided mapper is one whose result is already an Optional, and if invoked, flatMap does not wrap it with an additional Optional.

In other words, when you chain a method call that returns an Optional, using Optional.flatMap avoids creating nested Optionals.

For example, given the following classes:

public class Foo {
	Optional<Bar> getBar(){
		return Optional.of(new Bar());
	}
}
 
public class Bar {
}
 
If you use Optional.map, you will get a nested Optional; i.e. Optional<Optional<Bar>>.
 
Optional<Optional<Bar>> nestedOptionalBar =
	Optional.of(new Foo())
		.map(Foo::getBar);
 
However, if you use Optional.flatMap, you will get a simple Optional; i.e. Optional<Bar>.
 
Optional<Bar> optionalBar =
	Optional.of(new Foo())
		.flatMap(Foo::getBar);

Basic Programs