我正在编写一个函数,用于计算给定数字的数字平方和。我正在为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文件。
答案 0 :(得分:1)
如注释中所述,您将收到此异常,因为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