次のコードでストリームまたはリストの最後の要素を取得するにはどうすればよいですか?
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
から直接取得できないようです。 (有限ストリームに対してのみ意味があります)List
インターフェースからfirst()
やlast()
のようなものを取得できないようです。これは本当に苦痛です。List
インターフェイスでfirst()
およびlast()
メソッドを提供しないという引数はありません。そこにある要素は順序付けられており、さらにサイズがわかっています。
しかし、元の答えに従って:有限の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
を使用する必要があります。これは、パフォーマンスを低下させる可能性があるため、通常は望ましくありません。
メソッド Stream :: reduce で最後の要素を取得することができます。次のリストには、一般的な場合の最小限の例が含まれています。
Stream<T> stream = ...; // sequential or parallel stream
Optional<T> last = stream.reduce((first, second) -> second);
この実装は、すべての 順序付きストリーム ( Lists から作成されたストリームを含む)で機能します。 nordered ストリームの場合、明らかな理由により、どの要素が返されるかは指定されていません。
実装は、sequentialとparallelストリームの両方で機能します。それは一見すると驚くかもしれませんが、残念ながらドキュメントには明示的に記載されていません。ただし、これはストリームの重要な機能であり、明確にしようとしています。
(first, second) -> second
。密接に関連する Collectors のドキュメントはさらに明確です: "sequentialおよび並列実行は同等の結果を生成し、コレクター関数はアイデンティティを満たさなければならず、 結合性 制約。 "
元の質問に戻ります。次のコードは、変数last
の最後の要素への参照を格納し、ストリームが空の場合に例外をスローします。複雑さは、ストリームの長さにおいて線形です。
CArea last = data.careas
.stream()
.filter(c -> c.bbox.orientationHorizontal)
.reduce((first, second) -> second).get();
コレクション(またはより一般的なIterable)がある場合、Google Guavaの
Iterables.getLast(myIterable)
便利なワンライナーとして。
1つのライナー(ストリームの必要なし;):
Object lastElement = list.get(list.size()-1);
グアバには、このケース専用の方法があります。
Stream<T> stream = ...;
Optional<T> lastItem = Streams.findLast(stream);
stream.reduce((a, b) -> b)
と同等ですが、作成者はパフォーマンスがはるかに優れていると主張しています。
ドキュメント から:
このメソッドの実行時間はO(log n)とO(n)の間であり、効率的に分割可能なストリームでパフォーマンスが向上します。
ストリームが順序付けられていない場合、このメソッドはfindAny()
のように動作することに注意してください。