Scala study
书名:Scala 学习手册/(美)Swartz,J. 著;苏金国等译。–北京:中国电力出版社,2016.2
第1章 概述
- 输出:
println("hello world!")
,String
字符为双引号,Char
字符为单引号 - REPL:Read,Evaluate,Print,Loop.可以跨会话存储
- up 箭头:上一行命令
- 每一行的输出
result
REPL 会用一个常量变量保存:res0,res1,...
- 运行
scala
文件hello.scala
- 交互环境中输入
scala> :load hello.scala
- 命令行:
scala hello.scala
- 交互环境中输入
- 退出:
:q
第2章 数据类型(数值类型:Int,Double
,非数值类型:String,Char
)
- 字面量值(不可重新赋值):
scala> val x:Int=10
,不可变有类型的存储文件,用关键字val
(value),类型可省略scala> val x = 10
- 变量:
scala> var a:Double=2.73
,关键字var
(variable),类型可省略scala> var a=2.73
- 字符串
val approx = 355/113f println("Pi,using 355/113,is about "+approx+".") println(s"Pi,using 355/113,is about $approx.") //内插法
- 字符串内插(替代格式
printf
,难读,输出可格式化)val item = "apple" println(s"How do you like them ${item}s?") println(s"Fish n chips n ,${"pepper "*3}salt") // 字符串乘法println(f"I wrote a new $item%.3s today") println(f"Pi,using 355/113,is about ${355/113.0}%.5f.") //内插法
- 正则表达式
"Froggy went a' courting" matches ".* courting" //Ture or False"milk,tea,muck" replaceAll ("m[^ ]+k","coffee") "milk,tea,muck" replaceAll ("m[^ ].k","coffee")"milk,tea,muck" replaceFirst ("m[^ ]+k","coffee") "milk,tea,muck" replaceFirst ("m[^ ].k","coffee")// 捕获组:小括号定义,输入至少包括一个匹配值 val input = "Enjoy this apple 3.14159 times today" val pattern = """.* apple ([\d.]+) times .*""".r // r 为字符串操作符 val pattern(amountText) = input val amount = amountText.toDouble
- 类型操作(每个类型都属于一个对象)
scala> 5.asInstanceOf[Double]
:val/var 类型转换(尽量用第五条)scala> nada.getClass
:val/var 查看类型- val/var 类型确认:
scala> nada.isInstanceOf[Unit]
- val/var 散列码:
scala> "A".hashCode
- val/var 转换函数:
toString/toByte/toFloat/...
- 元组:包含两个以上值得有序容器,值类型可不同,不可迭代但可通过下标访问。类似关系型数据库中得一行
// 元组,下标从1开始 val info = (5,"Korben",true) val name = info._2val red = "red"->"0xff0000" // 利用关系操作符创建2元组 val reversed = red._2 -> red._1
注:
1. 值优先于变量,因为值可以为代码带来稳定性和可预测性。
2. 类型为Double 的变量可以赋 Int 值,因为Int数可以自动转换为Double 数。
3. 变量命名建议:`camel case`驼峰命名
4. 字符串支持三重双引号
5. Scala 不支持其他类型到Boolean 的自动转换,非Null 字符不会计算为True,0也不等于False
6. &&与||很懒,第一个参数可以出结论,不在计算第二个参数。&与| 会对两个参数都做检查
7. Unit 字面量:`scala> val nada=()`,通常用来定义函数和表达式
第3章 表达式 和 条件式
表达式
表达式:
scala> val x=5*20;val amount = x+10
,字面量val/var 也是一种表达式表达式块:
scala> val amount = {val x=5*20;x+10}
块中最后一个表达式最为块得返回值。- 表达式块分号,可用换行替代
- 表达式块可以嵌套
scala> {val a=1;{val b=a*2;{val c=b+4;c}}}
// 结果可以赋值给变量 val x = -3 if (x>0) {println("This is a positive number!") } else if (x==0){println("This is zero") } else {println("This is a negative number !") }
if…else 表达式块:
scala> val max = if(5>3) {val x=4*2;x+2} else 2
匹配表达式(
match expressions
):类似 switch// 匹配表达式 val status=500 val message = status match {case 200 => "ok"case 400 => println("ERROR - we called the service incorrectly");"error"case 500 => {println("ERROR - the service encountered an error");"error"} } // 模式替换式 pattern alternative val day = "MON" val kind = day match {case "MON"|"tue"|"wed"|"thu"|"fri" => "weekday"case "sat"|"sun" => "weekend" case unexpected => unexpected + " is not expected!" // 除了通配符,匹配值还可以获取 }
通配模式匹配
//值绑定 val message="ok" val status = message match {case "ok" => 200case other => println(s"could not parse $other");-1 }//other 为case 块定义,并赋值为 message //通配符 val message="Tom" val status = message match {case "ok" => 200case _ => println(s"could not parse $message");-1 }//_ 通配符,可以匹配任意值,右侧不可访问.若需要访问,可直接访问输入// 类型模式 for (elem <- List(9,12.3,"spark","hadoop",'hello)){println("current value is:",elem)val result = elem match {case i:Int => i + " is an int value"case d:Double => d + " is an double value"case "spark" => "spark is find"case s:String => s + " is a string value"case _ => "this is an unexpected value"}println(result) }
模式哨卫匹配(case 后面 + if 表达式,可不加括号)
val response:String ="ok1" response match {case s if s!= null => println(s"Received '$s'")case s => println("ERROR! Received a null response") }
模式变量匹配类型(应该不常用)
循环(表达式的控制结构)
- for 循环
<-
类似python 中的in
。(x <- 1 to 7 by 1)
为生成器for (x <- 1 to 7 by 1) {println(s"Day $x")} println(s"${"*"*3}等价于${"*"*3}") val week = for (x <- 1 until 8 by 1) yield {s"Day $x:"} //返回值将作为一个集合返回,可迭代,for 推导式 for (day <- week) print(day+",") // print 不换行
- 迭代器哨卫(
iterator guard/filter
,增加一个 if表达式)val threes = for(i<-1 to 20 if i%3==0) yield i val quote = "Faith,Hope,,Charity,null" for {t<-quote.split(",");if t!=null;if t.size>0}{println(t)} //迭代器与迭代器哨卫 分开
- 嵌套迭代器(多层循环):
scala> for {x<-1 to 2;y<-3 to 5}{print(s"($x,$y)")}
- 值绑定 for 循环:
val powersOf2 = for (i<-0 to 8;pow=1<<i) yield pow // 1 左移 i 位
- while/do…while… 循环
- while:
scala> var x=10;while (x>=0) x -= 1
- do…while:
val x=0;do println(s"Here I am,x=$x") while (x>0)
- while:
第4章 函数
定义:def multiplier(x:Int,y:Int): Int = {x*y}
函数返回值:一般为表达式块最后一行,也可以使用 return 关键字返回并退出
- 过程 procedure:没有返回值的函数
- 隐式返回类型:
def log(d:Double) = println(f"Got value $d%.2f")
- 显示返回类型:
def log(d:Double):Unit = println(f"Got value $d%.2f")
- 隐式返回类型:
- 无参函数:
def hi():String ="hi"
- 块表达式函数:参数为块表达式,可赋 默认值
def formatEuro(amt:Double = 10) = f" $amt%.2f" formatEuro{val rate = 0.011;1500*rate}
- 递归函数
- 递归缺点:栈溢出,调用递归函数太多,耗尽分配的内存
- 尾递归特点:不使用额外的栈空间
// 计算 x^n 幂 def powerN(x:Int,n:Int):Double = {n match {case n if n<0 => 1.0/x * powerN(x,n+1);case n if n>=1 => x * powerN(x,n-1);case n => 1} }// tail-recursion 递归调用函数本身作为返回值,才能由Scala 编译器完成尾递归优化 @annotation.tailrec def power(x:Int,n:Int,t:Int=1):Int = {if (n<1) 1else power(x,n,x*t) }
- 嵌套函数
def max(a:Int,b:Int,c:Int):Int = {def max(x:Int,y:Int) = if(x>y) x else ymax(a,max(b,c)) // 局部函数优先于外部函数 }
- Vararg 参数
def mysum(item:Int*):Int = {var total = 0for (i<- item) total += itotal }mysum();mysum(20,30)
- 参数组:
def max(x:Int,y:Int) = if(x>y) x else y
- 方法和操作符
- 函数常存在于对象中,函数更适合的说法通常是方法。
- Scala 没有任何四则运算符,Scala 使用的算术运算符其实都是实例的方法。这里不使用传统点记法,而是使用空格来分割对象(2)、操作符方法(+)、和方法的参数(3)。例如:
2 + 3
scala 的操作符记法为2.+(3)
val d= 65.642 d.compare(18.0) d compare 18.0 1 + 2 + 3 (1.+(2)).+(3)
第六章 常用数据类型
List:可迭代
- filter:
List(23,8) filter (_ > 18)
- 合并:
List(List(1,2),List(3,4)).flatten
- 拆分:
List(1,2,3,4,5) partition (_<3)
- 切片:
List(1,2,3,4,5) slice (1,3)
- top n:
List(1,2,3,4,5) take 3
- zip:
List(1,2) zip List("a","b")
val colors = List("red","green","blue") println(s"The colors value's size head remain is ${colors.size},${colors.head},${colors.tail}") colors(1) // List 下标从 0 开始// 高阶函数 colors.foreach((c:String)=>println(c)) val numbers = colors.map((c:String)=> c.size)\ val total_str = colors.reduce((a:String,b:String)=> a+" "+b)
- filter:
Set
var myset = Set("hadoop","spark") // myset 可以指向不同的地址。Set 默认不可变 myset += "scala" // myset 指向另一个不可变 地址import Scala.collection.mutable.Set // 可变集合 val myset1 = Set("hadoop","spark") myset1 += "cloud computing" // myset1 指向地址不变,Set 内容增加
Cons 操作符
映射(Map)
val uni = Map("xmu"->"xiamen uin","thu"->"Tsinghua uin") // 默认不可变 val xmu = if(uni.contains("xmu")) uni("xmu") else 0 println(xmu)import scala.collection.mutable.Map val uni = Map("xmu"->"xiamen uin","thu"->"Tsinghua uin") // 可变 uni("xmu") = "xiamen university" // update uni("fzu") = "fuzhou uni" uni += ("tju"->"tianjin uni") uni += ("tju"->"tianjin uni","whu"->"wuhan uni")for ((k,v) <- uni) printf("code is: %s and name is: %s\n",k,v) // 遍历 for (k <- uni.keys) println(k) for (k <- uni.values) println(v)
迭代器(Iterator):基本操作:
next(),hasNext
val iter = Iterator("hadoop","spark") while (iter.hasNext){println(iter.next())} for (ele <- iter) println(ele)
类
else
基本语法
写入文件:Scala 需要java.io.PrintWriter 实现把数据写入文件
import java.io.PrintWriter
val out = new PrintWriter("/usr/local/output.txt")
for (i <- 0.8f to 1.6f by 0.2f) out.println(i)
out.close()
读取文件:可以使用 Scala.io.Source 的 getLines 方法 实现对文件中所有行读取
import scala.io.Source
val inputFile = Source.fromFile("output.txt")
val lines = inputFile.getLines
for (line <- lines) println(line)
异常处理:Scala 将所有异常都当作 不受检异常,使用 try-catch 结构捕获异常
// 暂不能运行
import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOExceptiontry {val f = new FileReader("input.txt")
} catch {case ex:FileNotFoundException => println("file not found")case ex:IOException => println("IO error")case _ => println("else error")
}
finally{file.close()
}
类
class Counter{private var value = 0 // 外部不可访问def increment():Unit = {value += 1}def current():Int = value
}val mycounter = new Counter // 无参数可不加括号,下同
println(mycounter.current)
mycounter.increment
println(mycounter.current)
class Counter{var value = 0 // 外部可访问def increment(step:Int):Unit = {value += step} // 含参函数def current():Int = value
}
object Mycounter{def main(args:Array[String]){val mycounter = new Counter // 无参数可不加括号,下同println(mycounter.current)mycounter.increment(5)println(mycounter.current)}
}
getter 与 setter 方法
class Counter{private var privateValue = 0 // 外部可访问def value = privateValue // 类似 Java 的 getter 方法def value_= (newValue:Int){// 类似 Java 的 setter 方法if (newValue > 0) privateValue = newValue}def increment(step:Int):Unit = {value += step} // 含参函数def current():Int = value
}
object Mycounter{def main(args:Array[String]){val mycounter = new Counterprintln(mycounter.value)mycounter.value = 3println(mycounter.value)mycounter.increment(5)println(mycounter.current)}
}
辅助构造器
- scala 构造器包含一个主构造器和若干个(>=0)辅助构造器
- 辅助构造器名称为 this,每个辅助构造器都必须调用已经定义辅助构造器或主构造器
class Counter{ // 类 主构造器private var value = 0 // 计数器起始值private var name = "" // 计数器名称private var mode = 1 // 计数器类型def this(name:String){ // 第一个 辅助构造器,只能调用 主构造器this() // 调用主构造器this.name = name}def this(name:String,mode:Int){this(name)this.mode = mode}def increment(step:Int):Unit = {value += step} // 含参函数def current():Int = valuedef info():Unit = {printf("Name:%s and mode is %d\n",name,mode)}
}
object Mycounter{def main(args:Array[String]){val mycounter1 = new Counter // 主构造器val mycounter2 = new Counter("Runner")val mycounter3 = new Counter("Timer",2)mycounter1.infomycounter1.increment(1)printf("current value is:%d\n",mycounter1.current)mycounter2.infomycounter2.increment(2)printf("current value is:%d\n",mycounter2.current)mycounter3.infomycounter3.increment(3)printf("current value is:%d\n",mycounter3.current)}
}class Counter(val name:String,val mode:Int){ // 类:主构造器private var value = 0 // 计数器起始值def increment(step:Int):Unit = {value += step} // 含参函数def current():Int = valuedef info():Unit = {printf("Name:%s and mode is %d\n",name,mode)}
}
单例对象 和 伴生对象
- 单例对象:对象定义不需要出现class,而是用 object。静态变量,每次调用都累加
- 伴生对象
- 同时包含实例方法 和 静态方法的类
- 当单例对象 与某类具有相同名称时,它被称为这个类的伴生对象
- 类及其伴生对象 必须存在于同一文件,可以相互访问
- 定义在伴生对象的方法都属于静态方法(static method)
class Person {private val id = Person.newPersonId() // 调用伴生对象(静态 static方法)private var name = ""def this(name:String){this()this.name = name}def info(){printf("The id of %s is %d.\n",name,id)}
}object Person { // 单例对象:类Person 的伴生对象private var lastId = 0private def newPersonId() = {lastId += 1lastId}def main(args:Array[String]){ // main 函数入口val person1 = new Person("ziyu")val person2 = new Person("minxing")person1.infoperson2.info}
}scalac hello.scala
scala -classpath . Person
javap Person // Java 反编译
继承
- 子类重写超类的抽象方法不需要使用 override 关键字
- 只有 主构造器 可以调用 超类中的 主构造器
- 可以重写超类中的字段
- 重写一个非抽象方法必须使用 override 修饰符
- Scala 和 Java 一样,不允许从多个超类中继承
- abstract 抽象类关键字,extends 继承关键字
abstract class Car{ // 抽象类:不能被直接实例化val carBrand :String // 抽象字段:没初始化,必须声明类型def info() // 抽象方法:没有定义任何方法的方法(空着)def greeting() {println("welcome to my car!")} // 具体方法
}class BMWCar extends Car{override val carBrand = "BMW" // 重写超类字段,必须用 overridedef info(){printf("This is a %s car.It is on sale.\n",carBrand)} // 重写超类抽象方法, override 可忽略override def greeting(){println("welcome to my BMWCar car!")} // 重写超类具体方法, override 不可忽略
}object Mycar{def main(args:Array[String]){val mycar = new BMWCarmycar.greetingmycar.info}
}
特质(trait):继承多个父类
trait CarId{var id:Intdef currentId():Int
}
trait CarGreeting{def greeting(msg:String) {println(msg)}
}class BMWCarId extends CarId with CarGreeting{ // 可以使用多个 with 混入多个特质override var id:Int = 20000def currentId():Int = {id += 1;id} // 重写超类抽象方法, override 可忽略
}object Mycar{def main(args:Array[String]){val mycarid = new BMWCarIdmycarid.greeting("welcome my first car!")printf("my first carid is %d\n",mycarid.currentId)}
}
函数式编程
// 函数式编程实例 WordCount:对当前目录下文本文件进行词频统计
import java.io.File
import scala.io.Sourceobject WordCount{def main(args:Array[String]){val dirfile = new File("D:/documents/3_linzi_work/com_tools/bailing")val files = dirfile.listFilesfor (file <- files) println(file)val listFiles = files.toListval wordsMap = scala.collection.mutable.Map[String,Int]() // 声明可变映射listFiles.foreach(file=>Source.fromFile(file).getLines().foreach(line=>line.split(" ").foreach(word=> {if (wordsMap.contains(word)){wordsMap(word) += 1}else{wordsMap += (word->1)}})))println(wordsMap)for ((k,v)<- wordsMap) println(k+":"+v)}
}
Scala study相关推荐
- Scala的特质(Trait)介绍
Scala的特质(Trait) 基本概念 特质声明 基本语法 特质的使用 基本语法 说明 案例实操 特质叠加 基本概念 案例实操 特质叠加执行顺序 案例说明 特质自身类型 说明 案例实操 特质和抽象类 ...
- 如何通过建造餐厅来了解Scala差异
I understand that type variance is not fundamental to writing Scala code. It's been more or less a y ...
- Martin Odersky Scala编程公开课 第三周作业
Functional Programming Principles in Scala by Martin Odersky 这次的作业叫做Object-Oriented Sets.要完成一个完整的类, ...
- array函数参数 scala_3小时Scala入门
〇,编程环境 1,安装Java 2,配置Java环境变量 3,安装Scala 4,配置Scala环境变量 参考文末阅读原文链接. 一,算术运算 二,输入输出 输出:println,print,prin ...
- Machine Learning Algorithms Study Notes--Supervised Learning
转载自:http://www.tuicool.com/articles/VvuIvqU Machine Learning Algorithms Study Notes 高雪松 @雪松Cedro Mic ...
- Machine Learning Algorithms Study Notes
2 Supervised Learning 3 2.1 Perceptron Learning Algorithm (PLA) 3 2.1.1 PLA -- " ...
- 第四课 尚硅谷Scala语言学习-面向对象
第四课 尚硅谷Scala语言学习-面向对象 文章目录 第四课 尚硅谷Scala语言学习-面向对象 第一节 Scala 包 1.1 包基本语法 1.2 包说明 1.3 包对象 1.4 导包说明 第二节 ...
- spark学习02天-scala读取文件,词频统计
1.在本地安装jdk环境和scala环境 2.读取本地文件: scala> import scala.io.Source import scala.io.Sourcescala> val ...
- Scala数组函数二(dropRight~intersect)
dropRight 功能同drop,去掉尾部的n个元素 val a=Array(1,2,3,4,5) a.dropRight(2) Array[Int] = Array(1, 2, 3) dropWh ...
最新文章
- 10.15 iptables filter表案例
- 递归下降分析法(编译原理)
- python制作界面怎么触发事件_python模拟事件触发机制详解
- springboot 项目 测试环境在独立的tomcat部署
- C# 之 Win32 Api使用
- 好用的服务器终端,推荐7款超级好用的终端工具 —— SSH+FTP
- Java常量池详解:字符串常量池、Class常量池、运行时常量池 三者关系
- 总在说思科华为认证 可你真的清楚它们的区别吗?
- DefCamp CTF 2122 Rsa-factory 复现笔记
- 关于禁用Cookie的问题以及解决办法
- 关于QQ热键在不知道的情况下找出热键组合的办法
- 51系列、arduino、stm32系列驱动DAC模块TLC5615输出指定电压(可修改为波形输出)
- golang中os/signal包的使用
- [系统安全] 三十五.Procmon工具基本用法及文件进程、注册表查看
- 【华人学者风采】钱煦 加州大学圣地亚哥分校
- 新手小心:c语言的强符号和弱符号
- CentOS7 搭建Janus服务
- 调用命令强制关闭windows进程
- Linux篇19多线程第三部分
- IM开发——群组创建业务设计