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文件的完整内容。
是的,但是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);
你怎么样?
实际上,一个问题中有两个问题,第一个问题是它是否会对编写流产生影响。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的回答。
本文向大家介绍区块链以什么顺序链接?相关面试题,主要包含被问及区块链以什么顺序链接?时的应答技巧和注意事项,需要的朋友参考一下 回答:区块链中的所有区块都以反向顺序链接,或者每个区块都与其前一个区块链接。