Scala零基础教学【41-60】
第41讲:List继承体系实现内幕和方法操作源码揭秘
def main(args: Array[String]) {
/**
* List继承体系实现内幕和方法操作源码揭秘
*
* List本身是一个抽象类 定义如下:
* abstract sealed class List[+A] extends AbstractSeq[A]
* with LinearSeq[A]
* with Product
* with GenericTraversableTemplate[A, List]
* with LinearSeqOptimized[A, List[A]]
*
* List下的两个重要的子类Nil和::
* Nil 表示一个空值 定义为一个Cass Object: case object Nil extends List[Nothing]
* :: 定义 final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extends List[B]
*
*/
//这种方式其实是 调用List的伴生对象的apply方法 val list: List[Int]
val list: List[Int] = List(1, 2, 3, 4, 5)
//这是一种"协变"的概念 Int为Any的子类 所以认为List[Int]的具体父类型可以是List[Any]
val listAny: List[Any] = list
println(list.isEmpty)
println(list.head)
println(list.tail)
println(list.length)
println(list.drop(2))
list.map(_ * 2)
}
第42讲:Scala中泛型类、泛型函数、泛型在Spark中的广泛应用
/**
* 定义一个泛型类[]中定义的就是未知的类型 只有赋值使用才能确定具体的类型
*/
class Triple[F, S, T](val first: F, val second: S, val third: T) /**
* Scala中泛型类、泛型函数、泛型在Spark中的广泛应用
*/
object Hello_Type_Parameterization { def main(args: Array[String]) {
//在定义后scala的类型推断会得出triple类型为 Triple[String, Int, Double]
val triple = new Triple("Spark", 3, 3.1415)
//显示声明类型
val bigData = new Triple[String, String, Char]("Spark", "Hadoop", 'R') //定义泛型类型
def getData[T](list : List[T]) = list(list.length / 2)
//List(1)=>"Hadoop"
println(getData(List("Spark", "Hadoop", 'R')))
val f = getData[Int] _
println(f(List(1,2,3,4,5,6)))//5 val queue = Queue(1,2,3,4,5)
val queue_appended = queue enqueue 6
println("queue : " + queue + " " + "queue_appended : " + queue_appended) } }
第43讲:Scala中类型变量Bounds代码实战及其在Spark中的应用源码解析
/**
* 类型的界定
* 这里的[T <: Comparable[T]] 表示类型T必须是Comparable[T]的子类
*/
class Pair[T <: Comparable[T]](val first : T,val second : T){
def bigger = if(first.compareTo(second) > 0)first else second
}
/**
* [R >: T]表示 R类型是T类型的父类
* 类型变量的界定 就R而言 T为R的下界 就T而言 R为T的上界
*
*/
class Pair_Lower_Bound[T](val first:T,val second:T){
def replaceFirst[R >: T](newFirst:R)= new Pair_Lower_Bound[R](newFirst,second)
} object Typy_Variables_Bounds { def main(args: Array[String]){
/**
* 49-57:0-9
* A-Z:66-90
* a-z:97-122
*/
val schar='S'
println(schar.toInt)
println('H'.toInt)
println("Spark".compareTo("Hadoop"))//11
val pair = new Pair("Spark", "Hadoop")
println(pair.bigger)//Spark
}
}
第44讲:Scala中View Bounds代码实战及其在Spark中的应用源码解析
class Pair_NotPerfect2[T <: Comparable[T]](val first : T,val second : T){
def bigger = if(first.compareTo(second) > 0)first else second
}
/**
* 视图界定 <%
*/
/**
* Ordered视图界定
* 上面这种方式的12行first.compareTo(second) > 0 通过compareTo来比较 但是不能直观的像数学比较那样清晰
* Scala提供了Ordered视图界定
* Ordered在Comparable上提供一些关系型的操作符 < > <= >=等
*/
class Pair_NotPerfect[T <% Comparable[T]](val first : T,val second : T){
def bigger = if(first.compareTo(second) > 0)first else second
}
class Pair_Better[T <% Ordered[T]](val first : T,val second : T){
def bigger = if(first > second)first else second
}
object View_Bounds {
def main(args: Array[String]) {
// val pair2 = new Pair_NotPerfect2(1, 3)
// println(pair2.bigger)
val pair = new Pair_NotPerfect("Spark", "Hadoop")
println(pair.bigger)
/*
* 当类型界定为Pair_NotPerfect[T <: Comparable[T]]报错 因为Int本身不是Comparable的子类
*
* 当类型界定为视图界定时 Pair_NotPerfect[T <% Comparable[T]] 就可以正常运行
* 是因为Int本身不是Comparable的子类型 Scala通过"隐式转换"将Int转换成RichInt 而这个类型是Comparable的子类
*/
val pairInt = new Pair_NotPerfect(3, 5) //Int -> RichInt
println(pairInt.bigger)
/**
* 注意:这样定义不是因为String的上界是Ordered[String],String不是Ordered[String]的子类
* 当使用视图界定时 会发生"隐式转换" 把String --> RichString
* 而RichString是Ordered[RichString]的子类型 RichString中是实现了这样的 < > <= >=等方法
* 从而真正是让String类型完成视图界定
*/
val pair_Better_String = new Pair_Better("Java", "Scala") //String -> RichString
println(pair_Better_String.bigger)
val pair_Better_Int = new Pair_Better(20, 12)
println(pair_Better_Int.bigger)
}
}
第45讲:Scala中Context Bounds代码实战及其在Spark中的应用源码解析
/**
* 上下文界定 [T : Ordering] 说明存在一个隐式的值Ordering[T] //implicit ordered: Ordering[T]
*
* Ordering源码声明:
* trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializable
*/
class Pair_Ordering[T : Ordering] (val first : T, val second : T){ //这是一个隐式转换的显式定义 这个函数没有参数 当时函数执行的时候 这个隐式值就会自动传进来
def bigger(implicit ordered: Ordering[T]) = {
if (ordered.compare(first, second) > 0) first else second
}
} object Context_Bounds { def main(args: Array[String]) { val pair = new Pair_Ordering("Spark", "Hadoop")
println(pair.bigger) val pairInt = new Pair_Ordering(3, 5)
println(pairInt.bigger) } }
第46讲: ClassTag 、Manifest、ClassManifest、TypeTag代码实战及其在Spark中的应用源码解析
package com.wanji.scala.type_parameterization import scala.reflect.ClassTag class A[T] /**
* ClassTag 、Manifest、ClassManifest、TypeTag代码实战及其在Spark中的应用源码解析
*
* ClassTag ==> ClassManifest
* TypeTag ==> Manifest
*/ object Manifest_ClassTag { def main(args: Array[String]) { /**
* Q: 可以创建泛型数组吗? 理论上是不可以的,因为没有指定具体的,在Scala程序运行中,数组必须有具体的类型,没有否无法创建的相应的数组
*
* 引出Manifest的概念可以创建泛型数组
* [T : Manifest]这样的写法被称之为Manifest上下文界定 实质上这是需要一个Manifest[T]类型的隐式对象 这又是一个"隐式转换"的过程
* 通过这个隐式的值来辅助构建泛型数组,来确定T的具体类型
* 所以在创建泛型函数时 需要Manifest的类型来辅助构建泛型数组,借助Manifest类型对象来指定泛型数组具体的类型
*
* 通过Manifest[T]可以记录T的类型 在实际运行的时候我们获取T具体的类型
**/ def arrayMake[T: Manifest](first: T, second: T) = {
val r = new Array[T](2)
r(0) = first
r(1) = second
r
} arrayMake(1, 2).foreach(println) /**
* [T : ClassTag]这种写法说明 当这个函数在运行时 对存在一个ClassTag[T]一个隐式值 这种方式是最常用的
*/
def mkArray[T: ClassTag](elems: T*) = Array[T](elems: _*) mkArray(42, 13).foreach(println)
mkArray("Japan", "Brazil", "Germany").foreach(println) /**
* Manifest的原生写法,不推荐
*/
def manif[T](x: List[T])(implicit m: Manifest[T]) = {
if (m <:< manifest[String]) //<:< 表示m是manifest[String]类型
println("List strings")
else
println("Some other type")
} manif(List("Spark", "Hadoop"))
manif(List(1, 2))
manif(List("Scala", 3))
val m = manifest[A[String]]
println(m)
val cm = classManifest[A[String]]
println(cm)
} }
第47讲:Scala多重界定代码实战及其在Spark中的应用源码解析
class M_A[T]
class M_B[T] /**
* scala多重界定代码实战及其在Spark中的应用源码解析
*
* T<:A with B
* T是A或者B的子类
*
* T>:A with B
* A或者B是T的子类
*
* T>:A <:B (写法上 下界必须在前边 上届必须在后面)
* T同时拥有下界A和上界B(A必须为B的子类型) 但是T不能同时拥有多个上界或者多个下界
*
* T:A:B(上下文界定)
*
* T <% A <% B(视图界定) T必须能够同时转化为A和B的要求
* T可以< 同时>拥有多个视图界定
* T可以通过"隐式转换"为A 也可以"隐式转换"为B
*
*/ object Multiple_Bounds { def main(args: Array[String]) {
implicit val a = new M_A[Int]
implicit val b = new M_B[Int]
def foo[ T : M_A : M_B ](i:T) = println("OK")
foo(2) } }
第48讲:Scala类型约束代码实战及其在Spark中的应用源码解析
/**
* Scala类型约束代码实战及其在Spark中的应用源码解析
*
* A =:= B 表示A类型等同于B类型
* A <:< B 表示A类型是B类型的子类型
*/ object Type_Contraints { def main(args: Array[String]){ def rocky[T](i:T)(implicit ev: T <:< java.io.Serializable) {
print("Life is short,you need spark!") }
rocky("Spark")
} }
第49讲:Scala中Variance代码实战及其在Spark中的应用源码解析
/**
* Scala中Variance代码实战及其在Spark中的应用源码解析
*
* 通俗讲
* B是A的子类 ==>List[B]是List[A]的子类(与具体元素的继承关系同向) 这样称之为"协变"
* B是A的子类 ==>List[A]是List[B]的子类(与具体元素的继承关系反向) 这样称之为"逆变"
* 如果支持上面的这种概念 就被称之为"Variance" 否则称之为"inVariance"
*
* 事实上Java不支持在定义一个类型时声明为这样的"Variance"
* e.g. String是object的子类,List<String> 却不是 List<Object>的子类
* 但是Java中是存在这样的痕迹的 比如:
* List<? extends Object> list = new ArrayList<String>()
* 在Scala中也是可以向上面这样写的:
* val list: List[_ <: Any] = List[String]("Spark", "Hadoop")
*
* 事实上Java支持在使用的时候 可以这样去定义,在声明的时候不支持,但是Scala中的可以
*
* Scala中 在声明时留意表达这种Variance的关系
* 形如class C[+T] “+”表示"协变" 也就是说若B为A的子类型 则C[B]是C[A]的子类型
* class C[-T] “-”表示"协变" 也就是说若B为A的子类型 则C[A]是C[B]的子类型
*
*/ class Person
class Student extends Person
class C[+T](val args: T)
class S[+T](arg : T) extends C[T](arg)
trait Friend[-T]{
def makeFriend(somebody: T)
} object Variance {
def makeFriendWithYou(s: Student, f: Friend[Student]){f.makeFriend(s)}
def main(args: Array[String]) {
val value : C[Person] = new C[Student](new Student) // List<? extends Oject> list = new ArrayList<String>()
val list : List[_ <: Any] = List[String]("Spark")
} }
第50讲:Scala中Variance变化点及其在Spark中的应用源码解析
package com.wanji.scala.type_parameterization //class P[+T](val first: T, val second: T)
class P[+T](val first: T, val second: T){
// def replaceFirst(newFirst: T) = new P[T](newFirst, second)
//方法是泛型的 方法的参数是逆变点 返回值是协变的协变点
def replaceFirst[R >: T](newFirst: R) = new P[R](newFirst, second)
} object Variant_Positions { def main(args: Array[String]) { } }
第51讲:Scala中链式调用风格的实现代码实战及其在Spark编程中的广泛运用
package com.wanji.scala.type_parameterization
class Animal { def breathe:this.type=this }
class Cat extends Animal { def eat :this.type= this }
object Singleton_Types {
def main(args: Array[String]): Unit = {
/* * 代码2 报错
* * cat.breathe 返回的是Animal的this Animal实例没有eat方法 所以报错
* */
/*
* * 为了到达链式调用 采用代码1
* * 注意:this.type = this *
* * Q:type是指什么?
* * A:在Scala中 任何类对象都有一个type属性
* * 当执行cat.breathe其实返回的Cat类实例的type 而这个type有eat方法
* */
val cat = new Cat
cat.breathe.eat
}
}
第52讲:Scala中路径依赖代码实战详解
val outer = new Outer
val inner = new outer.Inner /**
* Scala中的内部类 必须依赖于外部类的实例 而外部类的实例各不相同
* 所以被之为这种对于外部类的依赖为"路径依赖"
* 所以不同的路径代表不同的类型
*/
val inner2: outer.Inner = new outer.Inner
println(inner)
println(inner2) val o1 = new Outer
val o2 = new Outer
//报错 o1与o2不是同样的实例
//val i2: o2.Inner = new o1.Inner
val i: Outer#Inner = new o1.Inner
//o1.Inner是Outer#Inner的子类。外部类#内部类:类型投影(不同外部类实例,但内部类是同一类型)。
//虽有路径依赖,但还想用Java风格就用这种表达方式。
例如:
有2个社交网络,facebook和twitter,有很多会员,是依赖于各自网络的。
就算是同一个人在这两个不同的社交网络里,也是不同的实例。
spark编程中,数据是分布式的,会分成很多的片,不同分片的数据从理论上讲是一样的(当然数据内容不同),也就是说,属于同样类型的数据,但是我们写代码时,处理数据时,还是处理属于每一个blog或split分片的结果。从这个角度看,也可看作是路径依赖。
第53讲:Scala中结构类型实战详解
/**
* Scala中结构类型实战详解
* 结构类型不关心传入的类型 只关心传入的对象具有某种行为
*/
class Structural {
def open()=print("A class instance Opened")
} object Structural__Type { def main(args: Array[String]){
init(new { def open()=println("Opened") }) /**
* type的作用是把“=”右边的内容起个别名
*/
type X = { def open():Unit } def init(res:X) = res.open init(new { def open()=println("Opened again") })
/**
* 定义单例对象
*/
object A {
def open() {println("A single object Opened")}
}
init(A) val structural = new Structural
init(structural) } /**
* 从函数的定义来看,并不关心传入的对象为何,只关心传入的对象必须具有open方法
*
*/
def init( res: {def open():Unit} ) {
res.open
}
}
第54讲:Scala中复合类型实战详解
trait Compound_Type1;
trait Compound_Type2;
class Compound_Type extends Compound_Type1 with Compound_Type2 object Compound_Type {
def compound_Type(x: Compound_Type1 with Compound_Type2) = {
println("Compound Type in global method")
} def main(args: Array[String]) { compound_Type(new Compound_Type1 with Compound_Type2)
object compound_Type_oject extends Compound_Type1 with Compound_Type2
compound_Type(compound_Type_oject) type compound_Type_Alias = Compound_Type1 with Compound_Type2
def compound_Type_Local(x:compound_Type_Alias) = println("Compound Type in local method")
val compound_Type_Class = new Compound_Type
compound_Type_Local(compound_Type_Class) type Scala = Compound_Type1 with Compound_Type2 { def init():Unit }
} }
第55讲:Scala中Infix Type实战详解
def main(args: Array[String]) {
object Log { def >>:(data:String):Log.type = { println(data); Log } }
"Hadoop" >>: "Spark" >>: Log
val list = List()
val newList = "A" :: "B" :: list
println(newList)
class Infix_Type[A,B]
val infix: Int Infix_Type String = null
val infix1: Infix_Type[Int, String] = null
case class Cons(first:String,second:String)
val case_class = Cons("one", "two")
case_class match { case "one" Cons "two" => println("Spark!!!") } //unapply
}
第56讲:Scala中Self Types实战详解
/**
* Scala中Self Types实战详解
*/
class Self {
self => //用法一:self => 表示this的别名 这是self和this等价 注意不能使用this作为别名
val tmp="Scala"
def foo = self.tmp + this.tmp
}
trait S1
class S2 {
/**
* 用法二:
* 这种方式和self =>并不一样 将S1比如为摸个trait是
* 这种this:S1为this的别名时 有一个强制的要求
* (1)在该类型实例化时 必须混入这个类型 即: val c = new S2 with S1 否则报错
* (2)在继承该类的子类是 也必须混入 比如:class S3 extends S2 with S1 若不混入with S1则报错
* */ this:S1 =>
}
class S3 extends S2 with S1 trait T { this:S1 => }
object S4 extends T with S1
object Self_Types { def main(args: Array[String]) {
class Outer { outer =>
val v1 = "Spark"
class Inner {
/**
* 用法三:
* 这里内部类需要访问外部类成员和方法
* 通过定义了outer =>代替了外部类Outer的this
* 在内部类理由直接引用不需要考虑this是谁this
* 这是使用这种方式声明的好处
* 如果写成println(this.v1)则报错 因为这个this代表了Inner的this
* 下面的三种写法都是正确的 */ println(outer.v1)
println(v1)
println(Outer.this.v1)
}
}
val c = new S2 with S1
} }
第57讲:Scala中Dependency Injection实战详解
trait Logger {
def log (msg : String) }
trait Auth {
auth : Logger =>
def act(msg : String) {
log(msg)
}
}
object DI extends Auth with Logger {
override def log(msg : String) = println(msg); }
object Dependency_Injection {
def main(args: Array[String]) {
DI.act("I hope you'll like it")
}
}
第58讲:Scala中Abstract Types实战详解
import scala.io.Source
import scala.io.BufferedSource trait Reader{
/**
* 用type关键字 声明一个In类型(称为"抽象类型")
* 但是没有指明具体类型是什么类型 需要在它的实现类中指明具体的类型
* 在声明抽象类型时 可以对类型进行限定
*/
type In <: java.io.Serializable
type Contents /**
*在抽象对的可以使用抽象类型
*/
def read(in: In): Contents
}
class FileReader extends Reader {
type In = String //实现中具体的类型
type Contents = BufferedSource //type Contents=Contents
override def read(name: In) = Source.fromFile(name)
}
object Abstract_Types { def main(args: Array[String]) {
val fileReader = new FileReader
val content = fileReader.read("F:\\1.txt")
for (line <- content.getLines){
println(line)
}
} }
第59讲:Scala中隐式转换初体验实战详解以及隐式转换在Spark中的应用源码解析
import scala.io.Source
import java.io.File /**
* Scala中隐式转换初体验实战详解以及隐式转换在Spark中的应用源码解析
*/
//这里的RichFile相当于File的增强类 需要的将要增强的类作为参数传入构造器中
class RichFile(val file:File){
def read = Source.fromFile(file.getPath()).mkString
} object Context{
//File --> RichFile
//implicit是隐式转换的关键字 这里定义一个隐式转换函数把当前类型转换成增强的类型
implicit def file2RichFile(file:File)= new RichFile(file) //File -> RichFile
}
object Hello_Implicit_Conversions { def main(args: Array[String]) {
import Context.file2RichFile
//File类本身没有read方法 通过隐式转换完成
//这里的read方法是RichFile类中的方法 需要通过隐式转换File --> RichFile
println(new File("F:\\1.txt").read)
}
}
第60讲:Scala中隐式参数实战详解以及隐式参数在Spark中的应用源码解析
/**
* Scala中隐式参数实战详解以及隐式参数在Spark中的应用源码解析
*/
object Context_Implicits{
implicit val default:String = "Flink"
} object Param{
def print(content:String)(implicit language:String){
println(language+":"+content)
}
}
object Implicit_Parameters { def main(args: Array[String]) {
Param.print("Spark")("Scala") import Context_Implicits._
//隐式参数没有传值,编译器会在全局范围内搜索 有没有implicit String类型的隐式值 并传入
Param.print("Hadoop")
}
}
Scala零基础教学【41-60】的更多相关文章
- Scala零基础教学【1-20】
基于王家林老师的Spark教程——共计111讲的<Scala零基础教学> 计划在9月24日内完成(中秋节假期之内) 目前18号初步学习到25讲,平均每天大约完成15讲,望各位监督. 初步计 ...
- Scala零基础教学【102-111】Akka 实战-深入解析
第102讲:通过案例解析Akka中的Actor运行机制以及Actor的生命周期 Actor是构建akka程序的核心基石,akka中actor提供了构建可伸缩的,容错的,分布式的应用程序的基本抽象, a ...
- Scala零基础教学【90-101】Akka 实战-代码实现
第90讲:基于Scala的Actor之上的分布式并发消息驱动框架Akka初体验 akka在业界使用非常广泛 spark背后就是由akka驱动的 要写消息驱动的编程模型都首推akka 下面将用30讲讲解 ...
- Scala零基础教学【81-89】
第81讲:Scala中List的构造是的类型约束逆变.协变.下界详解 首先复习四个概念——协变.逆变.上界.下界 对于一个带类型参数的类型,比如 List[T]: 如果对A及其子类型B,满足 List ...
- Scala零基础教学【61-80】
第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析 第62讲:Scala中上下文界定内幕中的隐式参数与隐式参数的实战详解及其在Spark中的应用源码解析 /** ...
- Scala零基础教学【21-40】
第24讲:Scala中SAM转换实战详解 SAM:single abstract method 单个抽象方法 我们想传入一个函数来指明另一个函数具体化的工作细节,但是重复的样板代码很多. 我们不关 ...
- Android零基础入门第60节:日历视图CalendarView和定时器Chronometer
原文:Android零基础入门第60节:日历视图CalendarView和定时器Chronometer 上一期学习了AnalogClock.DigitalClock和TextClock时钟组件,本期继 ...
- Scala实战高手****第2课:Scala零基础实战入门的第一堂课及如何成为Scala高手
val声明的不可变的战略意义:1.函数式编程中要求值不可变,val天然符合这一特性:2.在分布式系统中,一般都要求值不可变,这样才能够要求分布式系统的设计和实现,同时拥有更高的效率,val声明的内容都 ...
- Android零基础入门第64节:揭开RecyclerView庐山真面目
原文:Android零基础入门第64节:揭开RecyclerView庐山真面目 大家还记得之前在第38期~第50期都在学习列表控件吗,其中用了8期讲ListView的使用,相信都已经掌握好了吧.那么本 ...
随机推荐
- python 闭包与装饰器
1.闭包--返回子函数名 作用:使用子函数之外的父函数的变量 闭包就是你调用了一个函数a,这个函数a反悔了一个子函数名b,这个返回的函数b就叫做闭包 代码举例 def a(): test = 'aa' ...
- API教程
www.yuanjiaocheng.net http://www.yuanjiaocheng.net/webapi/test-webapi.html
- xml数据格式
<?xml version="1.0" encoding="utf-8"?> <country> <name>中国</ ...
- DOM 2
1.对文档的信息进行检索常用的方法: getElementById; getElementsByTagName; getAttribute;//得到的是属性值 2把需要的信息添加到DOM中常用的方法: ...
- Android百度地图的使用
做关于位置或者定位的app的时候免不了使用地图功能,本人最近由于项目的需求需要使用百度地图的一些功能,所以这几天研究了一下,现写一下blog记录一下,欢迎大家评论指正! 一.申请AK(API Key) ...
- IE设置信任站点和安全级别(bat文件)
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Ranges\Range1 ...
- 【BZOJ1146】【CTSC2008】网络管理 [整体二分]
网络管理 Time Limit: 50 Sec Memory Limit: 162 MB[Submit][Status][Discuss] Description M公司是一个非常庞大的跨国公司,在 ...
- xampp命令
XAMPP命令安装 XAMPPtar xvfz xampp-linux-1.6.4.tar.gz -C /opt启动 XAMPP/opt/lampp/lampp start停止 XAMPP/opt/l ...
- 【转】vs2015一键卸载干净
插件是国外的一位同行写的,偶然在网上发现感觉挺好用,分享一下. 第二步.下载工具并解压 网盘下载地址:https://pan.baidu.com/s/1eSHRYxW 也可以在Github上下载最新版 ...
- Web Application Vulnerabilities and Potential Problem Due to Bad Design
web应用设计中不安全的设计及潜在的风险: REF: https://msdn.microsoft.com/en-us/library/ff648647.aspx