1.并行流的线程安全
如果在并行流中涉及到对共享资源的写的操作,需要注意多线程带来的问题。如下代码中,在并行流中操作共享资源result
,由于HashMap非线程安全
,代码执行结束之后可能会得到错误的结果
public Map<String, String> foo(List<String> demoList, String arg) {
if (CollectionUtils.isEmpty(demoList)) {
return Collections.emptyMap();
}
Map<String, String> result = new HashMap<>();
demoList.parallelStream().forEach(text -> {
try {
result.put(text, doSomething(arg));
} catch (Exception e) {
e.printStackTrace();
}
});
return result;
}
解决方案
保证共享资源的线程安全性,容器类可以改用对应的线程安全的类型,如HashMap改用ConcurrentHashMap
,其他同理,伪代码如下:
Map<String, String> result = new ConcurrentHashMap<>();
demoList.parallelStream().forEach(text -> {
try {
result.put(text, doSomething(arg));
} catch (Exception e) {
e.printStackTrace();
}
});
2.流(Stream)汇总为Map的时候建议指定key重复时的处理方式,若不指定,将会抛出异常
正向用例伪代码如下:
public Map<String, String> bar(List<String> demoList) {
if (CollectionUtils.isEmpty(demoList)) {
return Collections.emptyMap();
}
return demoList.stream().collect(Collectors.toMap(k -> k,
Function.identity(), (v1, v2) -> v1));
}
对应Collectors的API为:
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction)