在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());
}
的顺序?
答案 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
订单将反映原始Bar
中List
的原始顺序,但{ {1}}通过副作用生成的值可能不匹配(顺便说一下,并行性能可能很差)。
int
终端操作非常特殊,因为操作的处理顺序将与遭遇顺序相匹配。当使用此终端操作时,这将极大地限制并行处理的好处。
您可以使用
正确执行您想要的操作forEachOrdered