三、Scala的常用数据类型
1、注意:在Scala中,任何数据都是对象。
举例:数字 1 ----> 是一个对象,就有方法
scala> 1.toString
res0: String = 1 ----> 定义了新的变量 res0,类型String
2、Scala定义变量的时候,可以不指定变量的类型,Scala会进行类型的自动推导
举例:下面的语句是一样的
var a:Int = 10
var b = 10
如何定义常量? val
val c = 10
3、数据的类型
(1)数值类型:复习
(*)Byte: 8位的有符号 -128~127
(*)Short:16位的有符号 -32768 ~ 32767
(*)Int: 32位的有符号
(*)Long: 64位的有符号
(*)Float:浮点数
(*)Double:双精度
(2)字符串:Char、String
对于字符串,在Scala中可以进行插值操作
val s1 = "hello world"
可以在另一个字符串中,引用s1的值
s"My name is Tom and ${s1}"
(3)Unit类型:相当于Java中的void 类型
()代表一个函数:没有参数,也没有返回值
scala> val f = ()
f: Unit = ()
val f = (a:Int)
(4)Nothing类型:一般来说,表示在函数(方法)执行过程中产生了Exception
举例: 定义函数 def
def myfunction = throw new Exception("some exception ....")
myfunction: Nothing
四、Scala的函数
1、内置函数:数***算
举例:求最大值
max(1,2)
包: import scala.math._
https://www.scala-lang.org/files/archive/api/2.11.8/#package
scala> max(1,2)
res4: Int = 2 ----> 定义了一个新的变量来保存运算的结果
var result:Int = max(1,2)
var result = max(1,2)
2、自定义函数:def
3、Scala的条件表达式 if.. else
//注意:scala中函数的最后一句话,就是函数分返回值
//不写reture
五、循环: for、while、do...while
六、Scala函数的参数:求值策略
1、call by value:对函数的实参求值,并且仅求一次
举例:def test1(x:Int,y:Int):Int = x+x 没有用到y
2、call by name:函数的实参每次在函数体内部被调用的时候,都会进行求值
举例:def test2(x: => Int,y: =>Int):Int = x+x 没有用到y
3、一个复杂点的例子
x是call by value
y是call by name
def test3(x:Int,y: =>Int):Int = 1
再定义一个死循环的函数
def loop():Int = loop
考虑下面的两个调用
test3(1,loop) ---> 正常
test3(loop,1) ---> 死循环
4、函数的参数:默认参数、代名参数、可变参数
七、lazy值:如果一个变量被lazy修饰了,他的初始化会被推迟到第一次使用的时候
举例1
scala> var x = 10
x: Int = 10
scala> lazy val y = x + 10
y: Int = <lazy>
scala> y
res0: Int = 20
举例2:读文件(存在)
读文件(不存在)
scala> val words = scala.io.Source.fromFile("d:\\temp\\a.txt").mkString
words: String = I love Beijing
scala> val words1 = scala.io.Source.fromFile("d:\\temp\\b.txt").mkString
java.io.FileNotFoundException: d:\temp\b.txt (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at scala.io.Source$.fromFile(Source.scala:91)
at scala.io.Source$.fromFile(Source.scala:76)
at scala.io.Source$.fromFile(Source.scala:54)
... 32 elided
scala> lazy val words1 = scala.io.Source.fromFile("d:\\temp\\b.txt").mkString
words1: String = <lazy>
scala> words1
java.io.FileNotFoundException: d:\temp\b.txt (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at scala.io.Source$.fromFile(Source.scala:91)
at scala.io.Source$.fromFile(Source.scala:76)
at scala.io.Source$.fromFile(Source.scala:54)
at .words1$lzycompute(<console>:11)
at .words1(<console>:11)
... 32 elided
scala>
八、异常:Exception
补充:复习:异常处理的机制 ----> 向上处理异常机制
九、数组、映射、元组
1、数组:定长数组 Array
变长数组 ArrayBuffer
2、映射Map、元组Tuple
第二章:Scala面向对象:类似Java
一、复习:面向对象的基本概念
(*)定义:把数据和操作数据的方法放到一起,作为一个整体(类 class)
(*)面向对象的特质:
(1)封装
(2)继承
(3)多态
二、定义类class
三、属性的get和set方法
四、内部类(嵌套类):在类的内部,又定义了一个类
举例:创建类,保存学生和学生考试成绩(科目 成绩)
五、类的构造器
1、主构造器:跟类名写在一起,只能有一个主构造器
2、辅助构造器:可以有个多个,关键字 this
六、Object对象(相当于Java中的static)
1、在Object对象中的所有内容都是静态的
2、举例(1):实现单例模式:一个类只有一个对象
举例(2):省略main方法,objec对象需要继承App父类
七、apply方法:作用:使得程序简单,省略new关键字
八、继承:Scala和Java一样,使用extends关键字扩展类。
例子:参考讲义
九、特质(trait):当成Java中的抽象类,支持多重继承(像Java的接口)
trait就是抽象类。trait跟抽象类最大的区别:trait支持多重继承
十、包和包对象: 参考讲义
第三章:Scala函数式编程(最有特色):核心概念---> 把一个函数作为另一个函数参数的值传递过去
一、回顾:Scala函数:def关键字
二、什么是匿名函数:没有名字的函数
三、带函数参数的函数:也叫:高阶函数
把一个函数作为另一个函数参数的值传递过去
一个函数的参数值是另一个函数
四、闭包、柯里化
五、示例:常用的高阶函数
1、map:对集合中的每个元素进行操作,返回一个结果
val numbers = List(1,2,3,4,5,6)
每个元素乘以2
numbers.map((x:Int)=>x*2)
简写方式
numbers.map(_*2)
2、foreach:对集合中的每个元素进行操作,不返回结果
numbers.foreach(_*2)
3、filter:过滤,选择满足条件的元素
选择能够被2整除的元素
numbers.filter((i:Int)=> i%2==0)
完整
numbers.filter((i:Int)=>{
if(i%2 == 0){
true
}else{
false
}
})
4、zip:把两个集合合并成一个
List(1,2,3).zip(List(4,5,6))
List(1,2,3).zip(List(4,5,6,7))
5、partition: 分区,根据分区条件,把满足条件的分成一个区,不满足条件的分成另一个区
val numbers = List(1,2,3,4,5,6)
能够被2整除的分成一个区,不能整除的分成另一个区
numbers.partition((i:Int)=> i%2==0)
完整
numbers.partition((i:Int)=>{
if(i%2 == 0){
true
}else{
false
}
})
6、find: 查找第一个满足条件的元素
能够被3整除的元素
numbers.find(_%3 == 0)
7、flatten:把一个嵌套的结果展开
List(List(1,2,3),List(4,5,6)).flatten
8、flatMap = flatten + map
举例
val myList = List(List(1,2,3),List(4,5,6))
myList.flatMap(x=>x.map(_*2))
第一步:将List(1,2,3)和List(4,5,6)展开 (1,2,3,4,5,6)
第二步:(1,2,3,4,5,6)每个元素乘以2
第四章:Scala常用集合
一、可变集合、不可变集合
二、列表
三、序列
四、Set:不重复元素的集合,默认是:HashSet
五、模式匹配:就相当于switch ... case 语句
六、样本类:case class,支持模式匹配,就相当于支持switch ... case 语句 相当于 instanceof
第五章:Scala的高级内容:泛型
一、泛型类:定义类的时候,接收一个泛型参数
二、泛型函数:定义函数的时候,接收一个泛型参数
举例:
(1)定义函数:创建一个Int类型的数组
def mkIntArray(elem:Int*) = Array[Int](elem:_*)
mkIntArray(1,2,3)
mkIntArray(1,2,3,4,5)
(2)定义函数:创建一个String类型的数组
def mkStringArray(elem:String*) = Array[String](elem:_*)
mkStringArray("Tom","Mary")
(3)在函数中使用泛型,取代上面的两个函数
import scala.reflect.ClassTag
def mkArray[T:ClassTag](elem:T*)=Array[T](elem:_*)
说明:ClassTag表示Scala在运行时候的状态信息,这里表示调用时候的数据类型
调用
mkArray(1,2,3,4,5)
mkArray("Tom","Mary")
三、泛型的上界和泛型的下界:规定泛型的取值范围
1、普通的数据类型为例
10 <= x:Int <=100 ----> 规定了x的范围(10,100)
2、规定:类型的取值范围 ---> 下界 上界
定义几个类(继承关系) Class A ---> Class B ---> Class C ---> Class D
定义泛型
D <: T 泛型类型 <: B ----> 泛型T的取值:B、C、D
3、概念
上界:定义 S <: T 表示S的类型必须是T的子类
下界:定义 U >: T 表示U的类型必须是T的父类
4、举例:上界为例
5、举例:拼加字符,接收类型必须是String或者String的子类
def addTwoString[T<:String](x:T,y:T) = {println(x+"*****"+y)}
调用
addTwoString("abc","xyz") ---> abc*****xyz
addTwoString(100,200) ---> 期望:100*****200
错误
<console>:13: error: inferred type arguments [Int] do not conform to method addTwoString's type parameter bounds [T <
addTwoString(100,200)
^
<console>:13: error: type mismatch;
found : Int(100)
required: T
addTwoString(100,200)
^
<console>:13: error: type mismatch;
found : Int(200)
required: T
addTwoString(100,200)
实际上:addTwoString(100,200)
1、首先 100和200 转换成字符串 "100" "200"
2、再拼加 100*****200
四、视图界定: 扩展了上界和下界的范围,表示方式:<%
1、可以接收:(1)上界和下界的类型
(2)允许接收通过隐式转换过去的类型
实际上:addTwoString(100,200)
1、首先 100和200 转换(隐式转换)成字符串 "100" "200"
2、再拼加 100*****200
2、改写上面的例子
(*)定义订转换规则:隐式转换函数
implicit def intToString(n:Int):String = {n.toString}
(*)使用视图界定改写 addTwoString
def addTwoString[T <% String](x:T,y:T) = {println(x+"*****"+y)}
表示:T可以是String和String的子类
也可以是能够转换成String的其他类型
(*)分析一下执行的过程
addTwoString(100,200)
(1)检查参数的类型:Int类型
接收的是String的类型
(2)在当前的会话中,查找有没有一个隐式转换函数:Int ---> String
(3)如果找到,先调用这个隐式转换函数
如果没有找到,出错
(4)再调用函数
五、协变和逆变
概念
1、协变:泛型变量的值可以是本身或者其子类的类型
2、逆变:泛型变量的值可以是本身或者其父类的类型
六、隐式转换函数:使用关键字implicit
1、什么是隐式转换函数? 使用关键字implicit,由Scala自动调用
implicit def intToString(n:Int):String = {n.toString}
2、举例:定义一个隐式转换函数,针对class
七、隐式参数:是在参数的前面加上implicit
用途:实现隐式转换
八、隐式类:是在类的前面加上implicit
用途:增强类的功能(类似:包装设计模式,动态代理对象)
(一两年前:Scala的Actor编程:已经废弃)