Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The use of .peek() in java 8 streams

I am using .peek() in my stream but it is frowned upon, sadly I can't find a solution.

Simplified version:

static boolean fooAddTester(int size) {
    Foo foo = new foo(); //data structure

    return IntStream.range(0, size).
            .peek(i -> synchronized(r){foo.add(i)})
            .allMatch(e -> foo.isLegal());
}

what I need to do is to iterate over the IntStream and to check after every insert if the foo data structure is legal. This is logically equivalent to:

static boolean fooAddTester(int size) {
    Foo foo = new foo(); //data structure

    for(int i=0; i<size; i++){
        foo.add(i);
        if(!foo.isLegal())
            return false;
    return true;
}

However it is more complex and I'm trying to use streams to simplify and learn.

A way to do the same without using .peek() is this: which does work - but I'm just "moving" the problem to .allMatch():

return IntStream.range(0, size).
            .allMatch(i -> {
                 synchronized(r){foo.add(i)};
                 foo.isLegal();
             )};

My problem is very similar to this question, the diffrence is that I am checking every time so the solutions aren't working.

So my questions are:

  • Is .peek() really only to debugging or can I use it in this manner?
  • Is there any better solution?
  • Should I use my second solution?

I'm looking for a correct solution, not a working solution, all of those codes are already working.

like image 430
Adam Shem-Ur Avatar asked Jun 26 '17 11:06

Adam Shem-Ur


People also ask

What is the use of PEEK in Java stream?

This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline. Since Java 9, if the number of elements is known in advance and unchanged in the stream, the . peek () statement will not be executed due to performance optimization.

What is difference between Peek and foreach?

(1): using stream. foreach, you can also change the internal property value of each item in the list, etc., but you need to perform "secondary flow processing" to get the smallest item in the list (filter according to age). (2): stream. peek can get the smallest item directly compared with stream.

What is the use of streams in Java 8?

Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.

Which method is used for debugging in stream API?

peek() method is very useful for debugging and understating the stream-related code in Java.


1 Answers

the documentation of Stream#peek has mentioned as below, and mainly is not absolutely:

This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline

@Holger has answered this question absolutely:

the most useful thing you can do with peek is to find out whether a stream element has been processed.

and some side-effects he has also pointed it out in his answer, the peek operation depends on which terminal operation was invoked. so when using peek internally you should be carefully.

so the correctly way is just using for-each loop, since Stream#collect doesn't support short-circuiting operation.

the optional way is using peek because you can control the stream by yourself. and you need to remove the synchornized block, it is unnecessary here.

return IntStream.range(0, size).peek(foo::add).allMatch(__ -> Foo.isLegal(foo));
like image 193
holi-java Avatar answered Sep 21 '22 13:09

holi-java