Spark记录-Scala程序例子(函数/List/match/option/泛型/隐式转换)
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
Spark记录-Scala程序例子(函数/List/match/option/泛型/隐式转换)的更多相关文章
- Scala入门系列(十二):隐式转换
引言 Scala提供的隐式转换和隐式参数功能,是非常有特色的功能.是Java等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象.通过这些功能可以实现非常强大而且特殊的功 ...
- 02.Scala高级特性:第6节 高阶函数;第7节 隐式转换和隐式参数
Scala高级特性 1. 课程目标 1.1. 目标一:深入理解高阶函数 1.2. 目标二:深入理解隐式转换 2. 高阶函数 2.1. 概念 Scala混合了面向对象和函数式的特 ...
- Scala入门到精通——第十九节 隐式转换与隐式參数(二)
作者:摇摆少年梦 配套视频地址:http://www.xuetuwuyou.com/course/12 本节主要内容 隐式參数中的隐式转换 函数中隐式參数使用概要 隐式转换问题梳理 1. 隐式參数中的 ...
- Spark基础-scala学习(八、隐式转换与隐式参数)
大纲 隐式转换 使用隐式转换加强现有类型 导入隐式转换函数 隐式转换的发生时机 隐式参数 隐式转换 要实现隐式转换,只要程序可见的范围内定义隐式转换函数即可.Scala会自动使用隐式转换函数.隐式转换 ...
- Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、
1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...
- 深入理解Scala的隐式转换系统
摘要: 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码. 使用方式: 1. ...
- 转载:深入理解Scala的隐式转换系统
摘要: 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码. 使用方式: 1. ...
- 深入理解Scala的隐式转换
摘要: 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码. 使用方式: 1. ...
- scala的隐式转换
摘要: 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码. 使用方式: 1. ...
随机推荐
- TCP报文格式详解
TCP报文是TCP层传输的数据单元,也叫报文段. 1.端口号:用来标识同一台计算机的不同的应用进程. 1)源端口:源端口和IP地址的作用是标识报文的返回地址. 2)目的端口:端口指明接收方计算机上的应 ...
- linux和Mac上安装composer
使用命令行方式,可以直接使用下面的命令,顺序执行: php -r "copy ('https://getcomposer.org/installer','composer-setup.php ...
- 转载 loadrunner的一些问题解决
sckOutOfMemory 7 内存不足 sckInvalidPropertyValue 380 属性值不效 sckGetNotSupported 394 属性不可读 sckGetNotSup ...
- 自定义组件的 v-model
Vue.component('base-checkbox', { model: { prop: 'checked', event: 'change' }, props: { checked: Bool ...
- Windows 下面 winrar 压缩简单记录
1. 最高压缩比率 原始文件大小: 2.06g(3000余个文件) 压缩后文件大小:475m 压缩耗时: 210s 压缩率:22% 2. 较高压缩比率 压缩后文件大小:700 m 压缩率:32% 3 ...
- ARIMA模型识别、计算p、q值
#-*- coding: utf-8 -*- #确定最佳p.d.q值 import pandas as pd #参数初始化 discfile = '../data/discdata_processed ...
- python中常用的九种数据预处理方法分享
Spyder Ctrl + 4/5: 块注释/块反注释 本文总结的是我们大家在python中常见的数据预处理方法,以下通过sklearn的preprocessing模块来介绍; 1. 标准化(St ...
- BZOJ2135 刷题计划(贪心+二分)
相邻数作差后容易转化成将这些数最多再切m刀能获得的最小偏差值.大胆猜想化一波式子可以发现将一个数平均分是最优的.并且划分次数越多能获得的偏差值增量越小.那么就可以贪心了:将所有差扔进堆里,每次取出增量 ...
- UVa - 10339
It has been said that a watch that is stopped keeps better time than one that loses 1 second per day ...
- Application Server not specified
IDEA使用tomcat启动web项目,配置页面报错Application Server not specified: 那是因为没有配置tomcat,只要配置一下就好了: