当前位置: 首页 > 知识库问答 >
问题:

流并行跳过-链式流方法的顺序有什么区别吗?

慕志泽
2023-03-14
stream.parallel().skip(1) 

vs

stream.skip(1).parallel() 

这是关于Java8流的
这两个都跳过了第一行/条目吗?

例如:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.concurrent.atomic.AtomicLong;

public class Test010 {

    public static void main(String[] args) {
        String message = 
        "a,b,c\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n1,2,3\n4,5,6\n7,8,9\n";

        try(BufferedReader br = new BufferedReader(new StringReader(message))){

            AtomicLong cnt = new AtomicLong(1);

            br.lines().parallel().skip(1).forEach(
                s -> {
                    System.out.println(cnt.getAndIncrement() + "->" + s);
                }
            );

        }catch (IOException e) {
            e.printStackTrace();
        }

    }

}

今天早些时候,我有时会在lambda表达式中得到标题行“a,b,c”。这是一个惊喜,因为我本以为已经跳过了。现在我不能让这个例子工作,也就是说,我不能得到lambda表达式中的头行。所以我现在很困惑,也许是其他因素影响了这种行为。当然,这只是一个例子。在现实世界中,消息是从CSV文件读取的。该消息是该CSV文件的完整内容。

共有2个答案

邓俊材
2023-03-14

是的,但是skip(n)较慢,因为n在并行流中更大。

下面是kip()中的API注释:

虽然skip()通常是顺序流管道上的一种廉价操作,但在有序并行管道上,它可能非常昂贵,尤其是对于大值的n,因为skip(n)被约束为不仅跳过任何n元素,而且跳过相遇顺序中的第一个n元素。使用无序流源(例如generate(Supplier))或使用BaseStream删除订购约束。无序()可能会导致并行管道中的skip()显著加速,如果情况的语义允许的话。如果需要与遭遇顺序保持一致,并且在并行管道中使用skip()时,您的性能或内存利用率较差,请切换到使用BaseStream的顺序执行。sequential()可以提高性能

因此,从本质上讲,如果您希望使用skip()获得更好的性能,请不要使用并行流或无序流。

至于它似乎不适用于并行流,也许你真的看到元素不再有序了?例如,此代码的输出:

Stream.of("Hello", "How", "Are", "You?")
    .parallel()
    .skip(1)
    .forEach(System.out::println);


你呢<怎么做

创意演示

这很好,因为在并行流中,forEach不会强制执行遭遇顺序。如果你想让它强制执行遭遇顺序,可以使用顺序流(或者使用forEachOrdered,这样你的意图就显而易见了)。

Stream.of("Hello", "How", "Are", "You?")
    .skip(1)
    .forEachOrdered(System.out::println);


你怎么样?

竺和洽
2023-03-14

实际上,一个问题中有两个问题,第一个问题是它是否会对编写流产生影响。parallel()。跳过(1)流。跳过(1)。parallel(),第二个是其中一个或两个元素是否总是跳过第一个元素。另见“加载问题”。

第一个答案是没有区别,因为指定。sequential()。parallel()。

因此,在任何一种情况下,您都请求并行执行,这可能会影响跳过操作的结果,这是第二个问题的主题。

答案并不那么简单。如果流首先没有定义的相遇顺序,任意元素可能会被跳过,这是因为没有“第一”元素,即使在迭代源时可能会有一个元素首先遇到。

如果您有一个有序的流,skip(1)应该跳过第一个元素,但这是最近才提出的。如“Stream.skip behavior with unordered terminal operation”(无序终端操作的Stream.skip behavior)中所述,链接无序终端操作会对早期实现中的skip操作产生影响,这是否可能是有意的,存在一些不确定性,正如“这是Files.lines()中的一个bug,还是我对并行流有误解?”中所示,恰好与你的代码很接近;显然,跳过第一行是常见的情况。

最后一句话是,早期JRE的行为是一个错误,有序流上的kip(1)应该跳过第一个元素,即使流管道是并行执行的,终端操作是无序的。相关的错误报告将jdk1.8.0_60命名为第一个固定版本,我可以验证。因此,如果您在较旧的实现上使用,您可能会在使用时遇到Stream跳过不同的元素。并行()和无序的. foreach(...)终端操作。如果实现偶尔跳过预期的元素,这并不矛盾,这就是多线程的不可预测性。

所以答案仍然是流。parallel()。跳过(1)流。跳过(1)。parallel()具有相同的行为,即使在早期版本中使用时也是如此,因为当与无序的终端操作(如forEach)一起使用时,这两种行为同样不可预测。它们应始终跳过具有有序流的第一个元素,当与1.8.0_60或更新版本一起使用时,它们会跳过。

 类似资料:
  • 从流javadoc: 顺序流/并行流之间没有功能上的区别。输出从不受执行模式影响。 由于性能提高,在给定适当的核数和问题大小以证明开销合理的情况下,并行流始终是优选的。 我们希望编写一次代码并在任何地方运行,而不必关心硬件(毕竟这是Java) 假设这些假设是有效的(有一点元假设没有问题),那么在API中公开执行模式有什么价值呢? 看起来您应该能够声明一个,顺序/并行执行的选择应该在下面的一个层中自

  • 问题内容: 所述流文档状态双工流 “是同时实现可读写接口流”和变换流 “是双相流其中输出以某种方式从输入计算”。不幸的是,文档没有描述Transplex流在Duplex流之外提供的内容。 两者之间有什么区别吗?您什么时候可以使用另一个? 问题答案: 可以将双工流视为具有可写流的可读流。两者都是独立的,每个都有独立的内部缓冲区。读写事件独立发生。 转换流是双工的,其中读写以因果关系进行。双工流的端点

  • 在本书的后面,他们有一整章专门讨论CompletableFuture,在此期间,他们有一个案例研究,在那里他们比较了使用parallelStream和使用CompletableFuture的各自性能。事实证明,它们的性能非常相似--它们强调了这样做的原因,因为它们都是默认的,使用相同的公共池(因此有相同数量的线程)。 他们接着展示了一个解决方案,并认为CompletableFuture在这种情况下

  • 问题内容: 有许多不同的I / O 流(FileInputStream,FileOutputStream,FileReader,FileWriter,BufferedStreams等),我在确定它们之间的差异时感到困惑。在哪些示例中,一种流类型优先于另一种流类型,它们之间的真正区别是什么? 问题答案: 这是一个大话题!我建议您先阅读I / O流 : I / O流代表输入源或输出目的地。流可以表示许

  • 我试图理解反应流和反应流之间的区别,特别是在RxJava的上下文中? 我所能理解的最多的是,反应流在规范中有一些背压的概念,但在RxJava/Reactive中已经存在了请求(n)接口。 我不介意ELI5的回答。

  • 本文向大家介绍区块链以什么顺序链接?相关面试题,主要包含被问及区块链以什么顺序链接?时的应答技巧和注意事项,需要的朋友参考一下 回答:区块链中的所有区块都以反向顺序链接,或者每个区块都与其前一个区块链接。