我正在用Java编写一个用于Spark 1.6.0的程序(所以,请不要在你的答案中提供Scala或Python代码),这是我想要实现的代码:
double i = 0d;
JavaRDD<Vector> ideas = objects.map(
new Function<BSONObject, Vector>()
{
@Override public Vector call(final BSONObject t) throws Exception
{
double[] xy = new double[2];
xy[0] = i++;
xy[1] = ((Long)((Date)t.get("date")).toInstant().toEpochMilli()).doubleValue();
return Vectors.dense(xy);
}
}
);
但NetBeans显示错误:“从内部类引用的局部变量必须是最终的或实际上是最终的。”
我也试过使用Spark Accumulators,但是如果我从我正在定义的call()方法调用value()方法,则在作业期间引发SparkException,告诉我“Task is not serializable”,然后工作失败了。
那么,我怎样才能实现目标呢?
如果我的英语不完美(这不是我的母语),我提前道歉,如果我的问题可能出现noob-ish,但我在网上找不到任何解决方案。
答案 0 :(得分:2)
即使编译它也不会像你期望的那样工作。每个执行程序都获得自己在闭包内引用的变量的副本,并且任何修改都是严格本地的,并且不会传播回原始源。 Spark支持可写accumulators,可以按如下方式使用:
Accumulator<Double> accum = sc.accumulator(0d);
objects.map(
...
accum.add(1d)
...
)
但是这些在转换中使用时提供了非常弱的保证(至少称为一次),并且正如您已经意识到的那样,从工作者的角度来看是只写的。
关于您的代码,您看起来只需要zipWithIndex
:
objects.zipWithIndex().map(...)