次のコードでストリームまたはリストの最後の要素を取得するにはどうすればよいですか?
はどこ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()
andメソッドを提供しないことに異論はないと思います。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
、パフォーマンスが低下する可能性があるため、通常は望ましくない可能性があります。
ベストアンサー1
メソッドで最後の要素を取得することが可能ですストリーム::reduce次のリストには、一般的なケースの最小限の例が含まれています。
Stream<T> stream = ...; // sequential or parallel stream
Optional<T> last = stream.reduce((first, second) -> second);
この実装はすべての順序付けられたストリーム(以下から作成されたストリームを含む)リスト)。 のために順序なしストリームでは、明らかな理由により、どの要素が返されるかは指定されていません。
この実装は、一連そして並列ストリーム一見すると驚くかもしれませんが、残念ながらドキュメントには明示的に記載されていません。しかし、これはストリームの重要な機能であり、明確に説明します。
- メソッドのJavadocストリーム::reduce州は、"はない実行を強制される順次「。
- Javadocでは、「アキュムレータ関数は連想的な、非干渉的、ステートレス2つの値を組み合わせる関数"これは明らかにラムダ式の場合に当てはまります
(first, second) -> second
。 - Javadocの削減操作状態:「ストリームクラスには、複数の形式の一般的なリダクション操作があり、減らす()そして集める()[..]"そして「適切に構築されたreduce操作は本質的に並列化可能要素を処理するために使用される関数が連想的なそしてステートレス」
密接に関連するドキュメントコレクターさらに明確です:"それを確保するために一連そして並列実行生産する同等の結果コレクター関数は恒等式と連想性制約。」
元の質問に戻ります。次のコードは、変数の最後の要素への参照を格納しlast
、ストリームが空の場合は例外をスローします。複雑さはストリームの長さに比例します。
CArea last = data.careas
.stream()
.filter(c -> c.bbox.orientationHorizontal)
.reduce((first, second) -> second).get();