我是靠谱客的博主 完美钥匙,这篇文章主要介绍Scala编程语言入门学习笔记,现在分享给大家,希望可以做个参考。

数据类型和操作符

数据类型

(1)值类型和引用类型
(2)值类型是类类型,相当于java中的包装类,没有基本数据类型和包装类之分

复制代码
1
2
3
4
5
scala> 1 to 10 res4: scala.collection.immutable.Range.Inclusive = Range 1 to 10 scala> 1.to(10) res5: scala.collection.immutable.Range.Inclusive = Range 1 to 10

操作符

数学运算符:±*/%
关系运算符:>>=<=!
逻辑运算符:&&||
位运算符:& | ^
比较对象:== !=
(1)scala运算符都是方法的重载,是方法的调用
(2)scala没有++,- -运算符,可以用+=,-=代替

表达式

就是一个语句块,包含一条或多条语句
特点:
(1)表达式是有返回值的
(2)返回值是表达式中的最后一条语句的执行结果

条件表达式

含有if/else的语句块

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
scala> val age = 30 age: Int = 30 scala> if(age > 18) 1 else 0 res0: Int = 1 scala> val isAdult = if(age > 18) 1 else 0 isAdult: Int = 1 scala> var isAdult = -1 isAdult: Int = -1 scala> if(age > 18) isAdult = 1 else isAdult = 0 scala> :paste // Entering paste mode (ctrl-D to finish) if(age < 18) "children" else "adult" // Exiting paste mode, now interpreting. res4: String = adult

块表达式

{一条或多条语句}

循环

for:
for (i <- 表达式、数组、集合)
for推导式,构建集合

复制代码
1
2
3
scala> for(i <- 1 to 10) yield i res6: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

while:
while(条件语句) {表达式}

do while:
do{表达式} while(条件语句)

跳出循环,scala没有break,可以使用boolean类型变量、return或者Breaks的break函数来替代使用。

方法

定义语法:
def 方法名(参数列表):返回类型(递归类型不可省略) = 方法体(表达式)

//返回类型在方法是递归方法的时候,一定要指明返回类型,其他情况,可以省略返回类型

定义方法时,如果方法体直接包裹在了花括号里边,而没有使用=连接,则方法的返回值类型就是Unit。这样的方法就被称之为过程。过程通常用于不需要返回值的方法。过程还有一种写法,就是将方法的返回值定义为Unit。

带有参数列表的方法

复制代码
1
2
3
4
5
scala> def addAndMultiply(x:Int)(y:Int)=x+y addAndMultiply: (x: Int)(y: Int)Int scala> addAndMultiply(2)(3) res0: Int = 5

无参方法

复制代码
1
2
3
4
5
6
7
8
9
10
11
scala> def printInfo = println("scala") printInfo: Unit scala> printInfo scala scala> def printInfo1() = println("scala") printInfo1: ()Unit scala> printInfo1() scala scala> printInfo1 scala

带有默认参数的方法

可变长参数方法

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
scala> def add(a:Int*)={} add: (a: Int*)Unit scala> def add(a:Int*)={ | for (i <- a) | println(a) | } add: (a: Int*)Unit scala> add(1) WrappedArray(1) scala> add(1,2,3,4) WrappedArray(1, 2, 3, 4) WrappedArray(1, 2, 3, 4) WrappedArray(1, 2, 3, 4) WrappedArray(1, 2, 3, 4)

使用序列调用变长参数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
val s = sum(1 to 5: _*) //冒号后面定义的是类型 scala> def sum(nums: Int*) = { | var result = 0 | for(num <- nums) { | result += num | } | result | } sum: (nums: Int*)Int scala> sum(1,2,3,4,5) res16: Int = 15 scala> sum(1 to 5: _*) res17: Int = 15

函数

无参函数

复制代码
1
2
3
4
5
6
7
8
scala> val fun=() => println("hello") fun: () => Unit = $$Lambda$1209/1515342361@60e9bda0 scala> fun res12: () => Unit = $$Lambda$1209/1515342361@60e9bda0 scala> fun() //加上()才是无参函数的调用 hello

多参函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
val fun=(x:Int,y:Int)=>x*y fun: (Int, Int) => Int = $$Lambda$1210/939626967@537839b0 scala> fun() <console>:13: error: not enough arguments for method apply: (v1: Int, v2: Int)Int in trait Function2. Unspecified value parameters v1, v2. fun() ^ scala> fun res15: (Int, Int) => Int = $$Lambda$1210/939626967@537839b0 scala> fun(2,3) res16: Int = 6

方法和函数的区别

区别:

(1)方法和函数定义的语法不同

(2)方法一般定义在类,特质,或者object中

(3)方法可以共享所在类,特质,或者object中的属性

(4)方法可以调用函数,也可以存放到一个变量中,作为参数传递给其他的方法或函数,也可以作为返回值返回

联系:

(1)可以把函数作为参数传递给一个方法

复制代码
1
2
3
4
5
6
7
scala> def m(f:(Int,Int)=>Int) = f(5,1) m: (f: (Int, Int) => Int)Int scala> val f=(x:Int,y:Int)=>x-y f: (Int, Int) => Int = $$Lambda$1235/157170579@65c7d705 scala> m(f) res18: Int = 4

(2)方法可以转换成函数

a.把一个方法作为参数传递给其他的方法或者函数

复制代码
1
2
3
4
5
6
7
scala> def m(f:(Int,Int)=>Int) = f(5,1) m: (f: (Int, Int) => Int)Int scala> def m2(x:Int,y:Int) = x-y m2: (x: Int, y: Int)Int scala> m(m2) res19: Int = 4

b.使用 方法名 _ 把一个方法显示的转换为一个函数

复制代码
1
2
3
scala> m2 _ res20: (Int, Int) => Int = $$Lambda$1240/1778157082@3646f314

集合

什么是集合?

集合是存储各种数据类型对象的一个容器

(1)是一个容器

(2)一般放同种数据类型

(3)一般存放多个对象

集合

不可变集合:不可修改,但是可以模拟修改或删除等

可变集合:可修改,可以更新或者扩充

集合下面三大类:
set、序列、map

定长数组

数组的定义

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
scala> val arr=Array(1,2,3) arr: Array[Int] = Array(1, 2, 3) scala> val arr1=Array[Int](1,2,3) arr1: Array[Int] = Array(1, 2, 3) scala> val arr2 = new Array[Int](10) arr2: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) scala> val arr2 = new Array[Int](10,2,3) //使用new方式定义,无法同时初始化 <console>:11: error: too many arguments (3) for constructor Array: (_length: Int)Array[Int] val arr2 = new Array[Int](10,2,3) ^ scala> val arr3 = new Array(10) //使用new方式定义,必须写数据类型 arr3: Array[Nothing] = Array(null, null, null, null, null, null, null, null, null, null) scala> arr3(0) java.lang.NullPointerException

数组的访问

复制代码
1
2
3
scala> arr(0) res25: Int = 1

数组的常用方法

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
scala> arr1.length res24: Int = 3 scala> arr(0)=7 scala> arr res27: Array[Int] = Array(7, 2, 3) scala> var sum=0 sum: Int = 0 scala> for (elem <- arr) sum += elem scala> sum res29: Int = 12 scala> arr.sum res30: Int = 12 scala> arr.max res31: Int = 7 scala> arr.min res32: Int = 2 scala> arr.sorted res33: Array[Int] = Array(2, 3, 7) scala> arr.sorted.reverse res34: Array[Int] = Array(7, 3, 2) scala> arr.mkString(",") // 获取数组中的所有元素 res35: String = 7,3,2 scala> arr.mkString("(",",",")") res35: String = (7,3,2)

使用yield和函数式编程转换数组

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 对Array进行转换,获取的还是Array scala> val a = Array(1,2,3,4,5) a: Array[Int] = Array(1, 2, 3, 4, 5) scala> val a2 = for(ele <- a) yield ele * ele a2: Array[Int] = Array(1, 4, 9, 16, 25) // 对ArrayBuffer进行转换,获取的还是ArrayBuffer scala> import scala.collection.mutable.ArrayBuffer ArrayBuffer ArrayBuilder ArrayLike ArrayOps ArraySeq ArrayStack scala> val b = ArrayBuffer[Int]() b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() scala> b += (1,2,3,4,5) res24: b.type = ArrayBuffer(1, 2, 3, 4, 5) scala> val b2 = for(ele <- b) yield ele * ele b2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 4, 9, 16, 25) // 结合if守卫,仅转换需要的元素 scala> val a3 = for(ele <- a if ele % 2 ==0) yield ele * ele a3: Array[Int] = Array(4, 16) // 使用函数式编程转换数组(通常使用第一种方式) scala> a.filter(_ % 2 == 0).map(2 * _) res27: Array[Int] = Array(4, 8) scala> a.filter{_ % 2 == 0} map{2 * _} res28: Array[Int] = Array(4, 8)

变长数组

变长数组的创建

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
scala> import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer scala> var arr1=ArrayBuffer("a","b") arr1: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(a, b) scala> var arr1=ArrayBuffer[String]("a","b") arr1: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(a, b) scala> var arr2=new ArrayBuffer[Int](10) //因为是变长数组,所以这里的10没有意义 arr2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() scala> arr2.length res35: Int = 0 scala> var arr2=new ArrayBuffer[Int]() arr2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()

数组的操作

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
scala> arr2 += 1 //+=操作符,给变长数组添加元素,spark源码中大量使用 res36: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1) scala> arr2 += (2,3) res37: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3) scala> var arr3 = Array(4,5,6) arr3: Array[Int] = Array(4, 5, 6) scala> arr2 ++= arr3 // 使用++=操作符,添加其他集合中的所有元素 res38: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6) scala> arr2.append(8) scala> arr2.insert(2,88,99) scala> arr2 res41: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 88, 99, 3, 4, 5, 6, 8) scala> arr2 -= 1 res42: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 88, 99, 3, 4, 5, 6, 8) scala> arr2.insert(7,999) scala> arr2.insert(9,999) // insert() 指定位置,插入元素,可以是多个,这种方法效率极低 scala> arr2 res45: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 88, 99, 3, 4, 5, 6, 999, 8, 999) scala> arr2 -= 999 res46: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 88, 99, 3, 4, 5, 6, 8, 999) scala> arr2.trimEnd(1) // trimEnd(),可以从尾部截断指定个数的元素 scala> arr2 res48: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 88, 99, 3, 4, 5, 6, 8) scala> arr2.trimEnd(2) scala> arr2 res50: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 88, 99, 3, 4, 5) scala> arr2.remove(2,1) // remove() 指定位置移除指定个数 scala> arr2 res52: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 88, 3, 4, 5)

遍历数组

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
scala> for(i <- 0 until 10) print(i+" ") 0 1 2 3 4 5 6 7 8 9 scala> for(i <- 0 until (10,2)) print(i+" ") 0 2 4 6 8 scala> for(i <- (0 until (10,2)).reverse) print(i+" ") 8 6 4 2 0 scala> for(e <- b) print(e+" ")

练习:给你一个整数数组,产生一个新的数组,原有数组中的正数在新产生数组的前面,以原有数组的负数在新产生数组的后面,元素顺序保持不变。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
scala> var a1=Array(1,2,-6,-8,4,5,-2,33) a1: Array[Int] = Array(1, 2, -6, -8, 4, 5, -2, 33) scala> var a2=new ArrayBuffer[Int]() a2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() scala> var a3 = new ArrayBuffer[Int]() a3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() scala> for (e <- a1) { | if(e>0) a2.append(e) | else a3.append(e) | } scala> a2 ++=a3 res54: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 4, 5, 33, -6, -8, -2)

数组变换

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
scala> val a = Array(1,2,3,4,5) a: Array[Int] = Array(1, 2, 3, 4, 5) scala> for(e <- a) yield e*10 res55: Array[Int] = Array(10, 20, 30, 40, 50) scala> a.map(_*10) res56: Array[Int] = Array(10, 20, 30, 40, 50) scala> a.filter(_%2 == 0) res57: Array[Int] = Array(2, 4) scala> a.filter(x => x%2 == 0) res59: Array[Int] = Array(2, 4) scala> a.map(x => x*10) res58: Array[Int] = Array(10, 20, 30, 40, 50)

练习:移除第一个负数之后的所有负数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 构建数组 scala> val a = ArrayBuffer[Int]() a: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() scala> a += (1,2,3,4,5,-1,-3,-5,-9) res29: a.type = ArrayBuffer(1, 2, 3, 4, 5, -1, -3, -5, -9) // 每发现一个第一个负数之后的负数,就进行移除,性能较差,多次移动数组 scala> :paste // Entering paste mode (ctrl-D to finish) var foundFirstNegative = false var arrayLength = a.length var index = 0 while(index < arrayLength){ if(a(index) >= 0) { index += 1 } else { if(!foundFirstNegative) { foundFirstNegative = true index += 1 } else { a.remove(index) arrayLength -= 1 } } } // Exiting paste mode, now interpreting. foundFirstNegative: Boolean = true arrayLength: Int = 6 index: Int = 6 scala> a res32: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, -1) // 性能较高,数组内的元素迁移只要执行一次即可 scala> var foundFirstNegative = false foundFirstNegative: Boolean = false scala> val keepIndexes = for(i <- 0 until a.length if !foundFirstNegative || a(i) >= 0) yield { | if(a(i) < 0) foundFirstNegative = true | i | } keepIndexes: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3, 4, 5) scala> for(i <- 0 until keepIndexes.length) {a(i) = a(keepIndexes(i))} scala> a.trimEnd(a.length - keepIndexes.length) scala> a res36: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, -1)

List

创建list
不可变list:但是可以模拟修改或删除等

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
scala> var list1 = List(1,2,3) list1: List[Int] = List(1, 2, 3) scala> println(list1.getClass.getName) scala.collection.immutable.$colon$colon scala> 0 :: list1 // :: 可以用于将head和tail合并成一个List,0::list res62: List[Int] = List(0, 1, 2, 3) scala> list1 res63: List[Int] = List(1, 2, 3) scala> list1.::(0) res64: List[Int] = List(0, 1, 2, 3) scala> 0 +: list1 res65: List[Int] = List(0, 1, 2, 3) scala> list1.+:(0) //元素加在前面 res67: List[Int] = List(0, 1, 2, 3) scala> list1 :+ 4 //元素加在后面 res68: List[Int] = List(1, 2, 3, 4) scala> var list2=List(4,5,6) list2: List[Int] = List(4, 5, 6) scala> list1 ++: list2 res69: List[Int] = List(1, 2, 3, 4, 5, 6)

练习:用递归函数来给List中每个元素都加上指定前缀,并打印

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
scala> def decorator(list: List[Int],prefix: String) { | if(list != Nil){ | println(prefix+list.head) | decorator(list.tail,prefix) | } | } decorator: (list: List[Int], prefix: String)Unit scala> decorator(List(1,2,3,4),"+") +1 +2 +3 +4

可变list

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
scala> import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer scala> var list3 = ListBuffer(1,2,3) list3: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3) scala> list3 += 4 res72: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4) scala> list3 res73: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4) scala> list3.append(5) scala> var list4 = new ListBuffer[Int]() list4: scala.collection.mutable.ListBuffer[Int] = ListBuffer() scala> list4.append(9)

使用list

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
scala> list3 ++ list4 res76: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4, 5, 9) scala> list3 res77: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4, 5) scala> list4 res78: scala.collection.mutable.ListBuffer[Int] = ListBuffer(9) scala> list3 :+ 8 res79: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4, 5, 8) scala> list3 res80: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4, 5) scala> list3.map(_*10) res81: scala.collection.mutable.ListBuffer[Int] = ListBuffer(10, 20, 30, 40, 50) scala> list3.map(e=>e*10) res82: scala.collection.mutable.ListBuffer[Int] = ListBuffer(10, 20, 30, 40, 50) scala> list3.map{println("hello");_*10} hello res83: scala.collection.mutable.ListBuffer[Int] = ListBuffer(10, 20, 30, 40, 50) scala> list3.map{e=>println("hello");e*10} hello hello hello hello hello res85: scala.collection.mutable.ListBuffer[Int] = ListBuffer(10, 20, 30, 40, 50) scala> list3 res87: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4, 5)

map

创建map

不可变map:

复制代码
1
2
3
4
5
scala> val score = Map("zhansan"->90,"lisi"->80) score: scala.collection.immutable.Map[String,Int] = Map(zhansan -> 90, lisi -> 80) scala> val score = Map(("zhansan",90),("lisi",80)) score: scala.collection.immutable.Map[String,Int] = Map(zhansan -> 90, lisi -> 80)

可变map:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
scala> import scala.collection.mutable.Map import scala.collection.mutable.Map scala> val score = Map(("zhansan",90),("lisi",80)) score: scala.collection.mutable.Map[String,Int] = Map(zhansan -> 90, lisi -> 80) scala> val score = scala.collection.mutable.Map("zhansan"->100,"lisi"->95) score: scala.collection.mutable.Map[String,Int] = Map(zhansan -> 100, lisi -> 95) scala> val ages = new scala.collection.mutable.HashMap[String,Int] // 创建一个空的HashMap ages: scala.collection.mutable.HashMap[String,Int] = Map() // LinkedHashSet会用一个链表维护插入顺序 scala> val s = new scala.collection.mutable.LinkedHashSet[Int]() s: scala.collection.mutable.LinkedHashSet[Int] = Set() scala> s += 1 res110: s.type = Set(1) scala> s+=4 res111: s.type = Set(1, 4) scala> s += 2 res112: s.type = Set(1, 4, 2) // SortedSet会自动根据key来进行拍寻 scala> val s = scala.collection.mutable.SortedSet("orange","apple","banana") s: scala.collection.mutable.SortedSet[String] = TreeSet(apple, banana, orange)

map的基本操作:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
scala> score("zhansan") res89: Int = 100 scala> if(score.contains("zhan")) score("zhan") else -1 res90: Int = -1 scala> score.getOrElse("zhan",-2) res91: Int = -2 scala> score.getOrElse("zhansan",-2) res92: Int = 100 scala> score.isEmpty res93: Boolean = false scala> score.keys res94: Iterable[String] = Set(zhansan, lisi) scala> score.values res95: Iterable[Int] = HashMap(100, 95)

其他操作:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
scala> score("zhansan")=60 scala> score res97: scala.collection.mutable.Map[String,Int] = Map(zhansan -> 60, lisi -> 95) scala> score("zhang")=90 scala> score res99: scala.collection.mutable.Map[String,Int] = Map(zhansan -> 60, lisi -> 95, zhang -> 90) scala> score += ("zhaowu"->55) res100: score.type = Map(zhansan -> 60, zhaowu -> 55, lisi -> 95, zhang -> 90) scala> score += ("zhao",55) //因为","用来当作元素分割符号了 <console>:16: error: type mismatch; found : String("zhao") required: (String, Int) score += ("zhao",55) ^ <console>:16: error: type mismatch; found : Int(55) required: (String, Int) score += ("zhao",55) ^ scala> score += (("zhao",55)) res102: score.type = Map(zhao -> 55, zhansan -> 60, zhaowu -> 55, lisi -> 95, zhang -> 90) scala> score += (("zh1",99),("zh2",100)) res103: score.type = Map(zh1 -> 99, zhao -> 55, zhansan -> 60, zhaowu -> 55, lisi -> 95, zhang -> 90, zh2 -> 100) scala> score -= "zh1" res104: score.type = Map(zhao -> 55, zhansan -> 60, zhaowu -> 55, lisi -> 95, zhang -> 90, zh2 -> 100) scala> for((k,v) <- score) println(k+":"+v) zhao:55 zhansan:60 zhaowu:55 lisi:95 zhang:90 zh2:100

遍历map

复制代码
1
2
3
4
5
6
7
8
9
10
11
// 遍历map的entrySet scala> val ages = Map("Leo"->31,"Jack"->40,"Jen"->25) ages: scala.collection.immutable.Map[String,Int] = Map(Leo -> 31, Jack -> 40, Jen -> 25) scala> for((key,value) <- ages) println(key+" "+value) Leo 31 Jack 40 Jen 25 // 生成新map,反转key和value scala> for((key,value) <- ages) yield(value,key) res38: scala.collection.immutable.Map[Int,String] = Map(31 -> Leo, 40 -> Jack, 25 -> Jen)

map排序

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
// SortedMap可以自动对Map的key排序 scala> val ages = scala.collection.immutable.SortedMap[String,Int]("Leo"->30,"Jac k"->20,"Jen"->25) ages: scala.collection.immutable.SortedMap[String,Int] = Map(Jack -> 20, Jen -> 25, Leo -> 30) // LinkedHashMap可以记住插入entry的顺序 scala> val ages = new scala.collection.mutable.LinkedHashMap[String,Int] ages: scala.collection.mutable.LinkedHashMap[String,Int] = Map() scala> ages("Leo")=30 scala> ages("alice") = 20 scala> ages("mike") = 25 scala> ages res42: scala.collection.mutable.LinkedHashMap[String,Int] = Map(Leo -> 30, alice -> 20, mike -> 25)

元组

创建元组(元组元素不可修改)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
scala> val t1=(1,2,3,4) t1: (Int, Int, Int, Int) = (1,2,3,4) scala> val t2=("java","scala",1) t2: (String, String, Int) = (java,scala,1) scala> t2._1 res106: String = java scala> t2._3=2 //元组元素不可修改 <console>:15: error: reassignment to val t2._3=2 ^ scala> var t2=("java","scala",1) t2: (String, String, Int) = (java,scala,1) scala> t2._3=2 //元组元素不可修改 <console>:15: error: reassignment to val t2._3=2 ^ scala> val t4,(a,b,c)=("qian","edu",1) t4: (String, String, Int) = (qian,edu,1) a: String = qian b: String = edu c: Int = 1 scala> val t5=new Tuple2("dashuju",1) t5: (String, Int) = (dashuju,1) scala> val t5=new Tuple5("dashuju",1,2,3,4) t5: (String, Int, Int, Int, Int) = (dashuju,1,2,3,4)

操作元组

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
scala> val t5=new Tuple5("dashuju",1,2,3,4) t5: (String, Int, Int, Int, Int) = (dashuju,1,2,3,4) scala> t5.productIterator.foreach(i=>println(i)) dashuju 1 2 3 4 scala> t5.productIterator.foreach(println(_)) dashuju scala> val a1=Array("java","scala","python") a1: Array[String] = Array(java, scala, python) scala> val a2=Array(1,2,3) a2: Array[Int] = Array(1, 2, 3) scala> a1.zip(a2) res110: Array[(String, Int)] = Array((java,1), (scala,2), (python,3)) scala> val v3=Array(4,5,6,7) v3: Array[Int] = Array(4, 5, 6, 7) scala> a1.zip(v3) res113: Array[(String, Int)] = Array((java,4), (scala,5), (python,6)) scala> a1.zipAll(v3) //缺少参数 <console>:17: error: not enough arguments for method zipAll: (that: scala.collection.GenIterable[B], thisElem: A1, thatElem: B)(implicit bf: scala.collection.generic.CanBuild From[Array[String],(A1, B),That])That. Unspecified value parameters thisElem, thatElem. a1.zipAll(v3) ^ scala> val x="a" x: String = a scala> val y=0 y: Int = 0 scala> a1.zipAll(v3,x,y) res116: Array[(String, Int)] = Array((java,4), (scala,5), (python,6), (a,7)) scala> val res=a1.zipAll(v3,x,y) res: Array[(String, Int)] = Array((java,4), (scala,5), (python,6), (a,7)) scala> res.unzip res117: (Array[String], Array[Int]) = (Array(java, scala, python, a),Array(4, 5, 6, 7))

set

特点:

(1)set中的元素不允许重复

(2)set中的元素是无序、随机的

不可变set

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
scala> val set=Set(1,2,3) set: scala.collection.immutable.Set[Int] = Set(1, 2, 3) scala> set+4 res118: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4) scala> set res119: scala.collection.immutable.Set[Int] = Set(1, 2, 3) scala> set - 4 res120: scala.collection.immutable.Set[Int] = Set(1, 2, 3) scala> set - 1 res121: scala.collection.immutable.Set[Int] = Set(2, 3) scala> set res122: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

可变set

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
scala> import scala.collection.mutable.Set import scala.collection.mutable.Set scala> val set2=Set(1,2,3) set2: scala.collection.mutable.Set[Int] = Set(1, 2, 3) scala> set2 + 4 res123: scala.collection.mutable.Set[Int] = Set(1, 2, 3, 4) scala> set2 res124: scala.collection.mutable.Set[Int] = Set(1, 2, 3) scala> set2 += 4 res125: set2.type = Set(1, 2, 3, 4) scala> set2 res126: scala.collection.mutable.Set[Int] = Set(1, 2, 3, 4) scala> set2 -= 5 res127: set2.type = Set(1, 2, 3, 4) scala> set2 -= 3 res128: set2.type = Set(1, 2, 4) scala> set2 += 2 res129: set2.type = Set(1, 2, 4) scala> set2.head res130: Int = 1 scala> set2.tail res131: scala.collection.mutable.Set[Int] = Set(2, 4) scala> set2.isEmpty res132: Boolean = false scala> set2.max res133: Int = 4 scala> val set3=Set(3,4,5,6) set3: scala.collection.mutable.Set[Int] = Set(5, 6, 3, 4) scala> set2 res134: scala.collection.mutable.Set[Int] = Set(1, 2, 4) scala> set2 ++ set3 res135: scala.collection.mutable.Set[Int] = Set(1, 5, 2, 6, 3, 4) scala> set3 res136: scala.collection.mutable.Set[Int] = Set(5, 6, 3, 4) scala> set2.intersect(set3) res137: scala.collection.mutable.Set[Int] = Set(4)

集合函数

1.sum,max,min

复制代码
1
2
3
4
5
scala> val list1=List(2,3,4,6,7) list1: List[Int] = List(2, 3, 4, 6, 7) scala> list1.sum res138: Int = 22

2.filter 对传入的每个元素都进行条件判断,如果对元素返回true,则保留该元素,否则过滤掉该元素

复制代码
1
2
3
scala> list1.filter(e=>e%2==0) res139: List[Int] = List(2, 4, 6)

3.flatten

复制代码
1
2
3
4
5
6
7
scala> val list2=List(5,6,7) list2: List[Int] = List(5, 6, 7) scala> val list3=List(list1,list2) list3: List[List[Int]] = List(List(2, 3, 4, 6, 7), List(5, 6, 7)) scala> list3.flatten res140: List[Int] = List(2, 3, 4, 6, 7, 5, 6, 7)

4.flatMap,map

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
scala> list1.map(_*10) res143: List[Int] = List(20, 30, 40, 60, 70) scala> val list4=List('a','b','c') list4: List[Char] = List(a, b, c) scala> val list5=list4.map(ch=>List(ch,ch.toUpper)) list5: List[List[Char]] = List(List(a, A), List(b, B), List(c, C)) scala> list5.flatten res144: List[Char] = List(a, A, b, B, c, C) scala> val list6=list4.flatMap(ch=>List(ch,ch.toUpper)) list6: List[Char] = List(a, A, b, B, c, C) // 将List中的多行句子拆分成单词 scala> List("Hello World","You Me").flatMap(_.split(" ")) res117: List[String] = List(Hello, World, You, Me)

5.forall,foreach

复制代码
1
2
3
4
5
6
7
8
9
scala> list1.forall(e=>e>0) res146: Boolean = true scala> list1.foreach(println) 2 3 4 6 7

6.foldLeft,foldRight,reduceLeft,reduceRight

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
scala> list1.reduceLeft(_+_) res150: Int = 22 scala> list1 res151: List[Int] = List(2, 3, 4, 6, 7) scala> list1.reduceLeft(_-_) res152: Int = -18 scala> list1.reduceRight(_-_) res153: Int = 4 scala> list1.foldLeft(0)(_+_) res155: Int = 22 scala> list1.foldLeft(10)(_+_) res156: Int = 32

7.sortWith 对元素进行两两相比,进行排序

复制代码
1
2
3
scala> Array(3,2,4,10,1).sortWith(_<_) res101: Array[Int] = Array(1, 2, 3, 4, 10)

练习:统计多个文本内的单词总数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
// 使用scala的io包将文本文件内的数据读取出来 scala> val lines01 = scala.io.Source.fromFile("C://Users//89240//Desktop//test01.txt").mkString lines01: String = Hello you scala> val lines02 = scala.io.Source.fromFile("C://Users//89240//Desktop//test02.txt").mkString lines02: String = hello me // 使用List的伴生对象,将多个文件内的内容创建为一个List scala> val lines = List(lines01,lines02) lines: List[String] = List(Hello you, hello me) // 多个高阶函数的链式调用,以及大量下划线的使用 scala> lines.flatMap(_.split(" ")).map((_,1)).map(_._2).reduceLeft(_ + _) res120: Int = 4

类和属性

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class PersonS { //val修饰的属性,系统会自动生成getter方法 val id:String = "1234" def getId():String={ println("hello") this.id } //var修饰的属性,系统会自动生成getter和setter方法 var name:String = "" //private var修饰的属性,系统会自动生成private修饰的get和set方法 //相当于类的私有字段 private var gender:Int = 0 //private[this]修饰的属性,系统不会生成set,get方法 //只有当前对象可以访问该属性 private[this] var age:Int = 0 } object test{ def main(args: Array[String]): Unit = { var per:PersonS = new PersonS() println(per.id) println(per.getId()) per.name = ("zhangsan") println(per.name) } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 调用getter和setter方法,分别叫做变量名和变量名_= // 如果不希望生成getter和setter方法,则将变量声明为private[this] scala> class Student { | var name = "leo" | } defined class Student scala> val s = new Student s: Student = Student@3e8c4396 scala> s.name res45: String = leo scala> s.name="Jack" s.name: String = Jack

内部类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
scala> class Class { | class Student(val name:String) {} | val student = new ArrayBuffer[Student] | def getStudent(name: String) = { | new Student(name) | } | } defined class Class scala> val c1 = new Class c1: Class = Class@df1561f scala> val s1 = c1.getStudent("leo") s1: c1.Student = Class$Student@21b64cf scala> c1.student += s1 res47: c1.student.type = ArrayBuffer(Class$Student@21b64cf) scala> val c2 = new Class c2: Class = Class@5dd00359 scala> val s2 = c2.getStudent("leo") s2: c2.Student = Class$Student@716287c4 scala> c1.Student += s2 // s1和s2属于不同的外部类的属性,每个外部类的内部类都是不同的类 <console>:21: error: value Student is not a member of Class c1.Student += s2

构造函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//class ConstructorDemo { // var a:Int = 0 // println("Construtor Study") // //定义辅助构造函数 // def this(a1:Int){ // //首先需要调用主构造函数,或其他辅助构造函数 // this() // this.a = a1 // } //} //定义一个带有参数的主构造函数 //class ConstructorDemo(var b:Int) { // // var a:Int = 0 // println("Construtor Study") // //定义一个辅助构造函数 // def this(a1:Int,b1:Int){ // this(b1) //调用主构造函数 // this.a = a1 // } // //} //定义一个私有的主构造函数 class ConstructorDemo private (var b:Int) { var a:Int = 0 println("Construtor Study") //定义一个辅助构造函数 def this(a1:Int,b1:Int){ this(b1) //调用主构造函数,可以定义为私有的 this.a = a1 } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 辅助构造函数可以有多个,叫重载 scala> class Student { | private var name = "" | private var age = 0 | def this(name:String){ | this() | this.name = name | } | def this(name: String,age:Int) { | this(name) | this.age = age | } | } defined class Student scala> val s1 = new Student s1: Student = Student@2ed855dc scala> val s2 = new Student("leo") s2: Student = Student@115a512c scala> val s3 = new Student("leo",18) s3: Student = Student@571f626c
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//类自带有无参的构造函数 //主构造函数会执行类中定义的所有语句 //构造函数分为主构造函数和辅助构造函数 object ConstructorDemoTest{ def main(args: Array[String]): Unit = { // val obj:ConstructorDemo = new ConstructorDemo() // val obj:ConstructorDemo = new ConstructorDemo(a1=100) // println(obj.a) } }

单例对象和伴生对象

// object叫单例对象,可以定义工具类和常量

// 单例对象不能带参数,因为无法实列化

// 单例对象调用的时候才会初始化

// object,相当于class的单个实例,通常在里面放一些静态的变量或方法

// 第一次调用object的方法时,就会执行object的constructor,也就是object内部不在method中的代码;但是object不能定义接受参数的construct

// 注意,object的construct只会在其第一次被调用时执行一次,以后再次调用就不会再次执行construct了

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
scala> object Person { | private var eyeNum = 2 | println("this Person object!") | def getEyeNum = eyeNum | } defined object Person scala> Person // 第一次调用,会执行construct this Person object! res49: Person.type = Person$@3040acea scala> Person.getEyeNum // 第二次调用,不会执行construct res50: Int = 2
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
object Logger { def log(msg:String): Unit = { println(s"INFO:$msg") } } class Test{ def method:Unit = { Logger.log("hello") } } object LoggerTest{ def main(args: Array[String]): Unit = { Logger.log("haha") val obj:Test = new Test() obj.method } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//伴生类 class AccountInfo { // var id = 0 var id = AccountInfo.newUniqueNumber } //伴生对象和类在同一个文件中,且同名 //类的伴生对象,伴生对象和类可以互相访问彼此的私有属性,或者方法 object AccountInfo{ private var lastNumber = 0 private def newUniqueNumber: Int= { lastNumber += 1 lastNumber } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
scala> object Person { | private val eyeNum = 2 | def getEyeNum = eyeNum | } defined object Person scala> class Person(val name: String,val age: Int){ | def sayHello = println("Hi,"+name+", Iguess you are "+age+"years old!"+",and usually you must have"+Person.getEyeNum+"eyes.") | } defined class Person warning: previously defined object Person is not a companion to class Person. Companions must be defined together; you may wish to use :paste mode for this. scala> val p = new Person("leo",30) p: Person = Person@6b27f909 scala> p.sayHello Hi,leo, Iguess you are 30years old!,and usually you must have2eyes.
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//object companionTest{ // def main(args: Array[String]): Unit = { // var obj:AccountInfo = new AccountInfo() // println(obj.id) // } //} //应用程序对象 object companionTest extends App{ var obj:AccountInfo = new AccountInfo() println(obj.id) }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// object也可以继承抽象类,并覆盖抽象类中的方法 scala> abstract class Hello(var message: String){ | def sayHello(name: String): Unit | } defined class Hello scala> object HelloImpl extends Hello("hello"){ | override def sayHello(name: String)={ | println(message+","+name) | } | } defined object HelloImpl scala> HelloImpl.sayHello("leo") hello,leo
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// scala中没有提供枚举特性,如果要实现枚举,则需要用object继承Enumeration类,并且调用Value方法来初始化枚举值 scala> object Season extends Enumeration { | val SPRING, SUMMER, AUTUMN, WINTER = Value | } defined object Season scala> Season.SPRING res57: Season.Value = SPRING // 可以通过Value传入枚举值的id和name,通过id和toString可以获取;还可以通过id和name来查找枚举值 scala> object Season extends Enumeration { | val SPRING = Value(0,"spring") | val SUMMER = Value(1,"summer") | val AUTUMN = Value(2,"autumn") | val WINTER = Value(3,"winter") | } defined object Season scala> Season.SPRING.id res58: Int = 0 scala> Season.SPRING.toString res59: String = spring scala> Season(0) res60: Season.Value = spring scala> Season(2) res61: Season.Value = autumn scala> Season.withName("winter") res63: Season.Value = winter // 使用枚举object.values可以遍历枚举值 scala> for(ele <- Season.values) print(ele+" ") spring summer autumn winter

apply方法和unapply方法

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class User(val name:String,val password:String) { } //apply用来构造一个类的对象 //apply方法叫注入器,unapply方法叫提取器 object User{ def apply(name: String, password: String) = new User(name, password) def unapply(arg: User): Option[(String, String)] = { if(arg == null) None else{ Some(arg.name,arg.password) } } } object userTest{ def main(args: Array[String]): Unit = { // val obj = new User("zhangsan", "123456") val obj = User("zhangsan","123456") // println("result:"+obj.isInstanceOf[User]) // val arr = Array(1,2,3,4) obj match { case User(name,password) => println(name+":"+password) case _ => println("None") } } }

继承

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
class Point(val xc:Int,val yc:Int) { var x:Int = xc var y:Int = yc def move(dx:Int,dy:Int):Unit ={ x = x+dx y = y+dy //打印移动后的坐标 println("x的坐标:"+x) println("y的坐标:"+y) } } //继承了父类的所有属性和方法 //重写父类的非抽象方法,要用override,此时若需要调用父类方法,使用super关键字 //重写父类的抽象方法,override可选择 //final修饰的类、方法、属性,不能被继承/重写 class Location(override val xc:Int,override val yc:Int, val zc:Int) extends Point(xc,yc){ var z:Int = zc def move(dx:Int,dy:Int,dz:Int):Unit ={ x = x+dx y = y+dy z = z+dz //打印移动后的坐标 println("x的坐标:"+x) println("y的坐标:"+y) println("z的坐标:"+z) } } // 如果创建了子类对象,但是又将其赋予了父类类型的变量,则在后续的程序中,又需将父类类型的变量转换为子类类型的变量 // 首先使用isInstanceOf判断对象是否是指定类的对象,如果是的话,可以用asInstanceOf将对象转换为指定类型 // 注意,如果对象是null,则isInstanceOf一定返回false,asInstanceOf一定返回null // 注意,如果没有先使用isInstanceOf先判断对象是否为指定类的实例,就直接用asInstanceOf转换,可能会抛出异常 object testClass{ def main(args: Array[String]): Unit = { val obj1= new Point(2,3) val obj=new Location(5,6,7) obj.move(1,2,3) //判断对象是否属于给定的类? println(obj.isInstanceOf[Location]) //类型转换 obj.asInstanceOf[Point] //获取类的对象信息 println(classOf[Location]) } } // isInstanceOf只能判断出对象是否是指定类以及子类的对象,而不能精确判断出,对象就是指定类的对象 // 如果要求精确的判断对象就是指定类的对象,只能使用getClass和classOf // 对象.getClass可以精确获得对象的类,classOf[类]可以精确获取类,然后使用==操作符即可判断 scala> class Person defined class Person scala> class Student extends Person defined class Student scala> val p: Person = new Student p: Person = Student@6f2bd101 scala> p.isInstanceOf[Student] res77: Boolean = true scala> p.isInstanceOf[Person] res78: Boolean = true scala> p.getClass == classOf[Person] res79: Boolean = false scala> p.getClass == classOf[Student] res80: Boolean = true // 每个类可以有一个主constructor和任意多个辅助constructor,而每个辅助constructor的第一行都必须是调用其他辅助constructor或者主constructor;因此子类的辅助constructor是一定不可能直接调用父类的constructor的 // 只能在子类的主constructor中调用父类的constructor,以下这种语法就是通过子类的主构造函数来调用父类的构造函数 // 注意,如果是父类中接收的参数,比如name和age,子类中接收时,就不要使用任何valh或var来修饰了,否则会认为是子类要覆盖父类的field scala> class Person(val name: String, val age: Int) defined class Person scala> class Student(name: String, age: Int, var score: Double) extends Person(name,age){ | def this(name:String){ | this(name,0,0) | } | def this(age:Int){ | this("leo",age,0) | } | } defined class Student scala> val s = new Student("leo",30,100) s: Student = Student@14eb22d scala> s.name res81: String = leo scala> s.age res82: Int = 30 scala> s.score res83: Double = 100.0 scala> val s2 = new Student("li") s2: Student = Student@68f93c2d scala> s2.name res84: String = li scala> s2.age res85: Int = 0 scala> s2.score res86: Double = 0.0 scala> val s3 = new Student(44) s3: Student = Student@7b42f3de scala> s3.name res87: String = leo scala> s3.age res88: Int = 44 scala> s3.score res89: Double = 0.0

抽象类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//定义抽象类,使用关键字:abstract //抽象类不能被实例化 abstract class Person { //可以有抽象字段:没有初始化值 var name:String //抽象方法:没有方法体 def id:Int //可以原有具体方法 def smile:Unit={ println("person can smile") } } class Employ extends Person { var name = "Jerry" def id:Int ={ name.hashCode } //重载具体方法,需要加上override关键字 override def smile:Unit = super.smile } // 特质还是抽象类? // 优先使用特质,因为一个类只能继承一个超类,但是可以混入多个特质; //如果需要构建函数参数,只能只用抽象类,因为特质无法定义带参数的构造函数

特质

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//定义一个带有抽象方法的特质,关键字:trait trait Iterator[A]{ def hasNext:Boolean def next():A } //定义一个带有实现的特质,关键字:trait trait ConsoleLogger{ def log(msg:String):Unit = { println(msg) } } // 定义一个类,实现我们的特质 class Intlterator(to:Int) extends Iterator[Int] with ConsoleLogger { private var current = 0 override def hasNext: Boolean = current < to override def next(): Int = { if(hasNext){ log("has next") val t = current current +=1 t }else 0 } } object TraitTest { def main(args: Array[String]): Unit = { val iterator = new Intlterator(to = 10) println(iterator.next()) println(iterator.next()) println(iterator.next()) } }

为实例混入trait

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 有时可以在创建类的对象时,指定该对象混入某个trait,这样,就只有这个对象混入该trait的方法,而类的其他对象则没有。 scala> trait Logged{ | def log(msg: String) {} | } defined trait Logged scala> trait MyLogger extends Logged { | override def log(msg: String){println("log: "+msg)} | } defined trait MyLogger scala> class Person(val name: String) extends Logged { | def sayHello {println("Hi, I'm "+name); log("sayHello is invoked!")} | } defined class Person warning: previously defined object Person is not a companion to class Person. Companions must be defined together; you may wish to use :paste mode for this. scala> val p1 = new Person("leo") p1: Person = Person@7e51c630 scala> p1.sayHello Hi, I'm leo scala> val p2 = new Person("Jack") with MyLogger p2: Person with MyLogger = $anon$1@734e6391 scala> p2.sayHello Hi, I'm Jack log: sayHello is invoked!

trait调用链

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// scala中支持让类继承多个trait后,一次调用多个trait中的同一个方法,只要让多个trait的同一个方法中,在最后都执行super.方法即可 // 类中调用多个trait中都有的这个方法时,首先会从最右边的trait的方法开始执行,然后依次往左执行,形成一个调用链条 // 这种特性非常强大,其实就相当于设计模式中的责任链模式的一种具体实现依赖 scala> trait Handler { | def handle(data: String) {} | } defined trait Handler scala> trait DataValidHandler extends Handler { | override def handle(data: String) { | println("check data: "+ data) | super.handle(data) | } | } defined trait DstaValidHandler scala> trait SignatureValidHandler extends Handler { | override def handle(data: String) { | println("check signature: "+data) | super.handle(data) | } | } defined trait SignatureValidHandler scala> class Person(val name: String) extends SignatureValidHandler with DataVali dHandler { | def sayHello = {println("Hello, "+name); handle(name)} | } defined class Person warning: previously defined object Person is not a companion to class Person. Companions must be defined together; you may wish to use :paste mode for this. scala> val p = new Person("leo") p: Person = Person@3d86a682 scala> p.sayHello Hello, leo check data: leo check signature: leo

在trait中覆盖抽象方法

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 在trait中,是可以覆盖父trait的抽象方法的 // 但是覆盖时,如果使用了super.方法的代码,则无法通过编译。因为super.方法就会去掉用父trait的抽象方法,此时子trait的该方法还是会被认为是抽象的 // 此时如果要通过编译,就得给子trait的方法加上abstract override修饰 scala> trait Logger{ | def log(msg: String) | } defined trait Logger scala> trait MyLogger extends Logger{ | abstract override def log(msg: String) {super.log(msg)} | } defined trait MyLogger

混合使用trait的具体方法和抽象方法

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 在trait中,可以混合使用具体方法和抽象方法 // 可以让具体方法依赖于抽象方法,而抽象方法则放到继承trait的类中去实现 // 这种trait其实就是设计模式中的模板设计模式的体现 scala> trait Valid{ | def getName : String | def valid: Boolean = { | getName == "leo" | } | } defined trait Valid scala> class Person(val name: String) extends Valid { | println(valid) | def getName = name | } defined class Person scala> val p = new Person("leo") true p: Person = Person@473232e2

trait的构造机制

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 在scala中,trait也是有构造代码的,也就是trait中的,不包含在任何方法中的代码 // 而继承了trait的类的构造机制如下: // 1.父类的构造函数执行; // 2.trait的构造代码执行,多个trait从左到右依次执行; // 3.构造trait时会先构造父trait,如果多个trait继承同一个父trait,则父trait只会构造一次; // 4.所有trait构造完毕之后,子类的构造函数执行 scala> class Person{println("Person's constructor!")} defined class Person warning: previously defined object Person is not a companion to class Person. Companions must be defined together; you may wish to use :paste mode for this. scala> trait Logger { println("Logger's constructor!")} defined trait Logger scala> trait MyLogger extends Logger {println("MyLogger's constructor!")} defined trait MyLogger scala> trait TimeLogger extends Logger { println("TimeLogger's constructor!")} defined trait TimeLogger scala> class Student extends Person with MyLogger with TimeLogger { | println("Student's constructor!") | } defined class Student scala> val s = new Student Person's constructor! Logger's constructor! MyLogger's constructor! TimeLogger's constructor! Student's constructor! s: Student = Student@1619c34d

trait field的初始化

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 在Scala中,trait是没有接收参数的构造函数的,这是trait和class的唯一区别,但是如果需求就是要trait能够对field进行初始化,那只能使用Scala中非常特殊的一种高级特性--提前定义 scala> trait SayHello { | val msg: String | println(msg.toString) | } defined trait SayHello scala> class Person extends SayHello { | val msg: String = "init" | } defined class Person warning: previously defined object Person is not a companion to class Person. Companions must be defined together; you may wish to use :paste mode for this. scala> val p = new Person // 因为trait中的field还没有初始化,所以出错 java.lang.NullPointerException at SayHello.$init$(<console>:20) ... 29 elided scala> class Person defined class Person scala> val p = new { val msg: String = "init" } with Person with SayHello init p: Person with SayHello = $anon$1@678397a4 scala> val p = new Person p: Person = Person@2391e19c

特质的应用1

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 将trait作为接口使用 scala> :paste // Entering paste mode (ctrl-D to finish) trait SayHello { def sayHello(name: String) } trait MakeFriends { def makeFriends(p: Person) } class Person(val name: String) extends SayHello with MakeFriends { def sayHello(otherName: String) = println("Hello, "+otherName+"I'am "+name) def makeFriends(p: Person) = println("Hello, "+p.name+"I'am "+name+", I want to make friends with you.") } // Exiting paste mode, now interpreting. defined trait SayHello defined trait MakeFriends defined class Person warning: previously defined object Person is not a companion to class Person. Companions must be defined together; you may wish to use :paste mode for this. scala> val p = new Person("leo") p: Person = Person@79690db2 scala> val p2 = new Person("Jack") p2: Person = Person@7727a81c scala> p.sayHello("Jack") Hello, JackI'am leo scala> p.makeFriends(p2) Hello, JackI'am leo, I want to make friends with you.
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
trait Logger{ def log(msg:String) } //定义一个子特质,实现父特质里的抽象方法 trait ConsoleLogger2 extends Logger{ override def log(msg: String): Unit = println(msg) } //给日志加上时间戳 trait TimestampLogger extends ConsoleLogger2{ override def log(msg: String): Unit = super.log(msg=s"${java.time.Instant.now()}$msg") } //如果日志过长,对日志进行截断显示和 trait ShortterLogger extends ConsoleLogger2{ val maxLength = 15 override def log(msg: String): Unit = super.log( if(msg.length <= maxLength) msg else s"${msg.substring(0,maxLength-3)}...") } class Account{ protected var balance:Double = 0.0 } class SavingAccount extends Account with ConsoleLogger2 { def withdraw(amount:Double):Unit ={ if(amount > balance) log(msg="Insufficent funds") else balance = balance -amount } } //特质可以为我们的类提供可以堆叠的改变 object TraitTest2 { def main(args: Array[String]): Unit = { var acc1 = new SavingAccount with ConsoleLogger2 with TimestampLogger with ShortterLogger var acc2 = new SavingAccount with ConsoleLogger2 with ShortterLogger with TimestampLogger acc1.withdraw(100.0) acc2.withdraw((100.0)) } }

特质的应用2

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
trait Logger3{ def log(msg:String) //定义一个类,实现这个抽象方法,下面的三个具体方法都可以调用,把瘦接口变成了复接口 def info(msg:String):Unit ={log( msg = "INFO:"+msg)} def severe(msg:String):Unit ={log( msg = "SEVERE:"+msg)} def warn(msg:String):Unit ={log( msg = "WARN:"+msg)} } // 定义超类 class Account{ protected var balance:Double = 0 } // 定义子类 class SavingAccount extends Account with Logger3{ override def log(msg: String): Unit = println(msg) def withdraw(amount:Double):Unit ={ if(amount > balance) severe(msg = "Insufficent funds") else { balance = balance -amount info("you withdraw....") } } } object TraitTest3 { def main(args: Array[String]): Unit = { val acc= new SavingAccount acc.withdraw(100.0) } }

样例类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
object CaseclassDemo { def main(args: Array[String]): Unit = { //定义样例类,关键字 case //默认带有apply方法 //构造函数的参数默认是public val修饰的 case class Message(sender:String,recipient:String,body:String) //创建样例类的对象 val message1 = Message("Jerry", "Tom", "Hello") println(message1.sender) // 样例类的比较,基于值或者结构比较,而不是基于引用 val message2 = Message("Jerry","Tom","Hello") if(message1==message2) println("same") else println("different") //样例类的copy,是浅拷贝 val message3 = message1.copy() println(message3.sender+":"+message3.recipient+":"+message3.body) if(message1==message3) println("same") else println("different") //不完全copy,对部分参数赋值 val message4 = message1.copy(sender="hanmeimei") println(message4.sender+":"+message4.recipient+":"+message4.body) } }

模式匹配

(1)常量模式匹配
(2)变量模式匹配
(3)通配符模式匹配

语法:case 值 => 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
object PatternDemo { def main(args: Array[String]): Unit = { //常量模式匹配 //常量字面值的匹配 val site1 = "baidu.com" site1 match { case "baidu.com" => println("success") //前面的都不匹配,就会匹配这句 //不需要break case _ => println("fail") } //常量变量的匹配,变量名一定要大写 val site2 = "baidu.com" val BAIDU = "baidu.com" site2 match { case BAIDU => println("success") //前面的都不匹配,就会匹配这句 //不需要break case _ => println("fail") } //变量模式的匹配,变量名小写,会把要匹配的变量赋值给这个变量 val site3 = "baidu.com" val baidu = "ba.com" site3 match { case baidu => println(baidu+"success") //前面的都不匹配,就会匹配这句 //不需要break case _ => println("fail") } //通配符模式匹配 //通配符用下划线表示 val list = List(1,2,3) list match{ case List(_,_,3) => println("success") case _ => println("fail") } } }

样例类匹配

类型匹配
语法:case 变量:类型 => 代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 类型匹配 scala> import java.io._ import java.io._ scala> def processException(e: Exception) { | e match { | case e1:IllegalArgumentException => println("you passed illegal argument. exception is: "+e1) | case e2: FileNotFoundException => println("cannot find the file. exception is: "+e2) | case e3: IOException => println("you not an error while you were doing IO operation! exception is: "+e3) | case _: Exception => println("cannot know which exception you have!") | } | } processException: (e: Exception)Unit scala> processException(new IllegalArgumentException("expect two argument, but fo und one arguent.")) you passed illegal argument. exception is: java.lang.IllegalArgumentException: expect two argument, but found one arguent. scala> processException(new FileNotFoundException("test.txt not found.")) cannot find the file. exception is: java.io.FileNotFoundException: test.txt not found. scala> processException(new IOException("get data from socket fail.")) you not an error while you were doing IO operation! exception is: java.io.IOException: get data from socket fail. scala> processException(new ArrayIndexOutOfBoundsException("array is null.")) cannot know which exception you have!
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
object PatternDemo2 { def main(args: Array[String]): Unit = { //做信息的识别 abstract class Notification //定义不同信息的样例类,都继承 Notification,就可以使用这些样例类 case class Email(sender:String,title:String,body:String) extends Notification case class SMS(caller:String,message:String) extends Notification case class VoiceRecording(contactName:String,link:String) extends Notification //做信息的识别 def showNotification(notification: Notification):String ={ notification match{ case Email(sender,title,_) if(sender=="zhangsan") => "you get an important Email message from "+sender case SMS(caller,message) => "you get a SMS message from "+caller case VoiceRecording(contactName,link) => "you get a VoiceRecording message from "+contactName case _ => "you get an message" } } //创建一条信息 val email = Email("zhangsan","important","something") print(showNotification(email)) val email1 = Email("lisi","important","sda") println(showNotification(email1)) //类型匹配 val arr = Array("sss",1,2.3,'e') //随机取数组中的一个元素 val obj = arr(scala.util.Random.nextInt(4)) println(obj) obj match { case x:Int => println(x) case s:String => println(s.toUpperCase) case d:Double => println(Int.MaxValue) case _ => println("fail") } } }

// 对Array进行模式匹配,分别可以匹配带有指定元素的数组、带有指定个数元素的数组、以某元素打头的数组

// 对List进行模式匹配,与Array类似,但是需要使用List特有的::操作符

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 用Array scala> def greeting(arr: Array[String]) { | arr match { | case Array("leo") => println("How are you, leo") | case Array(girl1,girl2,girl3) => println("hi, girls, I'am jack, nice to meet you. "+girl1+", "+girl2+", "+girl3) | case Array("lei",_*) => println("hi, leo, why not introduce your frineds") | case stranger => println("hi, "+stranger+", who are you") | } | } greeting: (arr: Array[String])Unit scala> greeting(Array("leo")) How are you, leo scala> greeting(Array("lili","meimei","jie")) hi, girls, I'am jack, nice to meet you. lili, meimei, jie scala> greeting(Array("lei","meimei","jie")) hi, girls, I'am jack, nice to meet you. lei, meimei, jie // 用List scala> def greeting(list: List[String]) { | list match { | case "leo"::Nil => println("hi, leo") | case girl1::girl2::girl3::Nil => println("hi, girls, I'am jack, nice to meet you. "+girl1+", "+girl2+", "+girl3) | case "leo"::tail => println("hi, leo, please introduce you friends to me.") | case _ => println("hey, who are you") | } | } greeting: (list: List[String])Unit scala> greeting(List("leo")) hi, leo scala> greeting(List("leo","lili","jie")) hi, girls, I'am jack, nice to meet you. leo, lili, jie scala> greeting(List("jac","lili","jie")) hi, girls, I'am jack, nice to meet you. jac, lili, jie scala> greeting(List("jen")) hey, who are you

偏函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
object PartialFunctionDemo { //创建一个普通函数 val divl = (x:Int) => 100/x //定义一个偏函数 val div2 = new PartialFunction[Int,Int] { override def isDefinedAt(x: Int): Boolean = x!=0 override def apply(x: Int): Int = 100/x } //使用case 定义偏函数 val div3:PartialFunction[Int,Int]={ case d:Int if(d!=0) => 100/d } val res:PartialFunction[Int,String]={ case 1 => "one" case 2 => "two" case _ => "other" } //orElse 组合多个偏函数 val r1:PartialFunction[Int,String]={case 1 => "one"} val r2:PartialFunction[Int,String]={case 2 => "two"} val r3:PartialFunction[Int,String]={case _ => "other"} val res2 = r1 orElse r2 orElse r3 //相当于res函数 //andThen 偏函数串联 val r4:PartialFunction[Int,String] = {case cs if(cs == 1) => "one"} val r5:PartialFunction[String,String] = {case cs if(cs eq "one") => "the number is one"} val res3:(Int=>String) = r4 andThen(r5) def main(args: Array[String]): Unit = { println(div2.isDefinedAt(1)) div2(1) println(div2.isDefinedAt(0)) println(div3.isDefinedAt(1)) div3(1) println(div3.isDefinedAt(0)) println(res.isDefinedAt(1)) println(res(1)) println(res.isDefinedAt(3)) println(res(3)) println(res2.isDefinedAt(1)) println(res2(1)) println(res2.isDefinedAt(3)) println(res2(3)) println(res3(1)) println(res3(3)) } }

密封类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
用sealed修饰的类或者特质 约束:不能在类定义文件之外定义它的子类 作用1:避免滥用继承 作用2:用在模式匹配中 sealed abstract class Furniture case class Couch() extends Furniture case class Chair() extends Furniture object SealedDemo { def findPlaceToSit(furniture:Furniture):String = furniture match { case a:Couch => "lie on the couch" case b:Chair => "sit on the chair" case _ => "no match" } val chair = Chair() def main(args: Array[String]): Unit = { println(findPlaceToSit(chair)) } }

option类型

返回值可能有值,可能无值,返回值类型可以定义为option类型

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
object OptionDemo { def main(args: Array[String]): Unit = { val map= Map("a"->1,"b"->2) // println(map("a")) // println(map("c")) val a:Option[Int] = map.get("c") println(a) } }

字符串插值

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
插值器 f, s, raw object StringDemo { def main(args: Array[String]): Unit = { //s 字符串插值器 val name = "jerry" val res = s"hello,$name" //对${表达式}中的表达式进行计算 val res1 = s"1+1=${1+1}" println(res) println(res1) //f 插值器 val height = 1.9d val name1 = "tom" val res2 = f"$name1 is $height%2.2f meters tall" println(res2) //raw 插值器,类似与 s 插值器,但不对其中的内容做转换 val str = s"anb" println(str) val str2 = raw"anb" println(str2) } }

文件操作

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.io.PrintWriter import scala.io.Source object FileDemo extends App{ //读取文件行 val source = Source.fromFile("src/filetest") //获取文件行迭代器 val lines = source.getLines() for(line <- lines) println(line) //关闭源 source.close() //读取文件的每一个字符 val source1 = Source.fromFile("src/filetest") val iter = source1.buffered var sum = 0 while (iter.hasNext){ if(iter.head=='a') sum = sum + 1 println(iter.next()) } //打印符合条件字符的统计结果 println("sum:"+sum) source1.close //读取网络文件 val source2 = Source.fromURL("http://1000phone.com") val lines2 = source2.getLines() for(line <- lines2) println(line) //关闭源 source2.close //写文件 val out = new PrintWriter( "fileresult.txt") for(i <- 1 to 100) out.println(i) out.close() }

正则表达式

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import scala.util.matching.Regex object RegeDemo extends App{ //构造一个正则表达式,通过.r val pattern1 = "[0-9]+".r val pattern2 = new Regex("[0-9]+") //如果正则表达式中含有斜杆,或者引号,可以用三引号"""...""" val pattern3 = """s+[0-9]+s""" val matchStr = "99bottles,100bottles" //findAllIn 返回所有匹配项的迭代器 for(item <- pattern1.findAllIn(matchStr)) println(item) //返回首个匹配项 val first = pattern1.findFirstIn((matchStr)) println(first) //检查字符串的开始部分是不是能匹配 val ifStartMatch = pattern1.findPrefixOf(matchStr) println(ifStartMatch) //使用传入的字符串,替换首个匹配项 val res1 = pattern1.replaceFirstIn(matchStr,"xxx") println(res1) //使用传入的字符串,替换所有的匹配项 val res2 = pattern1.replaceAllIn(matchStr,"yyyy") println(res2) }

高阶函数

高阶函数:参数是函数,或者返回值是一个函数,或者参数和返回值都是函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
object HFuncDemo extends App{ //传入参数是函数 val arr = Array(1,2,3,4,5) val fun = (x:Int)=>x*2 val res = arr.map(fun) //传入匿名函数 val res1 = arr.map((x:Int)=>x*2) val res2 = arr.map(_*2) println(res.toBuffer) //返回值是函数 def urlBuilder(ssl:Boolean,domainName:String):(String,String)=>String = { val schema = if(ssl) "https://" else "http://" (endpoint:String,query:String) => s"$schema$domainName/$endpoint?$query" } val domainName = "www.1000phone.com" def getUrl:(String,String)=>String = urlBuilder(true,domainName) //得到函数 val endpoint = "users" val query = "id=1" val res3 = getUrl(domainName,query) //用函数接收 println(res3) }

高阶函数的类型推断

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
// 高阶函数可以自动推断出参数类型,而不需要写明类型;而且对于只有一个参数的函数,还可以省去其小括号;如果仅有的一个参数在右侧的函数体内只使用一次,则还可以将接收参数省略,并且将参数用_来替代 greeting: (func: String => Unit, name: String)Unit scala> greeting((name:String) => println("Hello, "+name), "leo") Hello, leo scala> greeting((name) => println("Hello, "+name), "leo") Hello, leo scala> greeting(name => println("Hello, "+name), "leo") Hello, leo scala> def triple(func: Int => Int) = {func(3)} triple: (func: Int => Int)Int scala> triple(3*_) res100: Int = 9

闭包

什么是闭包?

闭包是一个函数,函数的返回值依赖于函数外部的一个或多个变量。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
object FunDemo1 extends App{ val multiply = (x:Int) => x*5 var factor = 5 val multiply2 = (x:Int) => {x*factor} println(multiply2(10)) factor = 10 println(multiply2(10)) val multiply3 = (x:Int) => { factor = factor+10 x*factor } println("factor",factor) println(multiply3(10)) println("factor",factor) }

柯里化

柯里化是把接收多个参数的函数变成接收一个单一参数的函数,并且返回一个接收余下参数的新函数。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
object CurryDemo1 extends App{ //创建一个普通的函数 def add(x:Int,y:Int) = x+y println(add(1,2)) //柯化后的方法 def curryAdd(x:Int)(y:Int)=x+y println(curryAdd(1)(2)) //模拟柯里化的实现过程 def first(x:Int)=(y:Int) => x+y val second = first(1) val res =second(2) println(res) val one = curryAdd(1)_ println(one(2)) val two = curryAdd(2)_ println(two(2)) val list = List(1,2,3,4) println(list.foldLeft(2)(_+_)) }

方法的嵌套和多态

方法的嵌套:方法体里面定义其他嵌套

方法的多态:方法可以通过类型实现参数化,类似泛型

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
object methodDemo extends App{ //方法的嵌套:方法体里面定义其他嵌套 //阶乘 def fatorial(x:Int):Int = { def fact(x:Int,accumulator:Int):Int={ if(x<=1)accumulator else fact(x-1,x*accumulator) } fact(x,accumulator = 1) } println("fatorial of 5:" + fatorial(5)) //方法的多态:方法可以通过类型实现参数化,类似泛型 def listOfDuplicates[A](x:A, length:Int):List[A]={ if(length<1) Nil else x::listOfDuplicates(x,length-1) } println(listOfDuplicates[Int](3, 5)) println(listOfDuplicates("sss",5)) }

隐式转换

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//隐式引用,这三个包都是很默认导入的 import java.lang._ import scala._ import scala.Predef._ import java.io._ import scala.io.Source object ImplicitDemo extends App{ val a:Int = 1 println(a) val map = Map("a"->1) val aa = 1 to 10 val aaa = 1.to(10) println(aa) //定义隐式类,可以把File转换成定义的隐式类,叫RichFile implicit class RichFile(from:File){ def read:String = Source.fromFile(from.getPath).mkString } //使用隐式类做已有类的功能的扩展 val contents = new File("src/filetest").read println(contents) }

上边界Bounds

// 在指定泛型的时候,有时,需要对泛型的范围进行界定,而不是可以是任意的类型。比如,可能要求某个泛型类型,它就必须是某个类的子类,这样在程序中就可以放心的调用泛型类型继承的父类的方法,程序才能正常的使用和运行。此时就可以使用上下边界Bounds的特性。

// scala的上下边界特性允许泛型类型必须是某个类的子类,或者必须是某个类的父类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
scala> class Person(val name:String){ | def sayHello = println("Hello,I'm "+name) | def makeFriends(p:Person){ | sayHello | p.sayHello | } | } defined class Person scala> class Student(name: String) extends Person(name) defined class Student scala> class Party[T <: Person](p1:T,p2:T){ | def play = p1.makeFriends(p2) | } defined class Party scala> class Worker(val name:String) defined class Worker scala> val leo = new Student("leo") leo: Student = Student@318511f0 scala> val tom = new Worker("tom") tom: Worker = Worker@2de07c57 scala> val party = new Party(leo,tom) // 错误的示例 <console>:14: error: inferred type arguments [Object] do not conform to class Party's type parameter bounds [T <: Person] val party = new Party(leo,tom) ^ <console>:14: error: type mismatch; found : Student required: T val party = new Party(leo,tom) ^ <console>:14: error: type mismatch; found : Worker required: T val party = new Party(leo,tom) ^ scala> val jack = new Student("jack") jack: Student = Student@341889a1 scala> val party = new Party(leo,jack) party: Party[Student] = Party@3013e1e8

下边界

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
scala> class Father(val name: String) defined class Father scala> class Child(name: String) extends Father(name) defined class Child scala> def getIDCard[R >: Child](person: R){ | if(person.getClass == classOf[Child]) println("please tell us your father's name") | else if(person.getClass == classOf[Father]) println("please sign your name to get your child's lost id card") | else println("sorry, you are not allowed to get this id card") | } getIDCard: [R >: Child](person: R)Unit scala> val tom = new Worker("tom") tom: Worker = Worker@15914bb5 scala> val leo = new Child("leo") leo: Child = Child@fbe8fd3 scala> val jack = new Father("jack") jack: Father = Father@1c79d093 scala> getIDCard(jack) please sign your name to get your child's lost id card scala> getIDCard(tom) sorry, you are not allowed to get this id card scala> getIDCard(leo) please tell us your father's name

View Bounds

// View Bounds作为一种上下边界Bounds的加强版,支持可以对类型进行隐式转换,将指定的类型进行隐式转换后,再判断是否再边界指定的类型范围内

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
scala> class Person(val name: String) { | def sayHello = println("Hello, I'm "+name) | def makeFriends(p: Person): Unit ={ | sayHello | p.sayHello | } | } defined class Person scala> class Student(name: String) extends Person(name) defined class Student scala> class Dog(val name: String) { | def sayHello = println("wang,wang,wang, I'm "+name) | } defined class Dog scala> val leo = new Student("leo") leo: Student = Student@6f7e5e11 scala> val party = new Party(leo,doggy) // doggy还没有进行隐式转换 <console>:14: error: inferred type arguments [Object] do not conform to class Party's type parameter bounds [T <: Person] val party = new Party(leo,doggy) ^ <console>:14: error: type mismatch; found : Student required: T val party = new Party(leo,doggy) ^ <console>:14: error: type mismatch; found : Dog required: T val party = new Party(leo,doggy)

// 再scala中,如果要实例化一个泛型数组,就必须使用Manifest Context Bounds。也就是说,如果数组元素类型为T的话,需要为类或者函数定义[T: Manifest],这样才能实例化Array[T]这种泛型数组

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
scala> class Meat(val name: String) defined class Meat scala> class Vegetable(val name: String) defined class Vegetable scala> def packageFood[T: Manifest](food: T*)={ | val foodPackage = new Array[T](food.length) | for(i <- 0 until food.length) foodPackage(i) = food(i) | foodPackage | } packaggeFood: [T](food: T*)(implicit evidence$1: Manifest[T])Array[T] scala> val gongbaojiding = new Meat("gongBaoJiDing") gongbaojidi: Meat = Meat@5552f9e0 scala> val yuxiangrousi = new Meat("yuXiangRouSi") yuxiangrousi: Meat = Meat@7fad58f8 scala> val shousiyangpai = new Meat("shouSiYangPai") shousiyangpai: Meat = Meat@6831b1f6 scala> val meatPackage = packageFood(gongbaojiding,yuxiangrousi,shousi yangpai) meatPackage: Array[Meat] = Array(Meat@5552f9e0, Meat@7fad58f8, Meat@6831b1f6)

协变和逆变

// 在scala中,如果Professional是Master的子类,那么使用斜边和逆变,可以使Card[Professional]是Card[Master]的子类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
scala> class Master defined class Master scala> class Professional extends Master defined class Professional // 大师以及大师级别以下的名片都可以进入 scala> class Card[+T](val name: String) // +T 就是协变 defined class Card scala> def enterMeet(card: Card[Master]){ | println("welcome to have this meeting") | } scala> val leo = new Card[Professional]("leo") leo: Card[Professional] = Card@53a51411 scala> val jack = new Card[Master]("jack") jack: Card[Master] = Card@1e89b7d6 scala> enterMeet(leo) welcome to have this meeting scala> enterMeet(jack) welcome to have this meeting // 专家以及专家级别以上的名片都可以进入 scala> class Card[-T](val name: String) // -T 就是逆变 defined class Card scala> def enterMeet(card: Card[Professional]){ | println("welcome to have this meeting") | } scala> val leo = new Card[Professional]("leo") leo: Card[Professional] = Card@53a51411 scala> val jack = new Card[Master]("jack") jack: Card[Master] = Card@1e89b7d6 scala> enterMeet(leo) welcome to have this meeting scala> enterMeet(jack) welcome to have this meeting

隐式类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
object ImplicitClass { //定义一个隐式类 //隐式类只能定义在类,trait,object内部 implicit class IntWithTimes(x:Int){ def times[A](f: => A):Unit={ //递归方法需要指明其返回类型 def loop(current:Int):Unit={ if(current>0){ f loop(current-1) } } loop(x) } } //隐式类只能带一个非隐式参数 //implicit class Indexer[T](collection:Seq[T],index:Int) 这样不可以 implicit class Indexer[T](collection:Seq[T])(implicit index:Int) //这样可以 //在同一作用域,不能有方法、或者对象、或者成员、或者变量,与隐式类同名 } //引入隐式类 import ImplicitClass._ object ImplicitTest1 extends App{ 10 times println("success") }

隐式转换函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
object ImplicitDemo2 extends App{ var a:Int = 10 var b:Double = 100.99 b=100 b=a //自己定义一个隐式转换函数, 把Double转换成Int implicit def DoubleToInt(x:Double):Int = x toInt //此时可以编译通过,此处隐式函数不需要调用,会自动检查该作用域内是否有隐式函数 a=b }

隐式参数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
object ImplicitDemo3 extends App{ //一个特质,带有一个抽象方法 trait Adder[T]{ def add(x:T,y:T):T } //创建一个隐式对象 implicit val a = new Adder[Int] { override def add(x: Int, y: Int): Int = x+y } //定义一个带有隐式参数的方法 def addTest(x:Int,y:Int)(implicit adder:Adder[Int])={ adder.add(x,y) } println(addTest(1,2)) //等价于println(addTest(1,2)(a)) println(addTest(1,2)(a)) }

actor模型介绍

(1)是一个并行计算的模型。

并行和并发:

复制代码
1
2
3
并行,同一时间多个任务同时执行 并发,同一时间段多个任务同时执行

(2)一切皆actor

消息和邮箱

任务调度:

基于线程:
基于事件:

actor:
接收消息,放到自己的mailBox中
处理消息,可以创建新的actor,或者指定下一个消息的处理,或者给其他actor发送消息

最后

以上就是完美钥匙最近收集整理的关于Scala编程语言入门学习笔记的全部内容,更多相关Scala编程语言入门学习笔记内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部