object func {
def main(args:Array[String]):Unit={
//函数赋值给变量时, 必须在函数后面加上空格和下划线。
def sayHello(name: String) { println("Hello, " + name) }
val sayHelloFunc = sayHello _
sayHelloFunc("leo")
//Scala定义匿名函数的语法规则: (参数名: 参数类型) => 函数体
val sayHelloFunc1 = (name: String) => println("Hello, " + name)
sayHelloFunc1("leo")
//接收其他函数作为参数的函数, 也被称作高阶函数( higher-order function)
def greeting(func: (String) => Unit, name: String) { func(name) }
greeting(sayHelloFunc1, "leo")
//高阶函数的另外一个功能是将函数作为返回值
def getGreetingFunc(msg: String) = (name: String) => println(msg + ", " + name)
val greetingFunc = getGreetingFunc("hello")
greetingFunc("leo")
//高阶函数可以自动推断出参数类型, 而不需要写明类型。
// 而且对于只有一个参数的函数, 还可以省去其小括号。
def greeting1(func: (String) => Unit, name: String) { func(name) }
greeting1((name: String) => println("Hello, " + name), "leo")
greeting1((name) => println("Hello, " + name), "leo")
greeting1(name => println("Hello, " + name), "leo")
//map: 对传入的每个元素都进行映射, 返回一个处理后的元素
println(Array(1, 2, 3, 4, 5).map(2 * _))
//foreach: 对传入的每个元素都进行处理,但是没有返回值
(1 to 9).map("*" * _).foreach(println _)
//filter: 对传入的每个元素都进行条件判断, 如果对元素返回true,则保留该元素, 否则过滤掉该元素
println((1 to 20).filter(_ % 2 == 0))
//reduceLeft: 从左侧元素开始, 进行reduce操作, 即先对元素1和元素2
// 进行处理, 然后将结果与元素3处理, 再将结果与元素4处理, 依次类推,
// 右面这个操作就相当于1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9
println((1 to 9).reduceLeft( _ * _))
//sortWith: 对元素进行两两相比, 进行排序
println(Array(3, 2, 5, 4, 10, 1).sortWith(_ < _))
/***
* List代表一个不可变的列表, List的创建, val list = List(1, 2, 3, 4)
List有head和tail,head代表List的第一个元素,tail代表第一个元素之后的所有元素, list.hea,list.tail
List有特殊的::操作符, 可以用于将head和tail合并成一个List, 0 :: list
如果一个List只有一个元素, 那么它的head就是这个元素, 它的tail是Nil。
Nil是一个空的List, 定义为List[Nothing]。
*/
val list = List(1, 2, 3, 4)
for(i<-list){println(i)}
def decorator(list: List[Int], prefix: String) {
if (list != Nil) {
println(prefix + list.head)
decorator(list.tail, prefix)
}
}
decorator(list,"list-")
val Linklist= scala.collection.mutable.LinkedList(1, 2, 3, 4, 5)
var currentList =Linklist
while (currentList != Nil) {
currentList.elem = currentList.elem * 2
currentList = currentList.next
print(currentList)
}
/***
* Set代表一个没有重复元素的集合
将重复元素加入Set是没有用的, 比如val s = Set(1, 2, 3); s + 1; s + 4
而且Set是不保证插入顺序的, 也就是说, Set中的元素是乱序的,
*/
val s = new scala.collection.mutable.HashSet[Int](); s += 1; s += 2; s += 5
print(s)
//为List中每个元素都添加一个前缀
List("Leo", "Jen", "Peter", "Jack").map("name is " + _).foreach(println _)
//将List中的多行句子拆分成单词
List("Hello World", "You Me").flatMap(_.split(" ")).foreach(println _)
//打印List中的每个单词
List("I", "have", "a", "beautiful", "house").foreach(println(_))
//对学生姓名和学生成绩进行关联
List("Leo", "Jen", "Peter", "Jack").zip(List(100, 90, 75, 83)).foreach(println _)
//统计多个文本内的单词总数
val lines01 = scala.io.Source.fromFile("D:\\workspace\\scala\\test01.txt").mkString
val lines02 = scala.io.Source.fromFile("D:\\workspace\\scala\\test02.txt").mkString
val lines = List(lines01, lines02)
println(lines.flatMap(_.split(" ")).map((_, 1)).map(_._2).reduceLeft(_ + _))
/***
* 模式匹配, 其实类似于Java中的swich case语法, 即对一个值进行条件判断,
* 然后针对不同的条件, 进行不同的处理。
但是Scala的模式匹配的功能比Java的swich case语法的功能要强大地多,
Java的swich case语法只能对值进行匹配。
Scala的模式匹配除了可以对值进行匹配之外, 还可以对类型进行匹配、
对Array和List的元素情况进行匹配、 对case class( 样例类) 进行匹配、 甚至对有值或没值( Option)进行匹配。
对于Spark来说,Scala的模式匹配功能也是极其重要的,在Spark源码中大量地使用了模式匹配功能
*/
//Scala是没有Java中的switch case语法的, 相对应的, Scala提供了更加强大的match case语法, 即模式匹配。
//Scala的match case与Java的switch case最大的不同点在于, Java的switch case仅能匹配变量的值, 比1、 2、3等; 而Scala的match case可以匹配各种情况, 比如变量的类型、 集合的元素、 有值或无值。
//match case的语法如下: 变量 match { case 值 => 代码 }。
//此外, match case中, 只要一个case分支满足并处理了, 就不会继续判断下一个case分支了。
//( 与Java不同, java的switch case需要用break阻止)
//match case语法最基本的应用, 就是对变量的值进行模式匹配
def judgeGrade(grade: String) {
grade match {
case "A" => println("Excellent")
case "B" => println("Good")
case "C" => println("Just so so")
case _ => println("you need work harder")
}
}
judgeGrade("A")
//Scala的模式匹配语法, 有一个特点在于, 可以在case后的条件判断中, 不仅仅只是提供一个值,
//而是可以在值后面再加一个if守卫, 进行双重过滤。
def judgeGrade1(name: String, grade: String) {
grade match {
case "A" => println(name + ", you are excellent")
case "B" => println(name + ", you are good")
case "C" => println(name + ", you are just so so")
case _ if name == "leo" => println(name + ", you are a good boy, come on")
case _ => println("you need to work harder")
}
}
judgeGrade1("leo","D")
//在模式匹配中进行变量赋值
//Scala的模式匹配语法,有一个特点在于,可以将模式匹配的默认情况,下划线,替换为一个变量名
//此时模式匹配语法就会将要匹配的值赋值给这个变量,从而可以在后面的处理语句中使用要匹配的值
def judgeGrade2(name: String, grade: String) {
grade match {
case "A" => println(name + ", you are excellent")
case "B" => println(name + ", you are good")
case "C" => println(name + ", you are just so so")
case _grade if name == "leo" => println(name + ", " +
"you are a good boy, come on, your grade is " + _grade)
case _grade => println("you need to work harder, your grade is " + _grade)
}
}
judgeGrade2("leo","90")
//Scala的模式匹配一个强大之处就在于, 可以直接匹配类型, 而不是值。
//这点是Java的switch case绝对做不到的。
// 匹配类型的话, 需要用“ case变量:类型
//=> 代码” 这种语法, 而不是匹配值的“ case 值 => 代码” 这种语法。
import java.io._
def processException(e: Exception) {
e match {
case e1: IllegalArgumentException => println("you have illegal arguments! exception is: " + e1)
case e2: FileNotFoundException => println("cannot find the file you need read or write!, exception is: " + e2)
case e3: IOException => println("you got an error while you were doing IO operation! exception is: " + e3)
case _: Exception => println("cannot know which exception you have!" )
}
}
processException(_: Exception);
//对Array进行模式匹配, 分别可以匹配:
//带有指定元素的数组、 带有指定个数元素的数组、 以某元素打头的数组
def greeting2(arr: Array[String]) {
arr match {
case Array("Leo") => println("Hi, Leo!")
case Array(girl1, girl2, girl3) => println("Hi, "+girl1 + " and " + girl2 + " and " + girl3)
case Array("Leo", _*) => println("Hello, Leo")
case _ => println("hey, who are you?")
}
}
greeting2(Array("yaoyao1","yaoyao2","yaoyao3"))
//对List进行模式匹配, 与Array类似, 但是需要使用List特有的::操作符
def greeting3(list: List[String]) {
list match {
case "Leo" :: Nil => println("Hi, Leo!")
case girl1 :: girl2 :: girl3 :: Nil => println("Hi, " + girl1 + " and " + girl2 + " and " + girl3)
case "Leo" :: tail => println("Hi, Leo.")
case _ => println("hey, who are you?")
}
}
greeting3(List("yaoyao1","yaoyao2","yaoyao3"))
//Scala中提供了一种特殊的类, 用case class进行声明, 中文也可以称作样例类。
//case class其实有点类似于Java中的JavaBean的概念, 即只定义field, 并且由Scala编译时
//自动提供getter和setter方法, 但是没有method。
//case class的主构造函数接收的参数通常不需要使用var或val修饰, Scala自动就会使用 val修饰。
//Scala自动为case class定义了伴生对象, 也就是object, 并且定义了apply()方法, 该方
//法接收主构造函数中相同的参数, 并返回case class对象
class Person
case class Teacher(name: String, subject: String) extends Person
case class Student(name: String, classroom: String) extends Person
def judgeIdentify(p: Person) {
p match {
case Teacher(name, subject) => println("Teacher, name is " + name + ", subject is " + subject)
case Student(name, classroom) => println("Student, name is " + name + ", classroom is " +
classroom)
case _ => println("Illegal access, please go out of the school!")
}
}
judgeIdentify(new Teacher("yaoyao","youdian"))
judgeIdentify(new Student("yaoyao","youdian"))
//Scala有一种特殊的类型, 叫做Option。
//Option有两种值, 一种是Some, 表示有值, 一种是None, 表示没有值。
//Option通常会用于模式匹配中, 用于判断某个变量是有值还是没有值, 这比null来的更加简洁明了
val grades = Map("Leo" -> "A", "Jack" -> "B", "Jen" -> "C")
def getGrade(name: String) {
val grade = grades.get(name)
grade match {
case Some(grade) => println("your grade is " + grade)
case None => println("Sorry!")
}
}
getGrade("Leo")
getGrade("Le")
}
}
Hello, leo
Hello, leo
Hello, leo
hello, leo
Hello, leo
Hello, leo
Hello, leo
[I@11438d26
*
**
***
****
*****
******
*******
********
*********
Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
362880
[I@29b5cd00
1
2
3
4
list-1
list-2
list-3
list-4
LinkedList(2, 3, 4, 5)LinkedList(3, 4, 5)LinkedList(4, 5)LinkedList(5)LinkedList()Set(1, 5, 2)name is Leo
name is Jen
name is Peter
name is Jack
Hello
World
You
Me
I
have
a
beautiful
house
(Leo,100)
(Jen,90)
(Peter,75)
(Jack,83)
2
Excellent
leo, you are a good boy, come on
leo, you are a good boy, come on, your grade is 90
Hi, yaoyao1 and yaoyao2 and yaoyao3
Hi, yaoyao1 and yaoyao2 and yaoyao3
Teacher, name is yaoyao, subject is youdian
Student, name is yaoyao, classroom is youdian
your grade is A
Sorry!
Process finished with exit code 0
//泛型类
class Student[T](val local:T){
def getSchool(xf:T)="Student-"+xf+"-"+local
}
//斜边类
class Master
class Professional extends Master
class Card[+T](val name: String) {
def enterMeet(card: Card[Master]): Unit = {
println("welcome to have this meeting!")
}
}
//隐式转换类
class Num {}
class richNum(num:Num){
def richInfo(){
println("This is richnum project")
}
}
object T {
//定义一个名称为num2richNum的隐式函数
implicit def num2richNum(num:Num)=new richNum(num)
implicit def int2String(i:Int)=i.toString()
def main(args:Array[String]):Unit={
/***
* 泛型类, 顾名思义, 其实就是在类的声明中, 定义一些泛型类型,
* 然后在类内部, 比如字段或者方法, 就可以使用这些泛型类型。
* 使用泛型类, 通常是需要对类中的某些成员, 比如某些字段和方法中的参数或变量,
* 进行统一的类型限制, 这样可以保证程序更好的健壮性和稳定性。如果不使用泛型进行统一的类型限制,
* 那么在后期程序运行过程中, 难免会出现问题, 比如传入了不希望的类型,导致程序出问题。
* 在使用类的时候, 比如创建类的对象, 将类型参数替换为实际的类型, 即可。
* Scala自动推断泛型类型特性: 直接给使用了泛型类型的字段赋值时, Scala会自动进行类型推断。
*/
//新生报到, 每个学生来自不同的地方, id可能是Int, 可能是String
val s = new Student[Int](27)
println(s.getSchool(11003802))
/***
* 泛型函数,与泛型类类似,可以给某个函数在声明时指定泛型类型,
* 然后在函数体内, 多个变量或者返回值之间, 就可以使用泛型类型进行声明,
* 从而对某个特殊的变量, 或者多个变量, 进行强制性的类型限制。与泛型类一样,
* 你可以通过给使用了泛型类型的变量传递值来让Scala自动推断泛型的实际类型,
* 也可以在调用函数时, 手动指定泛型类型。
*/
//卡片售卖机, 可以指定卡片的内容, 内容可以是String类型或Int类型
def getCard[T](content: T) = {
if (content.isInstanceOf[Int]) "card: 001, " + content
else if (content.isInstanceOf[String]) "card: this is your card, " + content
else "card: " + content
}
println(getCard[String]("hello world"))
println(getCard[Int](001))
/***
* Scala的协变和逆变是非常有特色的! 完全解决了Java中的泛型的一大缺憾!
* 举例来说, Java中, 如果有Professional是Master的子类,
* 那么Card[Professionnal]是不是Card[Master]的子类?
* 答案是: 不是。 因此对于开发程序造成了很多的麻烦。
* 而Scala中, 只要灵活使用协变和逆变, 就可以解决Java泛型的问题。
*/
//进入会场,大师以及大师级别以下的名片都可以进入会场
val master = new Card[Master]("leo")
val profession = new Card[Professional]("hehe")
master.enterMeet(master)
profession.enterMeet(profession)
/***
* 它可以允许你手动指定, 将某种类型的对象转换成其他类型的对象。
* 通过这些功能, 可以实现非常强大, 而且特殊的功能。
* Scala的隐式转换, 其实最核心的就是定义隐式转换函数, 即implicit conversion function。
* 定义的隐式转换函数, 只要在编写的程序内引入, 就会被Scala自动使用。
* Scala会根据隐式转换函数的签名, 在程序中使用隐式转换函数接收的参数类型定义的对象时,
* 自动将其传入隐式转换函数, 转换为另外一种类型的对象并返回。 这就是“隐式转换” 。
*/
//隐式转换——隐式函数
val num = new Num
num.richInfo()
/***
* 代码中调用了String类型的length方法,Int类型本身没有length方法,但是在
* 可用范围内定义了可以把Int转换为String的隐式函数int2String,因此函数编译通过并运行出正
*/
println(2341.length())
//闭包最简洁的解释: 函数在变量不处于其有效作用域时, 还能够对变量进行访问, 即为闭包
def getGreetingFunc(msg: String) = (name: String) => println(msg + ", " + name)
var greetingFuncHello =getGreetingFunc("hello")
var greetingFuncHi =getGreetingFunc("hi")
println(greetingFuncHello,greetingFuncHi)
//两次调用getGreetingFunc函数, 传入不同的msg, 并创建不同的函数返回。
//但是, msg只是一个局部变量, 这种变量超出了其作用域, 还可以使用的情况, 即为闭包。
//Curring柯里华函数, 指的是, 将原来接收两个参数的一个函数, 转换为两个函数,
//第一个函数接收原先的第一个参数, 然后返回接收原先第二个参数的第二个函数。
//在函数调用的过程中, 就变为了两个函数连续调用的形式。
def sum(a: Int, b: Int) = a + b
println(sum(1, 1))
def sum3(a: Int)(b: Int) = a + b
println(sum3(1)(1))
/***
* Scala的Actor类似于Java中的多线程编程。 但是不同的是, Scala的Actor提供的模型与多线程有所不同。
* Scala的Actor尽可能地避免锁和共享状态, 从而避免多线程并发时出现资源争用的情况,
* 进而提升多线程编程的性能。 此外, Scala Actor的这种模型还可以避免死锁等一系列传统多线程编程的问题。
* Spark中使用的分布式多线程框架, 是Akka。 Akka也实现了类似Scala Actor的模型, 其核心概念
* 同样也是Actor。 因此只要掌握了Scala Actor, 那么在Spark源码研究时, 至少即可看明白Akka
* Actor相关的代码。 但是, 换一句话说, 由于Spark内部有大量的Akka Actor的使用, 因此对于
* Scala Actor也至少必须掌握, 这样才能学习Spark源码。
*/
/***
* Actor的创建、 启动和消息收发
* Scala提供了Actor trait来让我们更方便地进行actor多线程编程, Actor trait就类似于
* Java中的Thread和Runnable一样, 是基础的多线程基类和接口。
* 我们只要重写Actor trait的act方法, 即可实现自己的线程执行体, 与Java中重写run方法类似。
* 此外, 使用start()方法启动actor; 使用 ! 符号, 向actor发送消息;
* actor内部使用receive和模式匹配接收消息
*/
}
}
Student-11003802-27
card: this is your card, hello world
card: 001, 1
welcome to have this meeting!
welcome to have this meeting!
This is richnum project
4
(<function1>,<function1>)
2
2
Process finished with exit code 0