Java Stream:计数始终是计数吗?
它可能會出現(xiàn)明顯的是,在計數(shù)的元素Stream需要較長時間的多個元素中有Stream 。 但實際上,
Stream::count有時可以在一個操作中完成,無論您有多少元素。 閱讀本文并了解操作方法。
計數(shù)復(fù)雜度
Stream::count終端操作對a中的元素數(shù)進(jìn)行計數(shù)
Stream 。 運(yùn)算的復(fù)雜度通常為O(N) ,這意味著子運(yùn)算的數(shù)量與運(yùn)算中元素的數(shù)量成正比。
Stream 。
相反, List::size方法的復(fù)雜度為O(1) ,這意味著無論List中元素的數(shù)量如何, size()方法都會在恒定時間內(nèi)返回。 通過運(yùn)行以下JMH基準(zhǔn)可以觀察到這一點(diǎn):
@State (Scope.Benchmark) public class CountBenchmark { private List<Integer> list; @Param ({ "1" , "1000" , "1000000" }) private int size; @Setup public void setup() { list = IntStream.range( 0 , size) .boxed() .collect(toList()); } @Benchmark public long listSize() { return list.size(); } @Benchmark public long listStreamCount() { return list.stream().count(); } public static void main(String[] args) throws RunnerException { Options opt = new OptionsBuilder() .include(CountBenchmark. class .getSimpleName()) .mode(Mode.Throughput) .threads(Threads.MAX) .forks( 1 ) .warmupIterations( 5 ) .measurementIterations( 5 ) .build(); new Runner(opt).run(); } }這在我的筆記本電腦(2015年中的MacBook Pro,2.2 GHz Intel Core i7)上產(chǎn)生了以下輸出:
Benchmark (size) Mode Cnt Score Error Units CountBenchmark.listSize 1 thrpt 5 966658591.905 ± 175787129.100 ops/s CountBenchmark.listSize 1000 thrpt 5 862173760.015 ± 293958267.033 ops/s CountBenchmark.listSize 1000000 thrpt 5 879607621.737 ± 107212069.065 ops/s CountBenchmark.listStreamCount 1 thrpt 5 39570790.720 ± 3590270.059 ops/s CountBenchmark.listStreamCount 1000 thrpt 5 30383397.354 ± 10194137.917 ops/s CountBenchmark.listStreamCount 1000000 thrpt 5 398.959 ± 170.737 ops/s <br>可以看出, List::size的吞吐量在很大程度上與List中元素的數(shù)量無關(guān),而Stream::count的吞吐量隨著元素數(shù)量的增加而Swift下降。 但是,實際上所有Stream實現(xiàn)本身總是如此嗎?
源感知流
一些流實現(xiàn)實際上知道它們的源,并且可以采用適當(dāng)?shù)目旖莘绞讲⒘鞑僮骱喜⒌搅髟幢旧碇小?這可以極大地提高性能,尤其是對于大型流。 Speedment ORM工具允許將數(shù)據(jù)庫視為Stream對象,并且這些流可以優(yōu)化許多流操作,如Stream::count操作,如下面的基準(zhǔn)所示。 我已使用開源Sakila示例數(shù)據(jù)庫作為數(shù)據(jù)輸入。 Sakila數(shù)據(jù)庫包含有關(guān)租賃電影,藝術(shù)家等的全部信息。
@State (Scope.Benchmark) public class SpeedmentCountBenchmark { private Speedment app; RentalManager rentals; private RentalManager rentals; private FilmManager films; @Setup public void setup() { app = new SakilaApplicationBuilder() .withBundle(DataStoreBundle. class ) .withLogging(ApplicationBuilder.LogType.STREAM) .withPassword(ExampleUtil.DEFAULT_PASSWORD) .build(); app.get(DataStoreComponent. class ).ifPresent(DataStoreComponent::load); rentals = app.getOrThrow(RentalManager. class ); films = app.getOrThrow(FilmManager. class ); } @TearDown public void tearDown() { app.close(); } @Benchmark public long rentalsCount() { return rentals.stream().count(); } @Benchmark public long filmsCount() { return films.stream().count(); } public static void main(String[] args) throws RunnerException { Options opt = new OptionsBuilder() .include(SpeedmentCountBenchmark. class .getSimpleName()) .mode(Mode.Throughput) .threads(Threads.MAX) .forks( 1 ) .warmupIterations( 5 ) .measurementIterations( 5 ) .build(); new Runner(opt).run(); } }運(yùn)行時,將產(chǎn)生以下輸出:
Benchmark Mode Cnt Score Error Units SpeedmentCountBenchmark.filmsCount thrpt 5 71037544.648 ± 75915974.254 ops/s SpeedmentCountBenchmark.rentalsCount thrpt 5 69750012.675 ± 37961414.355 ops/s <br> <br> “租賃”表包含10,000行,而“電影”表僅包含1,000行。 但是,它們的Stream::count操作幾乎在同一時間完成。 即使一個表包含一萬億行,它仍然會在相同的經(jīng)過時間內(nèi)對元素進(jìn)行計數(shù)。 就這樣
Stream::count實現(xiàn)的復(fù)雜度為O(1)而不是
O(N)
注意:上面的基準(zhǔn)測試是通過Speedment的“ DataStore” JVM虛擬機(jī)內(nèi)存加速來運(yùn)行的。 如果直接對數(shù)據(jù)庫沒有加速運(yùn)行,則響應(yīng)時間將取決于基礎(chǔ)數(shù)據(jù)庫執(zhí)行“SELECT count(*) FROM film”查詢的能力。
摘要
可以創(chuàng)建在單個操作中對元素進(jìn)行計數(shù)的Stream實現(xiàn),而不是對流中的每個元素進(jìn)行計數(shù)。 這可以顯著提高性能,尤其是對于具有許多元素的流。
資源資源
Speedment Stream ORM初始化程序: https ://www.speedment.com/initializer/
Sakila: https ://dev.mysql.com/doc/index-other.html或https://hub.docker.com/r/restsql/mysql-sakila
翻譯自: https://www.javacodegeeks.com/2019/04/java-stream-count-always-count.html
總結(jié)
以上是生活随笔為你收集整理的Java Stream:计数始终是计数吗?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 备案办税人员信息填谁(备案办)
- 下一篇: 金太阳安卓版(金太阳安卓)