Java 以原始顺序在数组列表中使用并行流

Java 以原始顺序在数组列表中使用并行流,java,lambda,java-8,Java,Lambda,Java 8,我有一个产品,我想用相同的原始顺序填充另一个数组中的产品,我使用并行流,结果不是按原始顺序排序的 List<Product> products = productList.getProducts(); List<ProductModelDTOV2> productModelDTOV2s = new ArrayList<>(); products.parallelStream().forEach(p -> {

我有一个产品,我想用相同的原始顺序填充另一个数组中的产品,我使用并行流,结果不是按原始顺序排序的

    List<Product> products = productList.getProducts();
    
    List<ProductModelDTOV2> productModelDTOV2s = new ArrayList<>();
    
    products.parallelStream().forEach(p -> {
        try {
            ProductModelDTOV2 ProductModelDTOV2 = dtoFactoryV2.populate(p, summary);
            productModelDTOV2s.add(ProductModelDTOV2);
        } catch (GenericException e) {
            log.debug(String.format("Unable to populate Product %s", p));
        }
    });
    return productModelDTOV2s;
List products=productList.getProducts();
List productModelDTOV2s=新的ArrayList();
products.parallelStream().forEach(p->{
试一试{
ProductModelDTOV2 ProductModelDTOV2=dtoFactoryV2.populate(p,summary);
productModelDTOV2s.add(ProductModelDTOV2);
}捕获(一般例外e){
log.debug(String.format(“无法填充产品%s”,p));
}
});
返回productModelDTOV2s;

这部分代码似乎可以无序并并行运行:

ProductModelDTOV2 ProductModelDTOV2 = dtoFactoryV2.populate(p, summary);
但这一部分必须订购:

productModelDTOV2s.add(ProductModelDTOV2);
你能做的就是把这两件事分开。在平面图中执行第一部分,在forEachOrdered中执行第二部分:

products.parallelStream().flatMap(o -> { // this block will be done in parallel
    try {
        return Stream.of(dtoFactoryV2.populate(p, summary));
    } catch (GenericException e) {
        // don't expect this message to be printed in order
        log.debug(String.format("Unable to populate Product %s", p));
        return Stream.of();
    }
})
.forEachOrdered(productModelDTOV2s::add); // this will be done in order, non-parallel

正确的方法是让流创建列表:

List products=productList.getProducts();
退货产品。parallelStream()
.map(p->{
试一试{
返回dtoFactoryV2.populate(p,summary);
}捕获(一般例外e){
log.debug(“无法填充产品”+p);
返回null;
}
})
.filter(对象::非空)
.collect(Collectors.toList());

你不能既吃蛋糕又吃蛋糕。。。平行流是无序的。如果你想让它们有序排列,那么流的定义是连续的,这意味着“不并行”。@Sweeper是的,但我有大量需要填充的数据,所以我需要一个并行流,而不是流。如果你想从并行处理中获得真正的好处,请使用
.collector(Collectors.toList())
而不是'forEachOrdered-.@Holger因为使用了
forEachOrdered
而等待下一个可能会花费更多的有序元素处理,对吗?还是别的什么?@Holger会按顺序添加元素,因为这是OP的要求?如果是这样的话,它怎么仍然是平行的呢。一般来说,不要混淆。通过讨论
toMap
vs
toConcurrentMap
,它解释了并发和非并发采集之间的区别,这可能是有帮助的,但非当前收集器的工作方式也适用于
toList