java8 stream map reduce 导致ConcurrentModificationException,为什么?

java8 stream map reduce cause a the ConcurrentModificationException, why?

final BigDecimal couponlessAmount = orderItems.stream()
            .filter(item -> !item.getIsUseCoupon())
            .map(item -> item.getTotalAmount().subtract(item.getReduceProductAmount()))
            .reduce(BigDecimal.ZERO, BigDecimal::add);

某些原因导致 java.util.ConcurrentModificationException

java.util.ConcurrentModificationException
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1380) ~[?:1.8.0_77]
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[?:1.8.0_77]
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[?:1.8.0_77]
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) ~[?:1.8.0_77]
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:1.8.0_77]
    at java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:474) ~[?:1.8.0_77]
    at com.yijiupi.himalaya.ordercompute.provider.domain.component.computer.CouponUseLimitComputer.getMaxUseAmount(CouponUseLimitComputer.java:103) ~[classes/:?]

不太可能是 JDK/JIT 错误。通常与 ConcurrentModificationException 一样,这表明您的 orderItems 是从另一个线程同时修改的。如果没有提供适当的外部同步,您不应该同时使用 ArrayList。请注意,将 ArrayList 包装到 Collections.synchronizedList 中是不够的,因为它不会同步遍历。作为替代方案(如果很少修改)使用 CopyOnWriteArrayList.