https://github.com/jeffgbutler/practical-functional-java
https://jeffgbutler.github.io/practical-functional-java/
All code examples in examples.basics.optional.OptionalTest.java
@Test
public void testCreatingOptionals() {
Optional<String> name = Optional.of("Fred"); // value must be non-null
assertThat(name.isPresent()).isTrue();
name = Optional.ofNullable("Fred"); // value may be null
assertThat(name.isPresent()).isTrue();
name = Optional.ofNullable(null);
assertThat(name.isPresent()).isFalse();
name = Optional.empty(); // always empty
assertThat(name.isPresent()).isFalse();
}
The map method is used to transform an optional if it exists
@Test
public void testOptionalMap() {
Optional<String> name = Optional.of("Fred");
Optional<String> upperName = name.map(String::toUpperCase);
assertThat(upperName.isPresent()).isTrue();
assertThat(upperName.get()).isEqualTo("FRED");
}
The map method works on an empty Optional - just returns an empty Optional
@Test
public void testOptionalMapOnEmpty() {
Optional<String> emptyName = Optional.empty(); // or Optional.ofNullable(null);
Optional<String> emptyUpperName = emptyName.map(String::toUpperCase);
assertThat(emptyUpperName.isPresent()).isFalse();
try {
assertThat(emptyUpperName.get()).isEqualTo("FRED");
fail("found a value on an empty Optional");
} catch (NoSuchElementException e) {
// ignore
}
}
The filter method is used to test the value of an optional if present
@Test
public void testOptionalFilter() {
Optional<String> name = Optional.of("Fred");
Optional<String> fred = name.filter(s -> s.equals("Fred"));
Optional<String> notFred = name.filter(s -> !s.equals("Fred"));
assertThat(fred.isPresent()).isTrue();
assertThat(notFred.isPresent()).isFalse();
}
Just like streams, optional methods can be chained
@Test
public void testOptionalMethodChaining() {
Optional<String> name = Optional.of("Fred");
Optional<String> upperFred = name.filter(s -> s.equals("Fred"))
.map(String::toUpperCase);
assertThat(upperFred.isPresent()).isTrue();
assertThat(upperFred.get()).isEqualTo("FRED");
}
The orElse method is used to supply a default value if the optional is empty
@Test
public void testOptionalOrElse() {
Optional<String> fred = Optional.of("Fred");
String upperFred = fred.filter(s -> s.equals("Fred"))
.map(String::toUpperCase)
.orElse("Unknown");
assertThat(upperFred).isEqualTo("FRED");
Optional<String> barney = Optional.of("Barney");
upperFred = barney.filter(s -> s.equals("Fred"))
.map(String::toUpperCase)
.orElse("Unknown");
assertThat(upperFred).isEqualTo("Unknown");
}
The Optional.ifPresent method is for side effects. We don't want side effects, so avoid doing this
@Test
public void testOptionalIfPresent() {
Optional<String> name = Optional.of("Fred");
StringBuilder sb = new StringBuilder();
name.ifPresent(s -> {
sb.append(s.toUpperCase());
});
assertThat(sb.toString()).isEqualTo("FRED");
}
Optionals are a solution for dealing with many null issues. Optional.map and Optional.filter can replace a whole class of if statements in your code.