Читаем Introducing Java 8 полностью

Alternatively, you can convert an existing Stream into a parallel Stream by using the parallel method: Stream expensiveInvoices = invoices.stream() .filter(inv -> inv.getAmount() > 10_000); List result = expensiveInvoices.parallel() .collect(Collectors.toList());

Nonetheless, it’s not always a good idea to use parallel streams. There are several factors you need to take into consideration to manage performance benefits: Splittability

The internal implementation of parallel streams relies on how simple it is to split the source data structure so different threads can work on different parts. Data structures such as arrays are easily splittable, but other data structures such as LinkedList or files offer poor splittability. Cost per element

The more expensive it is to calculate an element of the stream, the more benefit from parallelism you can get. Boxing

It is preferable to use primitives instead of objects if possible, as they have lower memory footprint and better cache locality. Size

A larger number of data elements can produce better results because the parallel setup cost will be amortized over the processing of many elements, and the parallel speedup will outweigh the setup cost. This also depends on the processing cost per element, just mentioned. Number of cores

Typically, the more cores available, the more parallelism you can get.

In practice, I advise that you benchmark and profile your code if you want a performance improvement. Java Microbenchmark Harness (JMH) is a popular framework maintained by Oracle that can help you with that. Without care, you could get poorer performance by simply switching to parallel streams.

Summary

Here are the most important takeaways from this chapter:

A stream is a sequence of elements from a source that supports aggregate operations.

There are two types of stream operations: intermediate and terminal operations.

Intermediate operations can be connected together to form a pipeline.

Intermediate operations include filter, map, distinct, and sorted.

Terminal operations process a stream pipeline to return a result.

Terminal operations include allMatch, collect, and forEach.

Collectors are recipes to accumulate the element of a stream into a summary result, including containers such as List and Map.

A stream pipeline can be executed in parallel.

There are various factors to consider when using parallel streams for enhanced performance, including splittability, cost per element, packing, data size, and number of cores available.

Acknowledgments

I would like to thank my parents for their continuous support. In addition, I would like to thank Alan Mycroft and Mario Fusco, with whom I wrote the book Java 8 in Action. Finally, I would also like to thank Richard Warburton, Stuart Marks, Trisha Gee, and the O’Reilly staff, who provided valuable reviews and suggestions.

About the Author

Raoul-Gabriel Urma is co-author of the bestselling book Java 8 in Action (Manning). He has worked as a software engineer for Oracle’s Java Platform Group, as well as for Google’s Python team, eBay, and Goldman Sachs. An instructor and frequent conference speaker, he’s currently completing a PhD in Computer Science at the University of Cambridge. He is also co-founder of Cambridge Coding Academy and a Fellow of the Royal Society of Arts. In addition, Raoul-Gabriel holds a MEng in Computer Science from Imperial College London and graduated with first-class honors, having won several prizes for technical innovation.

You can find out more about Raoul-Gabriel’s projects on his website and on Twitter @raoulUK.

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже