[解決済み】Java 8のOptionalをStream::flatMapで使用する。
質問
新しいJava 8のストリームフレームワークとその仲間たちは、非常に簡潔なJavaコードを作ってくれますが、一見単純に見える状況でも、簡潔に行うには厄介なことに遭遇しています。
を考えてみましょう。
List<Thing> things
とメソッド
Optional<Other> resolve(Thing thing)
. をマッピングしたいのですが
Thing
を
Optional<Other>
を取得し、最初の
Other
. 明らかな解決策は
things.stream().flatMap(this::resolve).findFirst()
しかし
flatMap
はストリームを返すことが必要であり
Optional
には
stream()
メソッド(あるいは
Collection
に変換する、あるいはそれを表示するメソッドを提供する。
Collection
).
私が思いつくのは、これくらいです。
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
しかし、ごく一般的なケースと思われるのに、やけに長文に感じます。どなたか良いアイデアをお持ちの方はいらっしゃいますか?
解決方法は?
ジャバ9
Optional.stream
が JDK 9 で追加されました。 これにより、ヘルパーメソッドを使わずに、以下のようなことができるようになりました。
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(Optional::stream)
.findFirst();
ジャバ8
そう、これは API の小さな穴だった。
Optional<T>
をゼロまたは1の長さの
Stream<T>
. こんなことができるんですね。
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
.findFirst();
三項演算子を
flatMap
はちょっと面倒なので、ちょっとしたヘルパー関数を書いておくといいかもしれませんね。
/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
if (opt.isPresent())
return Stream.of(opt.get());
else
return Stream.empty();
}
Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();
をインライン化しました。
resolve()
の代わりに、別の
map()
という操作になりますが、これは好みの問題です。
関連
-
[解決済み] 警告: コンテキスト初期化中に例外が発生 - 更新の試みはキャンセルされました。
-
[解決済み] 文字列の長さに応じて文字列をトリミングする
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaでNullPointerExceptionを回避する方法
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] JavaでArrayListではなくLinkedListを使用するのはいつですか?
-
[解決済み] Java 8 List<V> を Map<K, V> に変換する。
-
[解決済み] Java 8 StreamをArrayに変換する方法は?
-
[解決済み] Java 8のmap()メソッドとflatMap()メソッドの違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Jdbctemplate の文字列に対するクエリです。EmptyResultDataAccessException: 不正な結果サイズ:期待値1、実際0
-
[解決済み] getContentPane()は具体的に何をするのですか?
-
[解決済み] ボタンでTextFieldをクリアする(Java)
-
[解決済み] このフォーマット(Tue Jul 13 00:00:00 CEST 2010)の日付をJavaの日付に変換する方法(文字列はalfrescoのプロパティに由来しています)
-
[解決済み] XX:MaxDirectMemorySizeの既定値
-
[解決済み] 親から継承したメソッドの可視性を下げることができない [重複]。
-
[解決済み] ORA-01654: インデックスを拡張できません。
-
[解決済み] 午前0時からの時間を秒単位で取得する方法
-
[解決済み] アクティビティに割り当てられない
-
[解決済み] 文字列が一意な文字であるかどうかを判定する