我正在使用spark rdd。我必须在该rdd的每个元素上应用一个函数。当我调用rdd.map(x=>function(x))
时,代码不会提供所需的输出,但是当我执行rdd.collect().foreach(x=>function(x))
时,代码工作正常。但collect()
的问题在于它将数据带入内存,使得大尺寸数据变得困难。如何在rdd的每个元素上调用此函数?
答案 0 :(得分:3)
那是因为RDD是不可变的并且懒惰地执行。
执行rdd.map(x=>function(x))
时,您可以使用已应用的转换创建新的RDD。应用并不意味着执行 - RDD是转换和操作的谱系,当您键入rdd.map
时,您正在创建新RDD,并在RDD图中添加一个额外步骤。这就是为什么你这样做:
val rdd = // here reading
rdd.map (...)
rdd.collect()
collect()
的结果不会是map
函数转换的源数据。旧的RDD没有改变。
这是您代码中的第一个错误。
其次,在这种情况下,转换,映射将在执行时触发某些操作(收集,减少等)。
请检查:
val mapped = rdd.map(x=>function(x))
// collect is an action, so above transformation map will be executed
mapped.collect().foreach (x => println(x)) // collect will trigger `map` also
它将在转换后打印内容。如果您执行mapped.count()
,则map()
也将被执行。在调用动作之前,不会执行转换,因为RDD是惰性的
答案 1 :(得分:0)
尝试rdd.mapPartitions(func)。它在每个分区上应用了Iterable(ex:list)的函数。从技术上讲,每个分区中的元素可以迭代列表并在每个元素上应用所需的函数。
答案 2 :(得分:0)
我了解您的function(x)
实际上是println(x)
。您没有看到任何打印内容的原因是因为该函数在您的工作节点上执行,因此它会打印到您的工作节点上的stdout以及驱动程序上的而不是。