大数据系列第四课:scala高阶

来源:互联网 发布:论文:浅析淘宝店的运营 编辑:程序博客网 时间:2024/05/17 22:01

第一阶段:Spark streamingspark sqlkafkaspark内核原  理(必须有一个大型项目经验);

第二阶段:spark运行的各种环境,各种故障的解决,性能  优化(精通spark内核、运行原理);

第三阶段:流处理、机器学习为鳌头,需要首先掌握前两个  阶段的内容;

跟随王家林老师的零基础讲解,注重动手实战,成为spark高手,笑傲大数据之林!

第一部分:学习笔记

本期内容:

1 Scala模式匹配彻底详解

2 Scala类型系统彻底详解

3 Spark源码阅读及作业

一、模式匹配和类型

1)模式匹配可以匹配类型、值等

1、值的匹配

def bigData(data:String){data match{case "Spark" =>ptintln("Wow!")case "Hadoop" =>println("OK")case _O =>println(" The others!")  //匹配其他形式的字符串}}bigData("Hadoop") //传进Hadoop后,开始遍历匹配,匹配到后,会停止执行bigData("Flink")  //匹配其他的形式字符串

模式匹配的时候进行判断

def bigData(data:String){data match{case "Spark" =>ptintln("Wow!")case "Hadoop" =>println("OK")case _ if data =="Flink" =>println("Cool")case _ =>println("Something else")}}bigData("Spark")bigData("Flin")     //条件判断,进行分层过滤

用变量名接受了模式匹配输入的内容

def bigData(data:String){data match{case "Spark" =>ptintln("Wow!")case "Hadoop" =>println("OK")case data if data_ =="Flink" =>println("Cool" + data_)case _ =>println("Something else")} //将传进的data赋给变量data_}

2、类型的匹配

import java.io._def exception(e:Exception)e catch{case fileException:FileNotFoundException =>println("File not found:" +fileException)case _:Exception =>ptintln(s"Exception getting thread from excutor SexecutedID",e)}//调用,匹配首先打印Exception,匹配类型exception(new FileNotFoundException("Hello!"))

3、对集合进行匹配

def data(array:Array[String]){array match{case Array("Scala") =>("Scala")  //匹配指定数组中的元素case Array(Spark,hadoop,flink) =>println(spark +":" +hadoop+":" +flink)case Array("Spark", _*) =>println("Spark ...")//匹配以某元素开头的元素case _ =>println("Unknown")    //匹配其他的数组元素}}data(Array("Spark")data(Array("Scala","Spark"),"Kafka")  //匹配将值传给匹配的变量并打印

4、case class

case class person(name:String) //适合并发编程的消息传递

自动生成当前消息的case class的伴生对象case object

(1)case class 相当于Javabin

(2)自己的实例化,调用伴生对象的apply方法,返回一个实例

//case class Worker(id:String,salary:Double) extends Person(name)case class Person //直接定义Personcase class Worker(name:String,salary:Double) extends Personcase class Student(name:String,score:Double) extends Person//定义函数sayHidef sayHi(person:Person){person match{case Student(name,score) =>println("I am a student:" +name + score)case Worker(name,salary) =>println("I am a Worker:" +name + salary)case _ =>println("Unknown!")}}sayHi(Worker("Spark",32)) //传进参数,匹配变量并接收sayHi(Student("Spark",31))

二、类型参数

1、泛型类、函数

class Person[T](val content:T)class Person[T](val content:T){def getContent(id:T) = id + "_" +content}val p = new Person[String]("Spark")  //实例化对象的时候指定泛型类型Stringp.getContent("Scala") //类型控制,这里必须传入String类型

2、类型边界(对类型本身指定边界)

如:大数据Spark工程师,调用spark类型工作,也可以调用其子类型进行工作大数据Spark工程师[ _ <:Spark技能] //这边的上边界就是[Spark技能]

1.class Pair[T <: Comparable[T]](val first : T,val second : T){  2.  def bigger = if(first.compareTo(second) > 0)first else second    3.}  4.class Pair_Lower_Bound[T](val first:T,val second:T){  5.  def replaceFirst[R >: T](newFirst:R)= new Pair_Lower_Bound[R](newFirst,second)  6.}  7.object Typy_Variables_Bounds {  8.  def main(args: Array[String]){  9.    val pair = new Pair("Spark", "Hadoop")  10.    println(pair.bigger)  11.  }  12.}  

上述代码中给泛型类Pair中的类型T一个限定,即类型为T的成员有一个方法为CompareTo,如注释掉的代码会报错,因为不知道firstsecond的具体类型,无法判定firstsecond是否有CompareTo,那么就需要对T有一个限定(对变量类型本身的限定)。具体限定为[T<:Comparable[T]],即T类型为Comparable的子类型(如:compareTo),比较的实现为函数biggerClass replaceFirst[R:>T]说明R类型为T的父类,Pair[T:<ComparableTo[T]]说明T类型为ComparableTo[T]的下界。

3View Bounds视图界定(没有上下边界的类型)&隐式转换

支持对类型本身就行隐式转换(如:工作时可能出错,将其隐式转换为可以运行的状态,运行结束后再重新恢复原来的状态)将指定的类型进行隐式转换,转换的类型可以作为类型上界、下界。

View Bounds语法:<%

1.class Pair_NotPerfect[T <% Comparable[T]](val first : T,val second : T){  2.    def bigger = if(first.compareTo(second) > 0)first else second    3.}  1.val pair = new Pair_NotPerfect("Spark", "Hadoop")  2.println(pair.bigger)  3.  4.val pairInt = new Pair_NotPerfect(3, 5) //Int -> RichInt  5.println(pairInt.bigger) 

试图界定:是指我们可以把具体的传入的T类型的实例转换成Comparable[T]类型,如果comparable[T]类型不是T类型的父类,使用<%的方式可以进行隐式转换。

视图界定与隐式转换的过程:在应用类型T无法满足上界Comparable[T]的时候,使用<%做视图界定,将类型T隐式转换成Comparable[T]的子类型,例如整数类型Int会先变成RichInt类型,RichInt是以Comparable为类型上界的,所以用ComparaTo方法,即RichInt中有ComparaTo方法。

~[K:<% Writable]  //K必须为Writeble类型或者隐式转换为其类型,在上下文中注入隐式值,而且注入的过程是自动的。

class Compare[T :Ordering](val n1:T,val n2:T){ //比较数字大小def bigger(implicit ordered: Ordering[T]) if(ordered.Compare(n1,n2)>0)n1 else n2 }//一定存在一个Ordering 的T类型new Compare[Int](8,3),bigger new Compare[String]("Spark","Hadoop").bigger}

[TOrdering]其中的Ordering为隐式的,也就是Ordering[T];函数bigger中隐式传进一个参数ordered,他是一种上下文界定的方式。

注:String有一个Ordering[String]

        Int 有一个Ordered[Int]

[T:Manifest] //实例化数组Array[T]

4、逆变和协变

C[+T]:如果AB的子类,那么C[A]C[B]的子类。逆变范围小;

C[-T]:如果AB的子类,那么C[B]C[A]的子类。协变范围大;

C[T]:无论AB是什么关系,C[A]C[B]没有从属关系。

class Person[+T]    //强制定义为协变类型

[Dependence[_]] :表示可以为任何类型 相当于[Dependence[T]]  

Manifest:类型分类,上下文界定,有一个Manifest的隐式值,想得到运行时的具体信息,使用Manifest来存储具体的类型,后来演化为ClassTag

abstract class RDD[T: ClassTag](    @transient private var _sc: SparkContext,    @transient private var deps: Seq[Dependency[_]]  )T:ClassTag :运行的时候会有更完善的类型进行匹配import scala.reflect{{{ *   scala> def mkArray[T : ClassTag](elems: T*) = Array[T](elems: _*)  //elems:可变参数 *   mkArray: [T](elems: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]   * 根据运行时的类型进行完善匹配,只有运行的时候知道其类型,定义的时候不知道 *   scala> mkArray(42, 13) *   res0: Array[Int] = Array(42, 13) * *   scala> mkArray("Japan","Brazil","Germany") *   res1: Array[String] = Array(Japan, Brazil, Germany) * }}} *

5、多重界定

1T>:A<:B (T同时拥有上界B和下界A,A是B的子类型)

2T<:A with BTA或者B的子类,with为接口)

3T<%A<%B(视图界定,T即可隐式转换为A并且也可转换为B的类型)

4TAB(上下文界定)

第二部分:

作业:阅读Spark源码 RDDHadoopRDDSparkContextMasterWorker的源码,并分析里面使用的所有的模式匹配和类型参数的内容

/*   * 类型参数的泛型   * 定义了newAPIHadoopFile方法,它有三个类型K,V,F   * 类型K,V,F使用限定,是这三个类型都是NewInputFormat[K, V]的子类型;   * K,V,F的类型上界是NewInputFormat[K, V];   * Hadoop读取文件的时候,限定输入文件的类型为NewInputFormat的子类;   * ClassTag[K],ClassTag[V],ClassTag[F]是具有丰富的上下文信息,运行时推断具体的类型。   * implicit隐式转化   * 类型的上界约束   */  def newAPIHadoopFile[K, V, F <: NewInputFormat[K, V]]      (path: String)      (implicit km: ClassTag[K], vm: ClassTag[V], fm: ClassTag[F]): RDD[(K, V)] = withScope {    newAPIHadoopFile(      path,      fm.runtimeClass.asInstanceOf[Class[F]],      km.runtimeClass.asInstanceOf[Class[K]],      vm.runtimeClass.asInstanceOf[Class[V]])  } /*   * 类型参数的泛型:视图界定(View Bounds)   * 定义了rddToSequenceFileRDDFunctions方法,它有两个类型K,V,它们是Writable类型或者被隐式转换为Writable类型   * 带一个参数rdd,它是带有(K, V)类型的RDD   * 方法返回一个带有类型(K, V)的SequenceFileRDDFunctions   * ClassTag是具有丰富的上下文信息,运行时推断具体的类型。   * implicit隐式转化   */      def rddToSequenceFileRDDFunctions[K <% Writable: ClassTag, V <% Writable: ClassTag](      rdd: RDD[(K, V)]): SequenceFileRDDFunctions[K, V] = {    val kf = implicitly[K => Writable]    val vf = implicitly[V => Writable]    // Set the Writable class to null and `SequenceFileRDDFunctions` will use Reflection to get it    implicit val keyWritableFactory = new WritableFactory[K](_ => null, kf)    implicit val valueWritableFactory = new WritableFactory[V](_ => null, vf)    RDD.rddToSequenceFileRDDFunctions(rdd)  } /*   * 类型参数的泛型:上下文界定   * 定义了rddToSequenceFileRDDFunctions方法,它有两个类型K,V,它们是Writable类型或者被隐式转换为Writable类型   * K : Ordering : ClassTag 表示存在一个隐式值Ordering[K],上下文界定   * 方法返回一个带有类型[K, V, (K, V)] 的OrderedRDDFunctions   * ClassTag是具有丰富的上下文信息,运行时推断具体的类型。   */   @deprecated("Replaced by implicit functions in the RDD companion object. This is " +    "kept here only for backward compatibility.", "1.3.0")  def rddToOrderedRDDFunctions[K : Ordering : ClassTag, V: ClassTag](      rdd: RDD[(K, V)]): OrderedRDDFunctions[K, V, (K, V)] =    RDD.rddToOrderedRDDFunctions(rdd)


















2 0
原创粉丝点击