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

第一阶段: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 //直接定义Person
case class Worker(name:String,salary:Double) extends Person
case class Student(name:String,score:Double) extends Person
//定义函数sayHi
def 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")  //实例化对象的时候指定泛型类型String
p.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)


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值