Java Spark中“for”循环中的某种类型的计数器

时间:2016-03-07 19:11:20

标签: java apache-spark

我正在用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,但我在网上找不到任何解决方案。

1 个答案:

答案 0 :(得分:2)

即使编译它也不会像你期望的那样工作。每个执行程序都获得自己在闭包内引用的变量的副本,并且任何修改都是严格本地的,并且不会传播回原始源。 Spark支持可写accumulators,可以按如下方式使用:

Accumulator<Double> accum = sc.accumulator(0d);

objects.map(
  ...
  accum.add(1d)
  ...
)

但是这些在转换中使用时提供了非常弱的保证(至少称为一次),并且正如您已经意识到的那样,从工作者的角度来看是只写的。

关于您的代码,您看起来只需要zipWithIndex

objects.zipWithIndex().map(...)