.peek()在Java8流中的使用

.peek()在Java8流中的使用,java,java-8,java-stream,Java,Java 8,Java Stream,我正在我的流中使用.peek(),但它不受欢迎,很遗憾我找不到解决方案 简化版: 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.

我正在我的流中使用.peek(),但它不受欢迎,很遗憾我找不到解决方案

简化版:

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());
}
我需要做的是迭代IntStream,并在每次插入后检查,看foo数据结构是否合法。 这在逻辑上等同于:

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;
}
我的问题非常类似于,不同之处在于我每次都在检查,所以解决方案不起作用

因此,我的问题是:

  • .peek()
    真的只是为了调试,还是我可以这样使用它
  • 有没有更好的解决办法
  • 我应该使用第二种解决方案吗

我正在寻找一个正确的解决方案,而不是一个有效的解决方案,所有这些代码都已经在运行。

如果您真的想在逻辑之前使用其他流操作,我只能想到一种方法来实现它,但我不是它的忠实粉丝

 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);

显然,您需要用某种异常替换
RuntimeException

Stream#peek的文档如下所述,主要不是绝对的

此方法的存在主要是为了支持调试,您希望在元素流过管道中的某个点时看到这些元素

绝对回答了这个问题:

使用
peek
可以做的最有用的事情是找出流元素是否已被处理

他在回答中也指出了一些副作用,
peek
操作取决于调用哪个终端操作。因此,在内部使用
peek
时,您应该小心

因此正确的方法是对每个循环使用
,因为
Stream#collect
不支持

可选的方法是使用
peek
,因为您可以自己控制流。您需要删除
synchornized
块,这里不需要它

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

这可能会有帮助:您希望在每次插入后检查条件
;这依赖于副作用,应该避免。顺便说一句,
synchronized
对您没有多大帮助-它将保证每次只在
foo
中放入一个元素;但它不能保证将哪个元素放入foo中,因为在并行流的情况下没有处理顺序。对于“新手”来说,什么是
r
?你为什么要在上面同步?您的流代码与循环不匹配。您正在对
int
值进行流式处理,因此需要使用
static
方法
Foo.isLegal(int)
使编译器接受第一个代码段。在最后一个代码段中,您正在不允许方法引用的位置使用方法引用
Foo::isLegal
。显然,您从未尝试过这些方法中的任何一种。是的,
使用peek可以做的最有用的事情是找出流元素是否已被处理。
,但是通过日志记录,而不是依赖于副作用。只要你添加
parallel
,这将以神秘的方式中断。synchronized将确保一次只处理一个元素,但即使这样,您也不知道是哪个元素,有处理顺序。@Eugene但我想说OP可以控制如何创建、使用和操作流。所以这里没有问题。我添加了
synchornized
,最初是为了使用
parallel()
。非常感谢你的回答!
return IntStream.range(0, size).peek(foo::add).allMatch(__ -> Foo.isLegal(foo));