如何在RDD的mapPartition操作中声明Iterator和DenseMatrix类型变量?

时间:2016-04-19 02:46:42

标签: apache-spark

我在RDD的mapPartition中有一个double数组,当我通过这个double数组声明一个迭代器或DenseMatrix时。我发现迭代器和矩阵是空的。我的测试代码如下:

val RandXts = data.map{
line =>
  val fields = patterns.findAllIn(line).toArray.map(_.toDouble)
  fields(fields.length-1)
}.repartition(2)

val res = RandXts.mapPartitions(x=>{
val matrix = new DenseMatrix(x.length,1,x.toArray)
val arr = matrix.toArray
println(k.length)
(matrix::List[DenseMatrix[Double]]()).iterator
})

如上所示,行声明矩阵将导致错误。错误消息如下:

java.lang.IndexOutOfBoundsException: Storage array has size 0 but indices can grow as large as 124

如何解决此问题?

1 个答案:

答案 0 :(得分:0)

您的代码调用x.length,然后再次将x传递给DenseMatrix构造函数。由于x是一个迭代器,因此调用length“消耗”迭代器,因此再次传递它将导致集合。

要解决此问题 - 扫描迭代器一次(通过将其转换为数组):

val res: RDD[DenseMatrix] = RandXts.mapPartitions(x => {
  val arr = x.toArray // scan iterator only once
  val matrix = new DenseMatrix(arr.length, 1, arr)
  Seq(matrix).iterator // this is the return value
})

例如,对于输入val RandXts = sc.parallelize(Seq(0.5, 0.6, 0.8)),打印结果显示它包含具有以下值的单个Matrix:

res.collect().foreach(println)
// prints: 
// 0.5  
// 0.6  
// 0.8