Now, let's take a quick look at Java Stream. Basically, it is summarized by referring to JavaDoc of Stream, but the method Details such as the type variable of the internal argument are omitted, so refer to JavaDoc for details. Stream is a concept that appeared in Java 8 and can perform various processing on a collection of elements.
Stream operations can be divided into three stages: generate, intermediate, and terminate. Create and terminate operations can be performed only once per stream operation, but intermediate operations can be performed multiple times. Since the intermediate operation method is designed as a method that returns a Stream instance, it can be described by a method chain.
Result variable=Generate().Intermediate operation 1().Intermediate operation 2().Intermediate operation 3().Termination operation();
As the name implies, creation is the process for creating a Stream first.
However, Stream is an interface, and implementation classes are not provided in the form that is normally instantiated.
Collection provides stream ()
and parallel ()
methods to get the Stream of an element, but in many cases you just want to get the Stream without creating a Collection.
Therefore, you can create a Stream by using the following static methods provided by Stream.
Method | Contents | Element count |
---|---|---|
empty() | [] | Finite(Sky) |
of(Object e1, Object e2, Object e3, …) | [e1, e2, e3, …] | Finite(Same as argument) |
iterate(T s,Function f) | [s, f(s), f(f(s)), f(f(f(s))))…} | infinite |
generate(Function f) | [f(),f(),f(),f()…] | infinite |
concat(Stream s1, Stream s2) | [All elements of s1,All elements of s2] | By argument |
Type of element in T: Stream
You can also use the Builder obtained by Stream.builder ()
to generate a Stream.
Builder<Integer> builder = Stream.builder();
IntStream s = Stream.builder().add(1).add(2).add(3).build();
An infinite Stream generated by ʻiterate or
generatemust be interrupted using the intermediate operation
limit` described below (otherwise it will result in an infinite loop).
Intermediate operations operate on the elements in the Stream. The intermediate operation returns a new Stream instance after applying the operation to each element, so you can concatenate the intermediate operations in the method chain. Intermediate operations are roughly divided into characteristic change operations, stateless operations, and stateful operations.
The property change operation is an operation that changes the properties of the stream itself. The elements of the contents do not change. It is defined in its parent interface, BaseStream, not Stream.
Method | Contents |
---|---|
parallel() | Parallel stream |
sequential() | Sequential stream |
unordered() | Unordered stream |
onClose(Runnable r) | Registering a handler at close |
A stateless intermediate operation is one that is unaffected by other elements when you operate on one element. Therefore, it is suitable for parallel processing, and it is recommended that intermediate processing be as stateless as possible. Below, e and en (n: integer) are the elements in the stream.
Method | Contents |
---|---|
filter(Predicate p) | p(e)If is false, delete element e |
map(Function f) | [f(e1),f(e2),f(e3),…] |
flatMap(Function f) | [f(e1)All elements of the stream returned by, f(e2)All elements of the stream returned by,f(e3)All elements of the stream returned by,…] |
peek(Function f) | Execute f for each element, leaving the elements of the stream as they are |
Stateful intermediate operations are intermediate operations that are affected by other elements when you operate on one element.
Some operations may require all the elements in the Stream to return the result.
For example, the sorted
method that realizes sorting processing is an example.
Due to the influence of other factors, stateful intermediate operations require control over complex processing during parallel processing, which can be less efficient than sequential processing.
Method | Contents |
---|---|
distinct() | Remove duplicate elements in stream |
sorted() | Sorting in natural order for Comparable implementation classes |
sorted(Comparator c) | Sorting using Comparator |
limit(long maxSize) | Truncate to the length of up to maxSize elements |
skip(long n) | Discard the first n elements |
limit
is especially called a short-circuit intermediate operation.
A short-circuit operation is an operation that has the potential to turn an infinite stream into a finite stream.
It's easy to think that limit
and skip
are faster in parallel processing than distinct
and sorted
because they only look at the number of elements, but in an ordered stream, "n from the beginning". This is a costly operation because you need to find out.
If you want to prioritize parallel execution and you don't need to maintain the order, you can expect an improvement in efficiency by not ordering with ʻunordered`.
The termination operation processes the contents of the Stream at the time it is called and returns a non-Stream result (including no result (void)). After the termination operation is completed, the Stream that has been used until then becomes unusable, and if you try to use it again, an IllegalStateException will be thrown. Therefore, it is correct to handle Stream objects in the method chain rather than in variables.
Method | Return type | Contents |
---|---|---|
close() | void | Close the stream. All close handlers registered with onClose are called |
iterator() | Iterator | Returns an iterator |
spliterator() | Spliterator | Returns the splitter |
forEach(Consumer action) | void | Execute action for each element. Do not guarantee order |
forEachOrdered(Consumer action) | void | Same as forEach, but guarantees order |
toArray() | Object[] | Arrange |
reduce(T unit, BinaryOperator acc) | T | reduction(Convolution).. Returns the result of combining elements with the cumulative function acc for the identity element unit. |
collect(Supplier factory, BiConsumer acc, BiConsumer combiner) | Result container | Variable reduction. Variable container generated by factory(For example ArrayList)On the other hand, add an element with acc and combine each container with combiner. |
min() | Optional | Returns the smallest element. Special cases of reduction |
max() | Optional | Returns the largest element. Special cases of reduction |
count() | long | Returns the number of elements. Special cases of reduction |
anyMatch(Predicate p) | boolean | p(e)Returns true if even one evaluation result of is true |
allMatch(Predicate p) | boolean | p(e)Returns true if all evaluation results of |
noneMatch(Predicate p) | boolean | p(e)Returns true if all evaluation results are false |
findFirst() | Optional | Returns the first element. Returns arbitrary elements for unordered streams |
findAny() | Optional | Returns any element |
Type of element in T: Stream
Is it difficult to understand the reduction operations such as reduce
and collect
?
I will write more about this in another article in the near future. → Written.
There was also an unfamiliar name, Splitterator.
A splitterator is a parallel-processable (dividable) iterator.
A splitter is handled in the stream, and processing is performed on each divided splitter during parallel processing.
Recommended Posts