Operation types and use of peek in Java 8 Stream

Introduction to the

Java 8 Stream as a stream operation has two types of operations, intermediate operations and termination operations. What’s the difference between the two?

Let’s look at an example of peek:

Stream<String> stream = Stream.of("one"."two"."three"."four");
        stream.peek(System.out::println);
Copy the code

In the example above, we intended to print the value of Stream, but we didn’t actually print anything.

Why is that?

Intermediate operations and termination operations

A Java 8 Stream consists of three parts. Data source, zero or one or more intermediate operations, one or zero termination operations.

An intermediate operation is a process of data. Note that an intermediate operation is lazy and does not start immediately.

The termination operation is the start operation of the stream, and the stream will not actually start executing until the termination operation is added.

So, problem solved, peek is an intermediate operation, so the above example has no output.

peek

Peek is mainly used for debugging purposes.

Let’s look at the debug usage:

Stream.of("one"."two"."three"."four").filter(e -> e.length() > 3)
                .peek(e -> System.out.println("Filtered value: " + e))
                .map(String::toUpperCase)
                .peek(e -> System.out.println("Mapped value: " + e))
                .collect(Collectors.toList());
Copy the code

The above example output:

Filtered value: three
Mapped value: THREE
Filtered value: four
Mapped value: FOUR
Copy the code

In the above example we printed the intermediate value of stream to facilitate our debugging.

Why only debug? Let’s look at another example:

Stream.of("one"."two"."three"."four").peek(u -> u.toUpperCase())
                .forEach(System.out::println);
Copy the code

In the example above we used peek to convert Element to upper Case. Then output:

one
two
three
four
Copy the code

You can see that the elements in the stream are not converted to uppercase.

Here’s another map comparison:

Stream.of("one"."two"."three"."four").map(u -> u.toUpperCase())
                .forEach(System.out::println);
Copy the code

Output:

ONE
TWO
THREE
FOUR
Copy the code

You can see that the map actually transforms the elements.

There are exceptions for peek, of course. What if we had an object in the Stream?

    @Data
    @AllArgsConstructor
    static class User{
        private String name;
    }
Copy the code
        List<User> userList=Stream.of(new User("a"),new User("b"),new User("c")).peek(u->u.setName("kkk")).collect(Collectors.toList());
        log.info("{}",userList);
Copy the code

Output result:

10:25:59.784 [main] infocom.flydean.peekUsage - [peekusage. User(name= KKK), peekusage. User(name= KKK), PeekUsage.User(name=kkk)]Copy the code

We see that the actual result is changed for objects.

Why the difference between Peek and Map?

Let’s look at the definitions of PEEK and Map:

Stream<T> peek(Consumer<? super T> action)
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Copy the code

Peek receives a Consumer, and Map receives a Function.

Consumer does not return a value. It does something to the elements in the Stream, but the data is not returned to the Stream, so the elements in the Stream remain the same.

Function, on the other hand, returns a value, which means that all operations on elements of the Stream are returned to the Stream as new results.

This is why peek String does not change while Peek Object sends changes.

conclusion

In this article, we looked at the two types of operations on STREAM and summarized the use of PEEK. I hope you get the hang of it.

Examples of this article github.com/ddean2009/l…

Welcome to pay attention to my public number: procedures those things, more wonderful waiting for you! For more, visit www.flydean.com