如何进行scala隐式转换及Spark源码解析

本篇文章为大家展示了如何进行scala隐式转换及Spark源码解析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

十载专注成都网站制作,成都定制网站,个人网站制作服务,为大家分享网站制作知识、方案,网站设计流程、步骤,成功服务上千家企业。为您提供网站建设,网站制作,网页设计及定制高端网站建设服务,专注于成都定制网站,高端网页制作,对成都格栅板等多个领域,拥有丰富的营销推广经验。

隐式转换,是scala当中一个重要的特性,今天我们结合自己的例子和spark源码,争取对隐式转换有一个更加深入的了解。

关于implicit有3种使用方式,implicit def、implicit class以及implicit 参数

首先看一下implicit def的用法:

object implicitTest {
  class Man(val name: String){
    def work(){println(name + " is working!")}
  }

  class Woman(val name: String){
    def shop(){println(name + " is shopping!")}
  }

  class Child(val name: String){
    def play(){println(name + " is playing!")}
  }

  implicit def manToWoman(man: Man) = new Woman(man.name)
  implicit def manToChild(man: Man) = new Child(man.name)

  def main(args: Array[String]): Unit ={
    val man = new Man("Tom")
    val woman = new Woman("Lily")
    val child = new Child("baby")
    man.work()
    man.shop()
    man.play()
  }
}

在上面的代码当中,我们定义了3个class,Man、Woman、Child,他们之间没有任何继承关系。下面的main函数当中,我们声明了Man、Woman、Child,各一个实例,我们考虑,作为男人来讲,是不是也不一定只能是工作,适当的休闲和娱乐是不是也是可以的。所以我们做了2个隐式转换的函数,manToWoman和manToChild,需要注意的是,这两个函数名其实一点都不重要,我们只是希望看起来更容易理解一些,你写个aaa或者bbb,一点问题都没有。

编译过程大概是这样的:

1、编译man.shop(),发现并没有shop方法,即将报错

2、报错之前,搜索一下作用域内,有没有隐式转换函数,能够支持man对shop的调用,找到了manToWoman。

3、把man变成woman,调用shop方法

之后再看一下implicit class的用法:

object implicitTest {
  class Man(val name: String){
    def work(){println(name + " is working!")}
  }

  class Woman(val name: String){
    def shop(){println(name + " is shopping!")}
  }

  class Child(val name: String){
    def play(){println(name + " is playing!")}
  }

  implicit class ManConvert(m: Man){
    def shop() = new Woman(m.name).shop()
    def play() = new Child(m.name).play()
  }

  def main(args: Array[String]): Unit ={
    val man = new Man("Tom")
    val woman = new Woman("Lily")
    val child = new Child("baby")
    man.work()
    man.shop()
    man.play()
  }
}

这个当中实现的效果看起来和前一种差不多,其实它的语义是完全不同的。编译过程大概是这样的:

1、编译man.shop(),发现并没有shop方法,即将报错

2、报错之前,搜索一下作用域内,看看有没有隐式转换类,能够为man提供shop方法,找到了ManConvert

3、将man转换为ManConvert,执行shop方法。

最后我们再看一下implicit参数的用法:

object implicitTest {
  class Man(val name: String){
    def work(){println(name + " is working!")}
    def marry(implicit w: Woman){println(name + " marryed " + w.name)}
  }

  class Woman(val name: String){
    def shop(){println(name + " is shopping!")}
  }

  def main(args: Array[String]): Unit ={
    val man = new Man("Tom")
    implicit val woman = new Woman("Lily")
    man.marry
  }
}

我们为Man增加了一个marry的方法,它的参数w是implicit的,然后调用的时候,我们先在前面声明了一个implicit 类型的woman,之后调用marry但是不指定参数,这样是不会报错得到。但是如果我们在marry的前面声明了2个implicit的woman,那么marry还是会报错的。

换成人类的语言来解释这件事:一个男人要结婚,如果指定结婚对象,那没问题,如果没指定,那就看看身边有没有适合的结婚对象,有的话,就直接生米煮成熟饭,可是如果身边有2个,好吧,我也不知道该娶哪个!

结合Spark源码,我们来深入理解一下implicit,看下面这段代码:

val rdd = sc.textFile("hdfs://master:9000/woozoom/mavlink1.log", 12).zipWithIndex()
rdd.sortByKey()

看起来是达到目的了,可是这个sortByKey的确切含义究竟是什么,倒序?正序?能不能自定义排序原则?去找一下spark的api文档吧,找到RDD类,查找sortByKey方法,可是,居然,居然没有,只有sortBy,没有sortByKey。懵逼了~~~~~~

直到我了解了implicit这回事,并且在RDD的源码当中我们找到了下面这段:

  implicit def rddToOrderedRDDFunctions[K : Ordering : ClassTag, V: ClassTag](rdd: RDD[(K, V)])
    : OrderedRDDFunctions[K, V, (K, V)] = {
    new OrderedRDDFunctions[K, V, (K, V)](rdd)
  }

上面我们对scala的implicit做了比较全面的了解,这样的工作,对scala和spark的学习和理解,非常重要。

但是,我要说但是,凡事都有其两面性,implicit在带来代码的紧凑和精炼的同时,负作用就是可读性极差;特别是在工作的初级阶段,我是强烈不建议我们团队内部大量的使用implicit。在我看来,多写两行代码,显式的转换一下,真的不是什么大事!

上述内容就是如何进行scala隐式转换及Spark源码解析,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注创新互联行业资讯频道。


文章题目:如何进行scala隐式转换及Spark源码解析
文章出自:http://pwwzsj.com/article/pjcsjc.html