在java 8中的有序列表上进行映射

时间:2015-12-15 21:53:44

标签: java functional-programming java-8 java-stream

在Java 8附带的流媒体库中,我们提供了forEachOrdered API,其文档在此处转载

  

void forEachOrdered(消费者行为)

     

对此流的每个元素执行操作。

     

这是终端操作。

     

此操作一次处理一个元素,如果存在,则会遇到在为后续元素执行操作之前执行一个元素的操作,但对于任何给定元素,可以在库选择的任何线程中执行操作。

我们是否对map API

的订购有任何保证

例如,我在代码中有以下内容

import csv

with open("input.txt") as infile, open('output.txt', 'w') as fout:
    outfile = csv.writer(fout, delimiter='\t')
    for name, id, seq in csv.reader(infile, delimiter='\t'):
        locs = [i for i,char in enumerate(seq) if char=='r']
        for loc in locs:
            outfile.writerow([name, id, seq[max(loc-35, 0) : loc+36]])

处理中是否会遵守private final BazUtils bazUtils; public List<Foo> getFoos(List<Bar> bars) { AtomicInteger idx = new AtomicInteger(1); return bars.stream() .map(bar -> bazUtils.getFoo(bar, idx.getAndAdd(1))) .collect(Collectors.toList()); } 的顺序?

2 个答案:

答案 0 :(得分:3)

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps

  

如果订购了流,则大多数操作都被约束为对其遭遇顺序中的元素进行操作;如果流的源是包含[1,2,3]的List,那么执行map(x - &gt; x * 2)的结果必须是[2,4,6]。但是,如果源没有定义的遭遇顺序,那么值[2,4,6]的任何排列都将是有效的结果。

所以,是的;订单由map保留。

答案 1 :(得分:2)

请参阅package documentation,“无状态行为”和“副作用”部分:

  

......如果行为参数确实有副作用,除非明确说明,否则不保证visibility对其他线程的副作用,也不保证对“相同的流管道中的相同“元素在同一个线程中执行。此外,这些效果的排序可能令人惊讶。即使管道被限制为产生与流源的遭遇顺序一致的结果(例如,IntStream.range(0,5).parallel().map(x -> x*2).toArray()必须产生[0, 2, 4, 6, 8]),也不保证关于mapper函数应用于单个元素的顺序,或者在给定元素执行任何行为参数的线程中

换句话说,即使使用AtomicInteger,您的示例也不会在使用并行流时起作用,因为没有关于处理顺序的保证。流将保持遭遇顺序,即生成的List订单将反映原始BarList的原始顺序,但{ {1}}通过副作用生成的值可能不匹配(顺便说一下,并行性能可能很差)。

int终端操作非常特殊,因为操作的处理顺序将与遭遇顺序相匹配。当使用此终端操作时,这将极大地限制并行处理的好处。

您可以使用

正确执行您想要的操作
forEachOrdered