Spark源码解析之map,mapPartitions,filter

最近在复习spark,写一些笔记来记录复习的源码过程,以及使用一些源码手动实现算子的过程。

map算子

//这是一个简单的map方法Demo
object Demo1 {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("Demo1").setMaster("local[*]")
    val sc = new SparkContext(conf)

    val rdd1 = sc.makeRDD(List(1, 2, 3, 4, 5))

    val result = rdd1.map(_ + "分")

    result.foreach(println)
    sc.stop()
  }
}

//这里是map的源码
点击map进入
  def map[U: ClassTag](f: T => U): RDD[U] = withScope {
    val cleanF = sc.clean(f)
    new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.map(cleanF))
  }


点击MapPartitionsRDD进入
private[spark] class MapPartitionsRDD[U: ClassTag, T: ClassTag](
    var prev: RDD[T],
    f: (TaskContext, Int, Iterator[T]) => Iterator[U],  // (TaskContext, partition index, iterator)
    preservesPartitioning: Boolean = false,
    isFromBarrier: Boolean = false,
    isOrderSensitive: Boolean = false)

这里传入的参数
prev 父RDD
f 传入TaskContext,就是配置信息,然后传入分区编号,传入一个对迭代器操作的方法,其实就是传入了scala中的map方法。
preservesPartitioning 是否保留分区器,一般都是否。除非是pairRDD并且应用的方法没有改变key。
isFromBarrier 是否来自屏障RDD,这是Spark3中的新特性,好像是和机器学习相关的,没有仔细看
isOrderSensitive 

mapPartitions算子

object Demo1 {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("Demo1").setMaster("local[*]")
    val sc = new SparkContext(conf)

    val rdd1 = sc.makeRDD(List(1, 2, 3, 4, 5))
    
    val value = rdd1.mapPartitions(it=>it.map(_ + "分"))

    sc.stop()
  }
}

上边这是一个调用mapPartitions的例子,点进mapParttitions进入源码

  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)
  }

源码中,sc.clean(f)就是对传入的函数做了一个闭包检查,可以忽略它,把cleandF当成我们自己传入的逻辑就可以了。
可以看到mapPartitions也是新建了一个MapPartitionsRDD,里边就是和map的区别了,
在map中,对迭代器的操作是map(我们自己写的逻辑),
这样就会导致迭代器每次map出一条数据就会调用一次我们传入的逻辑。
而mapPartitions直接调用了我们传入的逻辑,
这样每个分区的迭代器只会调用一次,这样就算迭代器里的逻辑还是调用map,我们传入的逻辑也就只调用了一次。

mapPartitionsWithIndex算子

这个算子其实就是在mapPartitions的基础上把分区索引拿出来了,因为new MapPartition的时候参数就要有分区编号,所以这个算子本质上和mapPartitions没有区别。

filter算子

filter算子其实和map差不多,都是新建了一个MapPartitionsRDD,不过里边对迭代器的操作变成了filter。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值