私はこのようなコードを持っています:
List<Listing> Listings = new ArrayList<>();
Listings.add(listing1);
Listings.add(listing2);
...
...
...
Listing listing= listings.stream()
.filter(l -> l.getVin() == 456)
.findFirst();
私の質問は、フィルター処理の時間の複雑さは何ですか? O(n)の場合、私の直感は、データ構造のようなHashSetに変換して、時間の複雑さがO(1)になるようにすることです。これをストリームで行うエレガントな方法はありますか? ?
O(n)
です。ストリームフィルタリングは内部的に反復を使用します。
次のようにマップに変換できます。
Map<Integer, Listing > mapOfVinToListing = listings.stream().collect(Collectors.toMap(Listing::getVin, Functions.identity()); // Assuming vin is unique per listing
mapOfVinToListing.get(456);// O(1)
ただし、その変換プロセスもO(n)です。したがって、これを一度だけ行う必要がある場合は、フィルターを使用します。同じリストを何度も照会する必要がある場合は、それをマップに変換するのが理にかなっています。
並列ストリームを使用することもできます。場合によってはパフォーマンスが向上することもありますが、それは正確な状況に大きく依存します。
最悪のケースはO(n)
ですが、Stream
は遅延であるため、値が以前に見つかった場合は、反復が停止します。一定の時間ルックアップが必要な場合は、常に、Map
に変換することをお勧めしますが、追加のスペースが必要になります。リストが巨大な場合、その側面を考慮する必要があります。実際、リストが小さい場合、タイムクリティカルなシステムで作業しているのでない限り、Map
とList
の違いはほとんど目立ちません。
filter
自体なし端末操作はオーバーヘッドがゼロになります-まったく何もしないためです。ストリームは端末操作によってのみ駆動されます-端末操作はなく、何も実行されません。
次に、filter
がすべての要素(潜在的にすべて)に対してiterateでなければならない場合がありますソースの(遅延)。したがって、フィルターの時間の複雑さは、ストリーミング元のソースによって異なります。あなたのケースではList
なので、O(n)
になります。
しかし、それは最悪の場合です。 filter
一般的にについては、根本的なソースに依存しているため、平均的なケースを予測することはできません。