使用streams迭代linkedlist由于RaceCondition正在更改结果列表

dy2hfwbg  于 2021-07-09  发布在  Java
关注(0)|答案(2)|浏览(285)

我们使用java8中的流来迭代linkedlist,并创建另一个列表。但由于比赛的条件,结果列表的大小得到了大幅增加。

List<DesInfo> InfoList = new LinkedList<>();
documentList.stream()
            .parallel()
            .forEach(document -> {
                Info descriptiveInfo = objectFactory.createDescriptiveInfo();
                List<Document> documents = new ArrayList<>();
                documents.add(document);
                descriptiveInfo.setHotelInfo(getHotelInfo(document.get(CODE), documents));
                InfoList.add(Info);
            });

如果每次看到为同一个documentlist输入生成的infolist大小不同时都运行此代码。我浏览了一些论坛,他们提到linkedlist不是线程安全的,而是任何线程安全的集合。但我的要求不允许我改变除了linkedlist。我需要对同一个linkedlist使用并行流功能。
谢谢,拉哈文

7bsow1i6

7bsow1i61#

而不是使用 forEach 使用 Collector 和一个 map() 操作:

List<HotelDescriptiveInfo> hotelDescriptiveInfoList = documentList.parallelStream()
    .map(document -> {
        HotelDescriptiveInfo descriptiveInfo = objectFactory.createHotelDescriptiveInfo();
        List<Document> documents = new ArrayList<>();
        documents.add(document);
        descriptiveInfo.setHotelInfo(getHotelInfo(document.get(HOTEL_CODE), documents));
        return descriptiveInfo;
    })
    .collect(Collectors.toCollection(LinkedList::new));

这个 Stream api将负责处理,不允许竞争条件。

fd3cxomn

fd3cxomn2#

使用 collect 而不是改变集合的状态。
首先创建Map函数:

private DesInfo documentToDesInfo(Document document){
    DesInfo info = objectFactory.createDescriptiveInfo();
    List<Document> documents = new ArrayList<>();
    documents.add(document);
    info.setHotelInfo(getHotelInfo(document.get(CODE), documents));
    return info;
}

然后在管道中使用:

List<DesInfo> infoList = documentList.parallelStream()
                                     .map(this::documentToDesInfo)
                                     .collect(toCollection(LinkedList::new));

相关问题