This tutorial looks at Java 8 Stream API’s
peek() method in depth. It starts with explaining the
Stream.peek() method’s definition and intended use.This is followed by understanding the method’s intermediate and non-interfering nature. Lastly, we will look at the Java 8 code showing a working example of
Stream.peek() and its explanation.
Let us start with looking at the signature of
Stream.peak() method –
Stream<T> peek(Consumer<? super T> action);
action is the only parameter and is an instance of a Consumer Functional InterfaceClick to read detailed tutorial on Consumer Functional Interfaces
– The method returns back a
Stream<T> as output which consists of the same elements as in
Stream<T> instance it had been invoked on, after applying the consuming
action, passed as input, on each of them.
Stream.peek() method’s objective is literally to peek at the contents of the
Stream. I.e. it has been put as a part of Streams API to provide a method for debugging the Stream elements as they flow from one pipelined operationClick to read tutorial on Pipelines in Computing to another. The
stream.peek() method applies the
Consumer<T> function’s logic, which is its only input, to each element of the Stream. The
Consumer logic can be implemented as per the specific debugging requirements requirements to debug/log/print the elements as they stream through the
But then, one might ask the question, how is
Stream.peek() method different from any other method of the Stream API which can consume the values in the Stream? The answer is that this is the only method which allows you to consume(print/log/whatever way you want to check the contents) the elements of a Stream as an intermediate operationClick to Read Tutorial explaining intermediate & terminal Stream operations. In addition,
Stream.peek() also provides the guarantee of non-interference. Let us now look at what we mean by
peek() method having these two advantages.
Stream.peek() as a non-interfering intermediate operation
Stream.peek() is an intermediate operation, i.e. it does not end the processing of the stream. Other methods which allow using a
Consumer instance to act on the elements of a stream, such as the forEach() methodRead tutorial on forEach() method, or the
collect() method among others, are all terminal operationsClick to Read Tutorial explaining intermediate & terminal Stream operations. I.e. once you see the contents, by printing or logging them, your stream’s processing ends.
Stream.peek() thus provides you the unique capability to consume a stream without ending the pipeline of operations when acting on the stream contents, by virtue of it being an intermediate operation.
Stream.peek() is a non-interfering
Stream operation. Non-interfering methods are those which guarantee that they will not modify the
Stream’s data source during their execution. Non-interfering nature is required in multi-threaded environments where stream operations can be executed in parallel or concurrently. Concurrent execution makes it necessary to keep the stream’s data source unmodified until the terminal operation.
Let us now take a look at an example showing Stream.peek() method’s usage –
PeekingInStreamsclass first creates an infinite stream using Stream.iterate()Click to read tutorial on Creating Infinite Streams using iterate() method method by specifying logic to generate consecutive integers starting from 1.
iterate()method is pipelined to the
peek()method which uses a lambda expressionRead Java 8 Lambda Expressions Tutorial equivalent of the Consumer interface –
(n -> System.out.println("number generated: - " + n)). This expressions simply prints the generated number.
- Next, a filter is applied to the Stream using the Stream.filter()Click to read how Filtering and Slicing with Java 8 Streams works method. The filter’s predicateClick to read tutorial on Java 8 Predicates only allows even numbers to pass through using the logic
peek()is again pipelined next, and it prints the numbers obtained from the filter indicating which numbers passed the even number filter.
Stream.limit()method is used to restrict the infinite stream to
- Lastly, to end the pipeline of operations,
Stream.count()method is invoked which is a terminal operation.
- As expected, the output shows that only even numbers – 2,4,6,8,10 pass through the filter.
In the above Java 8
Stream.peek() method tutorial we understood the working of the method by going through its definition, charecteristics and usage. Lastly, we saw a Java 8 code example showing
Stream.peek() method’s usage practically.