代码之家  ›  专栏  ›  技术社区  ›  yali

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

  •  0
  • yali  · 技术社区  · 5 年前

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

        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;
    
    2 回复  |  直到 5 年前
        1
  •  5
  •   Sweeper    5 年前

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

    ProductModelDTOV2 ProductModelDTOV2 = dtoFactoryV2.populate(p, summary);
    

    但必须订购此部件:

    productModelDTOV2s.add(ProductModelDTOV2);
    

    你能做的就是把这两件事分开。做a中的第一部分 flatMap ,第二部分 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
    
        2
  •  2
  •   Andreas dfa    5 年前

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

    List<Product> products = productList.getProducts();
    
    return products.parallelStream()
            .map(p -> {
                try {
                    return dtoFactoryV2.populate(p, summary);
                } catch (GenericException e) {
                    log.debug("Unable to populate Product " + p);
                    return null;
                }
            })
            .filter(Objects::nonNull)
            .collect(Collectors.toList());