135
138

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

クラス java.util.Optionalのおさらいメモ

Last updated at Posted at 2018-03-21

概要

Java 1.8より導入されたjava.util.Optionalクラスのおさらいメモです。

環境

  • Windows 10 Professional
  • Oracle JDK 9.0.4
  • Oracle JDK 10.0.1

参考

[Optional<T> - Java 1.8] (https://docs.oracle.com/javase/jp/8/docs/api/java/util/Optional.html)

empty / of / ofNullable

いずれもstaticメソッドです。Optionalはpublicなコンストラクタを持たないのでOptionalオブジェクトを生成するにはこれらのメソッドを利用します。

empty

null値を持つOptionalオブジェクトを返します。

Optional<String> empty = Optional.empty();
empty.isPresent();
// false

empty.orElse("other");
// other

empty.get();
// java.util.NoSuchElementException: No value present

of

非null値を持つOptionalオブジェクトを返します。

String str = "nonNull";
Optional<String> nonNullString = Optional.of(str);
nonNullString.isPresent();
// true

nonNullString.get();
// result : nonNull

ofにnullなオブジェクトを渡すと例外がスローされます。

String str = null;
Optional.of(str);
//  java.lang.NullPointerException

ofNullable

nullかもしれない値(nullable)を持つOptionalオブジェクトを返します。

String str = null;
Optional<String> nullableString = Optional.ofNullable(str);
nullableString.isPresent();
// false

nullableString.orElse("other");
// other

get / isPresent

get

Optionalオブジェクトが保持する値を返します。保持する値がnullの場合はNoSuchElementExceptionがスローされます。

String str = "apple";
Optional<String> nullableString = Optional.ofNullable(str);

nullableString.get();
// apple
String str = null;
Optional<String> nullableString = Optional.ofNullable(str);

nullableString.get();
// java.util.NoSuchElementException: No value present

isPresent

Optionalオブジェクトが保持する値が非nullの場合はtrue、nullの場合はfalseを返します。

String str = "apple";
Optional<String> nullableString = Optional.ofNullable(str);

nullableString.isPresent();
// true
String str = null;
Optional<String> nullableString = Optional.ofNullable(str);

nullableString.isPresent();
// false

orElse / orElseGet / orElseThrow

orElse

Optionalオブジェクトが保持する値を返します。保持する値がnullの場合は指定した値を返します。(nullも可)

String str = "nonNull";
Optional<String> nullableString = Optional.ofNullable(str);

nullableString.orElse("other");
// nonNull
String str = null;
Optional<String> nullableString = Optional.ofNullable(str);

nullableString.orElse("other");
// other

nullableString.orElse(null);
// null

orElseGet

Optionalオブジェクトが保持する値を返します。保持する値がnullの場合は指定したSupplierの結果を返します。
Supplierがnullを返す場合はnullが返ります。

String str = "nonNull";
Optional<String> nullableString = Optional.ofNullable(str);

nullableString.orElseGet(() -> "other");
// nonNull
String str = null;
Optional<String> nullableString = Optional.ofNullable(str);

nullableString.orElseGet(() -> "other");
// other

nullableString.orElseGet(() -> null);
// null

orElseThrow

Optionalオブジェクトが保持する値を返します。保持する値がnullの場合は指定した例外がスローされます。

String str = null;
Optional<String> nullableString = Optional.ofNullable(str);

nullableString.orElseThrow(RuntimeException::new);
// java.lang.RuntimeException

ifPresent

Optionalオブジェクトが保持する値が非nullの場合、その値で引数に指定するConsumerの処理ブロックを実行します。
Optionalオブジェクトが保持する値がnullの場合は例外はスローされず、またなにも実行されません。

Optional<Employee> employee = Optional.ofNullable(new Employee(1L, "john"));
employee.ifPresent((e) -> {
    e.setName(e.getName().toUpperCase());
    System.out.println(e);
    // Employee{id=1, name='JOHN'}
});

filter / map / flatMap

filter

Optionalオブジェクトが保持する値が非nullの場合、その値で引数に指定するPredicateの処理ブロックを実行します。

Optional<String> nullableString = Optional.ofNullable("banana");

Optional<String> filtering = nullableString.filter(str -> str.length() > 5);
filtering.isPresent();
// true

filtering.orElse("other");
// banana

Optionalオブジェクトが保持する値がnullの場合、またはPredicateの処理ブロックがfalseを返す場合は空のOptionalが返ります。

Optional<String> nullableString = Optional.ofNullable("apple");
// Optional<String> nullableString = Optional.ofNullable(null);

Optional<String> filtering = nullableString.filter(str -> str.length() > 5);
filtering.isPresent();
// false

filtering.orElse("other");
// other

map

Optionalオブジェクトが保持する値が非nullの場合、その値で引数に指定するFunctionの処理ブロックを実行します。

Optional<String> nullableString = Optional.ofNullable("apple");
Optional<Integer> mapping = nullableString.map(str -> str.length());

mapping.isPresent();
// true

mapping.orElse(0);
// 5

Optionalオブジェクトが保持する値がnullの場合、またはFunctionの処理ブロックがnullを返す場合は空のOptionalが返ります。

Optional<String> nullableString = Optional.ofNullable(null);
Optional<Integer> mapping = nullableString.map(str -> str.length());

mapping.isPresent();
// false

mapping.orElse(0);
// 0

flatMap

Optionalオブジェクトが保持する値が非nullの場合、その値で引数に指定するFunctionの処理ブロックを実行します。
mapとの違いはFunctionがOptionalオブジェクトを返す点です。

mapに指定するFunctionはT型を取りU型を返します。

Function<? super T,? extends U> mapper

flatMapに指定するFunctionはT型を取りOptional型を返します。

Function<? super T,Optional<U>> mapper
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'}

Optionalオブジェクトが保持する値がnullの場合は空のOptionalを返します。

Optional<Long> optId = Optional.of(1L);
Optional<String> optName = Optional.ofNullable(null);

Optional<Employee> result = optId.flatMap(id -> optName.flatMap(name -> Optional.of(new Employee(id, name))));

result.isPresent();
// false

result.orElse(null);
// null

Optionalを返すFunctionをmapで使うと戻り値が期待しない型になってしまいます。

Optional<Optional<String>> nullableName = employee.map(emp -> Optional.ofNullable(emp.getName()));

[Java 9で追加されたAPI] (https://docs.oracle.com/javase/jp/9/docs/api/java/util/Optional.html)

ifPresentOrElse

ifPresentのバリエーションが増えました。
Optionalオブジェクトが保持する値がnullの場合、引数に指定するRunnableの処理ブロックが実行されます。

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

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

[Java 10で追加されたAPI] (https://docs.oracle.com/javase/jp/10/docs/api/java/util/Optional.html)

  • モジュール: java.base
  • パッケージ: java.util

orElseThrow

Optionalオブジェクトが保持する値を返します。保持する値がnullの場合はNoSuchElementExceptionをスローします。この動作はgetメソッドと同じです。
このため、Java 1.8からある同じメソッド名のorElseThrowのバリエーションの追加というよりも

java1.8_orElseThrowのシグネチャ
public <X extends Throwable> T orElseThrow​(Supplier<? extends X> exceptionSupplier)
    throws X extends Throwable

getメソッド名から曖昧さを取り除いたgetメソッドの代わりになるメソッドという感じです。

java1.8_getのシグネチャ
public T get()

orElseThrowはメソッド名から例外がスローされ得ることがわかります。

java10_orElseThrowのシグネチャ
public T orElseThrow()

[Java 11で追加されたAPI] ()

isEmpty

java11_isEmptyのシグネチャ
public boolean isEmpty()

値が存在しない場合にtrueを返します。

[Java 12で追加されたAPI] (https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/util/Optional.html)

追加されたAPIはありません。

[Java 13で追加されたAPI] (https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/Optional.html)

追加されたAPIはありません。

[Java 14で追加されたAPI] (https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/Optional.html)

追加されたAPIはありません。

その他のおさらいメモ

135
138
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
135
138

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?