Java 向同一数组添加项的并行流

Java 向同一数组添加项的并行流,java,java-stream,Java,Java Stream,我有一个对象数组,我流式地使用每个对象上的函数来修改它,并将其添加到一个全新的对象数组中 通过使用.parallel()执行时间加快了2倍,但在新数组上循环时,我得到了一些NullPointerExceptions 我试着调试了几次,但都没有成功。似乎这个问题只发生在运行时。我尝试实现一个同步功能,将新对象添加到列表中,但遗憾的是,它没有起到同样的作用 谁能给我一个建议,如何让这个工作?提前谢谢 以下是代码片段: private static final Object sync = new Ob

我有一个对象数组,我流式地使用每个对象上的函数来修改它,并将其添加到一个全新的对象数组中

通过使用
.parallel()
执行时间加快了2倍,但在新数组上循环时,我得到了一些
NullPointerException
s

我试着调试了几次,但都没有成功。似乎这个问题只发生在运行时。我尝试实现一个同步功能,将新对象添加到列表中,但遗憾的是,它没有起到同样的作用

谁能给我一个建议,如何让这个工作?提前谢谢

以下是代码片段:

private static final Object sync = new Object();
private ArrayList<Object> newList = new ArrayList<Object>();      

private void addNewObject(Object newObject) {
        synchronized (sync) {
            newList.add(newObject);
        }
    }

private Object mutateObject(Object oldObject) {
    // Do something with the object here
    return mutatedObject;
}

public ArrayList<Object> createNewList(ArrayList<Object> oldList) {
    oldList.stream().parallel().forEach(object -> addNewObject(mutateObject(object)));
    return newList;
}
private static final Object sync=new Object();
private ArrayList newList=new ArrayList();
私有void addNewObject(Object newObject){
已同步(同步){
添加(newObject);
}
}
私有对象mutateObject(对象oldObject){
//对这里的物体做点什么
返回变异对象;
}
公共ArrayList createNewList(ArrayList oldList){
forEach(object->addNewObject(mutateObject(object));
返回newList;
}

考虑将
createNewList
方法重构为如下内容:

public List<Object> createNewList(List<Object> oldList) {
    return oldList.parallelStream()
            .map(this::mutateObject)
            .collect(Collectors.toList());
}
public List createNewList(List oldList){
返回oldList.parallelStream()
.map(this::mutateObject)
.collect(Collectors.toList());
}
如果您查看,您可以看到有一些终端操作,如
forEach
collect
toArray
,等等。在您的问题中,最好使用
collect
终端操作,因为它在内部处理同步,避免争用情况,没有任何进一步的同步实现

使用
.map()
(Stream的中间操作)映射对象并并行地将结果收集到最终列表可以解决此问题


addNewObject
函数和
sync
对象应该被删除,因为它不再使用。

您可以用
this::mutateObject
替换
object->mutateObject(object)
。感谢您的快速响应!我试试看。如果我想将一个对象多次添加到新列表中,我该怎么办?@Robert您总是可以从
.map()
返回一个列表(例如
.map(object->Arrays.asList(mutateObject(object)、mutateObject(object),…)
操作和do
.flatMap(Collection::stream)
在流中将列表列表转换为单个列表。@SzymonStepniak映射到
列表
没有意义,只需在之后执行
.flatMap(Collection::stream)
即可。只需执行
.flatMap(object->stream.of(mutateObject(object),mutateObject(object),…)首先,为什么不使用它来添加一个参数到CealEnWistLead函数?固定这个例子。考虑使用内置的并发集合,这样你就不必编写你自己的并发代码了。