我有以下RDD,它有4个分区: -
val rdd=sc.parallelize(1 to 20,4)
现在我尝试在这上面调用mapPartitions: -
scala> rdd.mapPartitions(x=> { println(x.size); x }).collect
5
5
5
5
res98: Array[Int] = Array()
为什么它返回空数组? anonymoys函数只是返回它收到的相同迭代器,那么它是如何返回空数组的呢?有趣的是,如果我删除println语句,它确实返回非空数组: -
scala> rdd.mapPartitions(x=> { x }).collect
res101: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
我不明白。为什么println(只是打印迭代器的大小)的存在会影响函数的最终结果?
答案 0 :(得分:10)
那是因为x
是TraversableOnce
,这意味着您通过调用size
遍历它然后将其返回....空。
你可以通过多种方式解决这个问题,但这里有一个:
rdd.mapPartitions(x=> {
val list = x.toList;
println(list.size);
list.toIterator
}).collect
答案 1 :(得分:1)
要了解发生了什么,我们必须查看您传递给mapPartitions
的函数的签名:
(Iterator[T]) ⇒ Iterator[U]
那么Iterator
是什么?如果您查看Iterator
documentation,我会看到它是一个延伸TraversableOnce
的特征:
trait Iterator[+A] extends TraversableOnce[A]
上面应该给你一个暗示你的情况会发生什么。迭代器提供两种方法hasNext
和next
。要获得迭代器的size
,您必须简单地迭代它。在hasNext
返回false
之后,结果会显示空Iterator
。