Java Language
オプション
サーチ…
前書き
Optional
は、null以外の値を含む場合と含まない場合があるコンテナオブジェクトです。値が存在する場合、 isPresent()
はtrue
を返し、 get()
は値を返します。
含まれている値の存在に依存するさらなる方法は、以下のような、提供さorElse()
値が存在しない場合は、デフォルト値を返し、およびifPresent()
値が存在する場合、コードのブロックを実行します。
構文
- Optional.empty()//空のOptionalインスタンスを作成します。
- Optional.of(value)//指定された非null値を持つOptionalを返します。渡された値がnullの場合、NullPointerExceptionがスローされます。
- Optional.ofNullable(value)// nullの可能性のある指定された値を持つOptionalを返します。
Optionalが空の場合、デフォルト値を返します。
NoSuchElementException
スローする可能性があるので、単にOptional.get()
使用しないでください。 Optional.orElse(T)
およびOptional.orElseGet(Supplier<? extends T>)
メソッドは、Optionalが空の場合にデフォルト値を提供する方法を提供します。
String value = "something";
return Optional.ofNullable(value).orElse("defaultValue");
// returns "something"
return Optional.ofNullable(value).orElseGet(() -> getDefaultValue());
// returns "something" (never calls the getDefaultValue() method)
String value = null;
return Optional.ofNullable(value).orElse("defaultValue");
// returns "defaultValue"
return Optional.ofNullable(value).orElseGet(() -> getDefaultValue());
// calls getDefaultValue() and returns its results
orElse
とorElseGet
の重要な違いは、オプションが空の場合でも前者に提供された引数が評価されている間は後者のみが評価されることです。したがって、 orElse
は定数にのみ使用し、あらゆる種類の計算に基づいて値を供給することはできません。
地図
「 Optional
のmap()
メソッドを使用して、明示的なnull
チェックを行わずにnull
なる可能性のある値を処理します。
( map()
およびfilter()
操作は、 端末操作時にのみ評価されるStream対応とは異なり、直ちに評価されます)。
構文:
public <U> Optional<U> map(Function<? super T,? extends U> mapper)
コード例:
String value = null;
return Optional.ofNullable(value).map(String::toUpperCase).orElse("NONE");
// returns "NONE"
String value = "something";
return Optional.ofNullable(value).map(String::toUpperCase).orElse("NONE");
// returns "SOMETHING"
マッピング関数がnullを返すときにOptional.map()が空のオプションを返すので、いくつかのmap()操作をnull安全な逆参照の形式として連結できます。これは、 Nullセーフチェーンとも呼ばれます 。
次の例を考えてみましょう。
String value = foo.getBar().getBaz().toString();
getBar
、 getBaz
、およびtoString
いずれかが、 NullPointerException
スローする可能性があります。
Optional
を使用してtoString()
から値を取得する別の方法は次のとおりです。
String value = Optional.ofNullable(foo)
.map(Foo::getBar)
.map(Bar::getBaz)
.map(Baz::toString)
.orElse("");
いずれかのマッピング関数がnullを返した場合、空の文字列を返します。
以下は別の例ですが、少し異なります。いずれのマッピング関数もnullを返さなかった場合にのみ、値を出力します。
Optional.ofNullable(foo)
.map(Foo::getBar)
.map(Bar::getBaz)
.map(Baz::toString)
.ifPresent(System.out::println);
値がない場合は例外をスローする
含まれている値を取得するには、 Optional
のorElseThrow()
メソッドを使用します。設定されていない場合は、例外をスローします。これは、任意の例外型を許可する点を除いて、 get()
呼び出しと同様です。このメソッドは、スローされる例外を返さなければならないサプライヤを受け取ります。
最初の例では、このメソッドは単に含まれる値を返します。
Optional optional = Optional.of("something");
return optional.orElseThrow(IllegalArgumentException::new);
// returns "something" string
2番目の例では、値が設定されていないため、このメソッドは例外をスローします。
Optional optional = Optional.empty();
return optional.orElseThrow(IllegalArgumentException::new);
// throws IllegalArgumentException
メッセージが必要な例外をスローする場合は、ラムダ構文を使用することもできます。
optional.orElseThrow(() -> new IllegalArgumentException("Illegal"));
フィルタ
filter()
は、述語と一致する場合にのみ値を表示することを示すために使用されます。
それをif (!somePredicate(x)) { x = null; }
。
コード例:
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
プリミティブ型のオプションのコンテナの使用
OptionalDouble
、 OptionalInt
とOptionalLong
などの作業Optional
が、具体的にプリミティブ型をラップするように設計されています。
OptionalInt presentInt = OptionalInt.of(value);
OptionalInt absentInt = OptionalInt.empty();
数値型には値があるので、nullの特別な処理はありません。空のコンテナは以下を使ってチェックできます。
presentInt.isPresent(); // Is true.
absentInt.isPresent(); // Is false.
同様に、価値管理を支援するために簡略表記が存在します。
// 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();
値が存在する場合のみコードを実行する
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.
サプライヤを使用して遅延してデフォルト値を提供する
通常の orElse
メソッドはObject
とるため、 Supplier
を提供するオプション( orElseGet
メソッド)がある理由が不思議に思うかもしれません。
検討してください:
String value = "something";
return Optional.ofNullable(value)
.orElse(getValueThatIsHardToCalculate()); // returns "something"
オプションが空ではないため、結果が使用されていなくてもgetValueThatIsHardToCalculate()
呼び出します。
このペナルティを回避するには、サプライヤーに供給してください:
String value = "something";
return Optional.ofNullable(value)
.orElseGet(() -> getValueThatIsHardToCalculate()); // returns "something"
このように、 getValueThatIsHardToCalculate()
は、 Optional
が空の場合にのみ呼び出されます。
フラットマップ
flatMap
はmap
似ていmap
。この違いは、javadocによって次のように記述されます。
このメソッドは
map(Function)
と似ていmap(Function)
が、指定されたマッパーはresultがすでにOptional
で、呼び出された場合、flatMap
は追加のOptional
ラップしません。
あなたが返すメソッド呼び出し連鎖つまり、 Optional
使用して、 Optional.flatMap
ネストされた作成回避Optionals
。
たとえば、次のクラスがあるとします。
public class Foo {
Optional<Bar> getBar(){
return Optional.of(new Bar());
}
}
public class Bar {
}
Optional.map
を使用すると、ネストされたOptional
が取得されます。 ie Optional<Optional<Bar>>
。
Optional<Optional<Bar>> nestedOptionalBar =
Optional.of(new Foo())
.map(Foo::getBar);
ただし、 Optional.flatMap
を使用すると、単純なOptional
が取得されます。すなわち、 Optional<Bar>
。
Optional<Bar> optionalBar =
Optional.of(new Foo())
.flatMap(Foo::getBar);