mapPartitions
- 该函数和map函数类似,只不过映射函数的参数由RDD中的每一个元素变成了RDD中每一个分区的迭代器。如果在映射的过程中需要频繁创建额外的对象,使用mapPartitions要比map高效的过。
- 比如,将RDD中的所有数据通过JDBC连接写入数据库,如果使用map函数,可能要为每一个元素都创建一个connection,这样开销很大,如果使用mapPartitions,那么只需要针对每一个分区建立一个connection。
- 参数preservesPartitioning表示是否保留父RDD的partitioner分区信息。
/**
* 通过将一个函数应用于这个RDD的每个分区,返回一个新的RDD。
* `preservesPartitioning`指示输入函数是否保留分区
*/
def mapPartitions[U: ClassTag](
f: Iterator[T] => Iterator[U],
preservesPartitioning: Boolean = false): RDD[U] = withScope {
val cleanedF = sc.clean(f)
new MapPartitionsRDD(
this,
(context: TaskContext, index: Int, iter: Iterator[T]) => cleanedF(iter),
preservesPartitioning)
}
mapPartitionsWithIndex
- 函数作用同mapPartitions,不过提供了两个参数,第一个参数为分区的索引。
/**
* 通过在RDD的每个分区上应用一个函数来返回一个新的RDD,同时跟踪原始分区的索引。
*/
def mapPartitionsWithIndex[U: ClassTag](
f: (Int, Iterator[T]) => Iterator[U],
preservesPartitioning: Boolean = false): RDD[U] = withScope {
val cleanedF = sc.clean(f)
new MapPartitionsRDD(
this,
(context: TaskContext, index: Int, iter: Iterator[T]) => cleanedF(index, iter),
preservesPartitioning)
}
Scala实例
object Core005 {
def main(args: Array[String]) {
val conf = new SparkConf().setMaster("local").setAppName("core05")
val sc = new SparkContext(conf)
val rdd = sc.parallelize(List(1, 2, 3, 4, 5), 2)
//类似Java的mapPartitionsToPair
val rdd1 = rdd.mapPartitions(ite => {
val list = new ListBuffer[Tuple2[Integer, Integer]](); //scala.collection.mutable.ListBuffer
while (ite.hasNext) {
val next = ite.next()
list += Tuple2(next, next * 2)
}
list.iterator
}, false)
rdd1.foreach(x => print(x + " "))
结果:(1,2) (2,4) (3,6) (4,8) (5,10)
//mapPartitions