无法运行读取元组RDD并返回元组RDD的spark map函数

时间:2017-07-10 17:09:24

标签: scala apache-spark

我需要从另一个配对的RDD生成配对的RDD。基本上,我正在尝试编写一个执行以下操作的map函数。

RDD[Polygon,HashSet[Point]] => RDD[Polygon,Integer]

这是我写的代码:

Scala函数,它迭代HashSet并从“Point”对象中添加一个值。

def outCountPerCell( jr: Tuple2[Polygon,HashSet[Point]] ) : Tuple2[Polygon,Integer] = {
  val setIter = jr._2.iterator()
  var outageCnt: Int = 0
  while(setIter.hasNext()) {
    outageCnt += setIter.next().getCoordinate().getOrdinate(2).toInt
  }
  return Tuple2(jr._1,Integer.valueOf(outageCnt))
}

在配对的RDD上应用该功能,这会引发错误:

scala> val mappedJoinResult = joinResult.map((t: Tuple2[Polygon,HashSet[Point]]) => outCountPerCell(t))
<console>:82: error: type mismatch;
found   : ((com.vividsolutions.jts.geom.Polygon, java.util.HashSet[com.vividsolutions.jts.geom.Point])) => (com.vividsolutions.jts.geom.Polygon, Integer)
required: org.apache.spark.api.java.function.Function[(com.vividsolutions.jts.geom.Polygon, java.util.HashSet[com.vividsolutions.jts.geom.Point]),?]
       val mappedJoinResult = joinResult.map((t: Tuple2[Polygon,HashSet[Point]]) => outCountPerCell(t))

有人可以查看我看到的内容,或者分享在map()操作中使用自定义函数的任何示例代码。

1 个答案:

答案 0 :(得分:2)

这里的问题是joinResult是来自Java API的JavaPairRDD。这个数据结构的map期待Java类型lambdas(Function),它们(至少可以轻易地)与Scala lambdas互换。

所以有两种解决方案:尝试将给定方法转换为Java Function以传递给map,或者只是像开发人员那样使用Scala RDD:

设置虚拟数据

在这里,我创建一些替代类,并创建一个与OP的结构类似的Java RDD:

scala> case class Polygon(name: String)
defined class Polygon

scala> case class Point(ordinate: Int)
defined class Point

scala> :pa
// Entering paste mode (ctrl-D to finish)

/* More idiomatic method */
def outCountPerCell( jr: (Polygon,java.util.HashSet[Point])) : (Polygon, Integer) =
{
    val count = jr._2.asScala.map(_.ordinate).sum
    (jr._1, count)
}

// Exiting paste mode, now interpreting.

outCountPerCell: (jr: (Polygon, java.util.HashSet[Point]))(Polygon, Integer)

scala> val hs = new java.util.HashSet[Point]()
hs: java.util.HashSet[Point] = []

scala> hs.add(Point(2))
res13: Boolean = true

scala> hs.add(Point(3))
res14: Boolean = true

scala> val javaRDD = new JavaPairRDD(sc.parallelize(Seq((Polygon("a"), hs))))
javaRDD: org.apache.spark.api.java.JavaPairRDD[Polygon,java.util.HashSet[Point]] = org.apache.spark.api.java.JavaPairRDD@14fc37a

使用Scala RDD

可以使用.rdd

从Java RDD检索基础Scala RDD
scala> javaRDD.rdd.map(outCountPerCell).foreach(println)
(Polygon(a),5)

更好的是,将mapValues与Scala RDD一起使用

由于只有元组的第二部分正在改变,所以.mapValues可以彻底解决这个问题:

scala> javaRDD.rdd.mapValues(_.asScala.map(_.ordinate).sum).foreach(println)
(Polygon(a),5)