前々回から、Java SE 9の言語仕様や標準ライブラリの新機能を紹介しています。前回はjava.baseモジュールの中から、java.utilパッケージの新機能を解説しました。今回は、java.utilパッケージにも関連が深い「Project Lambda」の新機能について紹介します。
Java SE 8のProject Lambdaでは、言語仕様の変更としてラムダ式、新しいライブラリとしてストリームが導入されました。前々回に紹介したように、Java SE 9ではラムダ式に関する言語仕様の変更はありません。その一方で、ストリームはさらに使いやすくなるように、メソッドの追加などが行われています。
ストリームにファクトリーメソッドが追加
ストリームには、以下の2つのファクトリーメソッドが追加されました。
- ofNullable
- iterate
ofNullableメソッドはStreamインタフェースだけ、iterateメソッドはすべてのストリームで使用できます。iterateメソッドはJava SE 8からあったはずと思われる方もいらっしゃるかもしれません。それは正しい認識です。Java SE 9ではiterateメソッドのオーバーロードが追加されたのです。
ofNullableメソッド
では、ofNullableメソッドから解説しましょう。ofNullableメソッドは引数を1つだけ取るファクトリーメソッドです。既存のofメソッドは可変長引数ですが、ofNullableメソッドは可変長引数ではありません。また、メソッド名から分かるように引数がnullであることも許容します。
しかし、なぜこのようなファクトリーメソッドが必要なのでしょうか。その答えはストリームのパイプライン処理中に使用することにあります。
例えば、nullが返るかもしれないgetValueメソッドを中間操作に使用することを考えてみます。もし、nullが返ってきた時は、それを無視して次の要素に進むようにするとしましょう。
Java SE 8までであれば、リスト1のように記述できます。
リスト1●nullを返すかもしれないメソッドを使用する例(Java SE 8)。終端処理は省略。
List<String> contents = ...;
contents.stream()
.flatMap(c -> {
String value = getValue(c);
return value != null? Stream.of(value): Stream.empty();
})
...;
mapメソッドではなくflatMapメソッドを使用しているのは、mapメソッドだとgetValueメソッドの返り値がnullの場合、次の処理にnullが渡ってしまうからです。flatMapメソッドを使用し、nullの場合には空のストリームを返すようにすれば、次の処理にnullが渡ることはありません。しかし、このような場合、Java SE 8ではnullかどうかの三項演算子もしくはif文が必要になってしまいます。
このような場合に有効なのがofNullableメソッドです。ofNullableメソッドを使用してリスト1を書きかえたのが、リスト2です。
リスト2●nullを返すかもしれないメソッドを使用する例(Java SE 9)
List<String> contents = ...;
contents.stream()
.flatMap(c -> Stream.ofNullable(getValue(c)))
...;
赤字で示したように、ofNullableメソッドを使用すると、条件文を削除できるのです。