java - .peek() 在 java 8 流中的使用

标签 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.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() 的方法是这样的:它确实有效 - 但我只是将问题“移动”到 .allMatch():

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

我的问题与this question 非常相似,不同之处在于我每次都在检查,所以解决方案不起作用。

所以我的问题是:

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

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

最佳答案

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

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

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

所以正确的方法是使用for-each 循环,因为Stream#collect 不支持short-circuiting operation .

可选的方法是使用peek,因为您可以自己控制流。并且您需要删除 synchornized block ,这里没有必要。

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

关于java - .peek() 在 java 8 流中的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44759090/

相关文章:

java - Vaadin 窗口中的关闭通知事件

java - 如何破坏 StringBuilder 线程安全(示例不安全代码很有可能被破坏)

parallel-processing - Java8中Iterator和Spliterator的区别

java - 使用流从列表中获取总和和最大值

java - 像树命令一样打印目录

java - HtmlUnit 发布表单?

java - 无法通过 Java 8 上的反射调用 HashMap 的 getEntry

spring-boot - 微服务先返回响应再处理请求

java - 获取流中符合条件的第一个元素

java - 如何通过其中的某个最大值过滤流?