[解決済み] ワンライナーでストリーム/リストの最後の要素を取得する
質問
以下のコードで、ストリームやリストの最後の要素を取得するにはどうしたらよいでしょうか。
ここで
data.careas
は
List<CArea>
:
CArea first = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal).findFirst().get();
CArea last = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal)
.collect(Collectors.toList()).; //how to?
最初の要素を取得するとわかるように、ある特定の
filter
で、最初の要素を取得することは難しくありません。
しかし、ワンライナーで最後の要素を取得するのは本当に大変なことです。
-
から直接取得することはできないようです。
Stream
. (それは有限のストリームに対してのみ意味をなすでしょう) -
のようなものも取得できないようです。
first()
とlast()
からList
インターフェイスに変換する必要があり、これは本当に面倒です。
を提供しないことに対する反論は見当たりません。
first()
と
last()
メソッドを
List
インターフェイスにある要素は順番に並べられ、さらにサイズもわかっています。
しかし、元の答えのように の最後の要素を得るにはどうしたらよいでしょうか?
Stream
?
個人的には、これが一番近いかな。
int lastIndex = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal)
.mapToInt(c -> data.careas.indexOf(c)).max().getAsInt();
CArea last = data.careas.get(lastIndex);
ただし、この場合
indexOf
を使うことになりますが、これはパフォーマンスを低下させる可能性があるので、一般的には好ましくないでしょう。
どのように解決するのですか?
最後の要素を取得するためのメソッドとして ストリーム::reduce . 次のリストには、一般的な場合の最小限の例が含まれています。
Stream<T> stream = ...; // sequential or parallel stream
Optional<T> last = stream.reduce((first, second) -> second);
この実装は、すべての 順序付きストリーム (から作成されたストリームを含む)。 リスト ). については 順不同 ストリームでは、明白な理由により、どの要素が返されるかは指定されていません。
この実装は シーケンシャル そして 並列ストリーム . これは一見すると驚くべきことかもしれませんし、残念ながらドキュメントには明示的に書かれていません。しかし、これはストリームの重要な機能であり、私はそれを明確にするよう努めます。
- メソッドの Javadoc は ストリーム::リデュース には、以下のように書かれています。 です。 ではない を実行する制約があります。 シーケンシャル "です。 .
-
また、Javadocでは
"アキュムレータ関数は必ず
連想
,
非干渉型
,
ステートレス
2つの値を組み合わせるための関数"
これは明らかにラムダ式の場合です。
(first, second) -> second
. - の Javadoc は 削減操作 の状態になります。 "ストリームクラスは、一般的な還元操作の複数の形式を持ち、これを reduce() と collect() [...]" と "適切に構築されたreduceオペレーションは 本質的に並列化可能であり である限り、要素を処理するために使用される関数(複数可)が 連想的 であり ステートレス ."
密接に関連する コレクター のドキュメントはさらに明確です。 を確実にするために シーケンシャル と 並列実行 を生み出す 同等の結果 の場合、コレクター関数は ID と 連想性 制約."を満たす必要があります。
元の質問に戻ります。次のコードは、最後の要素への参照を変数に格納します。
last
に格納し、ストリームが空であれば例外を投げる。複雑さはストリームの長さに比例します。
CArea last = data.careas
.stream()
.filter(c -> c.bbox.orientationHorizontal)
.reduce((first, second) -> second).get();
関連
-
[解決済み] リストから要素を削除しようとすると、UnsupportedOperationExceptionが発生するのはなぜですか?
-
eclipseにプロジェクトをインポートした後、Editorにmain typeが含まれない問題
-
javax.net.ssl.SSLException: 読み取りエラー: ssl=0xdeae5100: システムコール中の I/O エラー、接続 res
-
[解決済み] ストリームから条件に合う最初の要素を取得する
-
[解決済み] リストの最後の要素を取得する方法
-
[解決済み] リストの要素数を取得する方法
-
[解決済み] インデックスを指定してリストから要素を削除する方法
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] リストの要素を値で削除する簡単な方法はありますか?
-
[解決済み】Javaストリームを1つの要素だけにフィルタリングする
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
IllegalArgumentException この例外を解決する方法
-
final, finally, finalizeの違いについて話してください。
-
SpringBootApplication を型解決できない。
-
Eclipseプロンプトを実行する java仮想マシンを使用しない
-
エラーの解決方法 jarfile XXX.jarにアクセスできません。
-
Spring BootのテストメソッドFailed to load ApplicationContextの問題を解決する
-
マスキング このリソースにアクセスするには、完全な認証が必要です。
-
javaコンパイル時のエラー:不正な文字 '\ufeff' に対する解決策です。
-
SocketTimeoutExceptionです。読み込みがタイムアウトしました
-
[解決済み] Java 8 ストリーム逆順