【Spark】RDD的序列化问题

发现问题

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

    val rdd: RDD[String] = sc.makeRDD(Array("hello world", "hello spark", "hive", "atguigu"))

    val search = new Search("h")

    search.getMatch1(rdd).collect().foreach(println)
//    search.getMatch2(rdd).collect().foreach(println)

    sc.stop()
  }

  // 查询对象
  // 类的构造参数其实是类的属性, 构造参数需要进行闭包检测,其实就等同于类进行闭包检测
  class Search(query:String){

    def isMatch(s: String): Boolean = {
      s.contains(this.query)
    }

    // 函数序列化案例
    def getMatch1 (rdd: RDD[String]): RDD[String] = {
      rdd.filter(isMatch)
    }

    // 属性序列化案例
    def getMatch2(rdd: RDD[String]): RDD[String] = {
      val s = query
      rdd.filter(x => x.contains(s))
    }
  }

}

运行结果: 

报错出现“任务无法序列化”的问题,分析原因得知:

从计算的角度 , 算子以外的代码都是在 Driver 端执行 , 算子里面的代码都是在 Executor
端执行 。那么在 scala 的函数式编程中,就会导致 算子内 经常会用到 算子外 的数据,这样就
形成了闭包的效果,如果使用的算子外的数据无法序列化,就意味着无法传值给 Executor
端执行,就会发生错误,所以需要在执行任务计算前,检测闭包内的对象是否可以进行序列
化,这个操作我们称之为 闭包检测。
 

解决问题

1、让类继承序列化特质

2、将构造参数赋给字符串常量,因为字符串是可序列化的:

 3、使用样例类


  * 样例类Case Class
  * Case Class一般被翻译成样例类,它是一种特殊的类,能够被优化以用于模式匹配。
  * 当一个类被声名为case class的时候,scala会帮助我们做下面几件事情:
  * 1、构造器中的参数如果不被声明为var的话,它默认的是val类型的,但一般不推荐将构造器中的参数声明为var。
  * 2、自动创建伴生对象,同时在里面给我们实现子apply方法,使我们在使用的时候可以不直接使用new创建对象。
  * 3、伴生对象中同样会帮我们实现unapply方法,从而可以将case class应用于模式匹配。
  * 4、实现自己的toString、hashCode、copy、equals方法
  * 除此之此,case class与其它普通的scala类没有区别
 

 

样例类引用:原文链接:https://blog.csdn.net/accptanggang/article/details/78575710

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值