在执行并行Stream Java 8时获取异常

问题描述 投票:1回答:1

我正在编写一个函数,计算给定数字的数字平方和。我正在为1到1000之间的数字并行调用此函数。但是我有一段时间会例外。

public static void main(String[] args) throws Exception {
        IntStream stream = IntStream.rangeClosed(1, 1000);
        Map<Integer, Integer> numbers = new TreeMap<>();
        stream.parallel().forEach(i -> {
            int result = digitSquareSum(i);
            numbers.put(i, result);
        });
        Files.write(Paths.get("result.csv"), () -> numbers.entrySet().stream()
                .<CharSequence>map(e -> e.getKey() + "," + e.getValue())
                .iterator());
    }

    private static int digitSquareSum(int i) {
        int result = 0;
        int temp = 0;
        while (i != 0) {
            temp = i % 10;
            result = result + temp * temp;
            i = i / 10;
        }
        return result;
    }

我正在跟踪异常

Exception in thread "main" java.lang.NullPointerException
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
    at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:590)
    at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:668)
    at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:726)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:160)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfInt.evaluateParallel(ForEachOps.java:189)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
    at java.base/java.util.stream.IntPipeline.forEach(IntPipeline.java:417)
    at java.base/java.util.stream.IntPipeline$Head.forEach(IntPipeline.java:574)

我的目标是编写一种有效的方法,该方法可以计算数字的数字平方和,然后将其以升序方式写入csv文件。

java java-8 nullpointerexception stream
1个回答
0
投票

如评论中所述,您将收到此异常,因为TreeMap不是线程安全的。从javadoc

请注意,此实现未同步。如果有多个线程同时访问地图,并且至少有一个线程修改了从结构上讲,地图必须在外部进行同步。 (一种结构修改是添加或删除一个或多个更多映射;仅更改与现有产品关联的值关键不是结构上的修改。)

我相信您正在使用TreeMap来保留初始数字的顺序。但这不是必需的(并且还引入了side-effects):您可以使用Collectors.toList(),它将所有输入元素按遇到的顺序收集到列表中

这还将使您避免创建第二个流来将这些数字写入文件:

List<String> lines = IntStream.rangeClosed(1, 1000)
            .parallel()
            .mapToObj(i -> i + " -> " + digitSquareSum(i))
            .collect(Collectors.toList());
Files.write(Paths.get("result.csv", lines); // the lines will come in the right order
© www.soinside.com 2019 - 2024. All rights reserved.