Optionalとは
Javaでは値のない状態のことをnullと言いますが、nullが原因で意図しないエラーが発生することも多いです。そのため、エラーを未然に防ぐためにif文を利用してnullチェックの処理を書く必要がありました。
Java8から java.util.Optionalクラスが導入されました。Optionalを使うと、値がnullであるかどうかを簡潔に書くことができます。if文のブロックを書かなくてもnullチェックが記述する事ができます。
- Optionalはnullかもしれないと伝えるもの
また、「値が入っていない場合」という処理を明示的に記述することが出来るため、ifによるnullチェック時のミスを減らすことも可能になり、プログラムの堅牢性が向上します。
オブジェクトの生成
of(nullでない値専用 )
非null値を持つOptionalオブジェクトを返します。 ofにnullなオブジェクトを渡すと例外がスローされます。
String str = "nonNull";
Optional<String> nonNullString = Optional.of(str);
nonNullString.isPresent();
// true
nonNullString.get();
// result : nonNull
String str2 = null;
Optional.of(str2);
// java.lang.NullPointerException
ofNullable(nullかもしれない )
ofNullableメソッドの引数にはnullの可能性があるオブジェクト名を指定します。ofNullableメソッドは引数がnullの場合に、Optional型の空のオブジェクトを返します。引数がnull以外の場合は、指定された値を記述するOptional型のオブジェクトを返します。
String str = null;
Optional<String> nullableString = Optional.ofNullable(str);
nullableString.isPresent();
// false
nullableString.orElse("other");
// other
empty (空の Optional オブジェクト)
null値を持つOptionalオブジェクトを返します。
Optional<String> value = Optional.empty();
empty.isPresent();
// false
empty.orElse("other");
// other
empty.get();
// java.util.NoSuchElementException: No value present
値を取り出す
get
Optionalオブジェクトが保持する値を返します。値がない場合は、NoSuchElementExceptionがthrowされます。
String str = "apple";
Optional<String> nullableString = Optional.ofNullable(str);
nullableString.get();
// apple
String str2 = null;
Optional<String> nullableString2 = Optional.ofNullable(str2);
nullableString2.get();
// java.util.NoSuchElementException: No value present
値をチェックする
isPresent
Optionalオブジェクトが保持する値が非nullの場合はtrue、nullの場合はfalseを返します。
String str = "hoge";
Optional<String> value = Optional.of(str);
if(value.isPresent()) {
System.out.println("値があります");
}
isEmpty
Optionalオブジェクトが保持する値がnullの場合はtrue、 非nullの場合はfalseを返します。
String str = null;
Optional<String> value = Optional.of(str);
if(value.isEmpty()) {
System.out.println("値がnullです");
}
ifPresentOrElse
ifPresentOrElseメソッドではnullでない場合の処理を第1引数に指定します。nullの場合の処理を第2引数に指定します。
Optional<Employee> employee = Optional.ofNullable(null);
employee.ifPresentOrElse((e) -> {
e.setName(e.getName().toUpperCase());
System.out.println(e);
},
() -> {
System.out.println("empty action");
// empty action
});
値がない時にデフォルト値を指定する
or
Optionalオブジェクトが保持する値がnullの場合、引数に指定するSupplierが生成したOptionalオブジェクトを返します。
Supplierがnullを返すと例外がスローされます。
String str = null;
Optional<String> nonNullString = Optional.ofNullable(str).or(() -> Optional.of("nonNull"));
nonNullString.isPresent();
// true
nonNullString.get();
// nonNull
orElse
Optionalオブジェクトが保持する値を返します。保持する値がnullの場合は指定した値を返します。
String str = "nonNull";
Optional<String> nullableString = Optional.ofNullable(str);
nullableString.orElse("other");
// nonNull
String str2 = null;
Optional<String> nullableString2 = Optional.ofNullable(str2);
nullableString2.orElse("other");
// other
orElseGet
Optionalオブジェクトが保持する値を返します。保持する値がnullの場合は指定したSupplierの結果を返します。
Supplierがnullを返す場合はnullが返ります。
String str = "nonNull";
Optional<String> nullableString = Optional.ofNullable(str);
nullableString.orElseGet(() -> "other");
// nonNull
String str2 = null;
Optional<String> nullableString2 = Optional.ofNullable(str2);
nullableString2.orElseGet(() -> "other");
// other
orElseThrow
Optionalオブジェクトが保持する値を返します。保持する値がnullの場合は指定した例外がスローされます。
String str = null;
Optional<String> nullableString = Optional.ofNullable(str);
nullableString.orElseThrow(RuntimeException::new);
// java.lang.RuntimeException
値を加工する
map
値がある場合に、引数で指定した処理を実行して加工した値の Optional オブジェクトを返却します。
Optional<String> nullableString = Optional.ofNullable("apple");
Optional<Integer> mapping = nullableString.map(str -> str.length());
mapping.isPresent();
// true
mapping.orElse(0);
// 5
値変換の結果がOptionalの場合に便利なflatMap
Optional<Long> optId = Optional.of(1L);
Optional<String> optName = Optional.of("john");
Optional<Employee> result = optId.flatMap(id -> optName.flatMap(name -> Optional.of(new Employee(id, name))));
result.isPresent();
// true
result.orElse(null);
// Employee{id=1, name='john'}
条件にマッチした値だけにする
filter
Optionalオブジェクトが保持する値が非nullの場合、その値で引数に指定するPredicateの処理ブロックを実行します。 Optionalオブジェクトが保持する値がnullの場合、またはPredicateの処理ブロックがfalseを返す場合は空のOptionalが返ります。
Optional<String> nullableString = Optional.ofNullable("banana");
Optional<String> filtering = nullableString.filter(str -> str.length() > 5);
filtering.isPresent();
// true
filtering.orElse("other");
// banana
Optional<String> nullableString2 = Optional.ofNullable("apple");
Optional<String> filtering2 = nullableString2.filter(str -> str.length() > 5);
filtering2.isPresent();
// false
filtering2.orElse("other");
// other
値でStreamを作るstream
stream
Optionalオブジェクトが保持する値が非nullの場合はその値だけを持つstreamを返し、nullの場合は空のstreamを返します。
List<Optional<String>> list = List.of(
Optional.of("a"),
Optional.of("b"),
Optional.of("c"),
Optional.empty(),
Optional.of("e"),
Optional.empty(),
Optional.of("g")
);
list.stream().filter(Optional::isPresent).map(Optional::get).forEach(System.out::println);
// a
// b
// c
// e
// g
// streamを使う場合
list.stream().flatMap(Optional::stream).forEach(System.out::println);
// a
// b
// c
// e
// g