简体   繁体   English

在java 8流中使用.peek()

[英]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. 我在我的流中使用了.peek(),但它很不满意,遗憾的是我无法找到解决方案。

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. 我需要做的是迭代IntStream并在每次插入后检查foo数据结构是否合法。 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() : 不使用.peek()就是这样:它确实有效 - 但我只是将问题“移动”到.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? .peek()真的只是为了调试还是以这种方式使用它?
  • 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. 我正在寻找一个正确的解决方案,而不是一个有效的解决方案,所有这些代码已经在运行。

the documentation of Stream#peek has mentioned as below, and mainly is not absolutely : Stream#peek的文档如下所述, 主要不是绝对的

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: @Holger绝对回答了这个问题:

the most useful thing you can do with peek is to find out whether a stream element has been processed. 你可以用peek做的有用的事情是找出是否已经处理一个流元素。

and some side-effects he has also pointed it out in his answer, the peek operation depends on which terminal operation was invoked. 他在答案中也指出了一些副作用, peek操作取决于调用哪个终端操作。 so when using peek internally you should be carefully. 所以在内部使用peek你应该小心。

so the correctly way is just using for-each loop, since Stream#collect doesn't support short-circuiting operation . 所以正确的方法就是使用for-each循环,因为Stream#collect不支持短路操作

the optional way is using peek because you can control the stream by yourself. 可选的方法是使用peek因为你可以自己控制流。 and you need to remove the synchornized block, it is unnecessary here. 你需要删除synchornized块,这里没有必要。

return IntStream.range(0, size).peek(foo::add).allMatch(__ -> Foo.isLegal(foo));

I can think of only a single way to do it if you really want to use other stream operations before your logic, but I'm not really a big fan of it... 如果你真的想在你的逻辑之前使用其他流操作,我只能想到一个单一的方法,但我不是真的很喜欢它...

 boolean result = true;
    try {
        IntStream.range(0, 10)
                .forEachOrdered(x -> {
                    foo.add(x);
                    if (!Foo.isLegal(foo)) {
                        throw new RuntimeException("just because");
                    }
                });
    } catch (RuntimeException re) {
        result = false;
    }

    System.out.println(result);

Obviously you need to replace RuntimeException with some kind of your exception. 显然,您需要使用某种异常替换RuntimeException

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM