首页 > 解决方案 > Java 8 流 lambda 中的共享可变性

问题描述

据说共享可变性在 Java8 中是邪恶的,我有一个像下面这样的用例,我正在修改 parallelStream() 中的共享列表,只是想知道这是否可以作为例外来获得 parallelStream() 的好处或应该只需使用命令式代码并牺牲并行性。

另外,我们可以使用其他方法来遇到这种情况吗?

private List<CustomClass> perfromActionInStream(Map<Long, List<CustomClass>> longCustomMap) {
        List<CustomClass> synchronizedList = Collections.synchronizedList(new ArrayList<>());
        longCustomMap
                .entrySet()
                .parallelStream()
                .forEach(entry -> performActionInLambda(synchronizedList, entry));

}

private void performActionInLambda(List<CustomClass> synchronizedList,
                              Map.Entry<Long, List<CustomClass>> entry) {
        try {
            Map<Long, CustomClass> recordsFromDb = persistService
                    .findInDb(entry.getKey());
            //Based on some condition 
            if(recordsFromDb.containsKey(entry.getKey())){
                //Some if condition on value for the entry
                recordsFromDb.remove(entry.getKey())
            }
            //:::Shared mutation::::Add all remaining elements from recordsFromDb to synchronizedList
            synchronizedList.addAll(recordsFromDb.values());
        } catch (DataAccessException e) {
            log.error("Error occurred in lambda for fetching records from database", e);
            throw e; //throwing to stop further execution
        }
}

标签: javalambdajava-8java-stream

解决方案


在这种情况下,与其将其作为并行流进行,不如您可以获取映射中所有键的数据库记录(或者,根据映射的大小以块的形式)会更好。这将使数据库调用一次或更少次,从而提高代码的性能。我觉得在 lambda 并行执行中改变一个同步列表可能不是一个好的选择。


推荐阅读