History of the Question:
Stream API was added in Java 8 to facilitate functional programming and parallel processing of collections. It provides a convenient way to describe chains of operations on data using lambda expressions.
The Problem:
Without Stream API, one had to write cumbersome imperative code for filtering, sorting, and aggregating collections. There was a potential for errors, maintenance complexity, and inefficiency when trying to add parallelism manually.
The Solution:
Stream API allows constructing a pipeline of intermediate and terminal operations. Streams are lazy, process data sequentially or in parallel, and make the code more compact and expressive.
Example of collection processing:
List<String> names = Arrays.asList("Anna", "Ivan", "Petr", "Eva"); names.stream() .filter(s -> s.length() > 3) .map(String::toUpperCase) .sorted() .forEach(System.out::println);
Key features:
parallelStream()), but thread-safety of collections and functions should be consideredCan you reuse the same Stream after it is closed?
No, attempting to reuse a closed Stream throws an IllegalStateException. A stream is one-time use.
Does changing the original collection after creating a Stream affect it?
Yes, if the collection is modified after the Stream is created but before the terminal operation, ConcurrentModificationException may occur.
Can external mutable variables be used within Stream operations?
It is not recommended, as it can lead to unexpected errors in a parallel stream. It is better to avoid mutable side-effects in the Stream pipeline.
.parallelStream() to non-thread-safe collectionsA programmer invokes a method through Stream that modifies an external list — this works in sequential execution, but in parallel it causes disruption of the data structure.
Pros:
Cons:
The entire pipeline is built cleanly: operations have no side effects, only immutable collections are used, and the final result is collected through a collector.
Pros:
Cons: