我是靠谱客的博主 完美钥匙,最近开发中收集的这篇文章主要介绍Scala编程语言入门学习笔记,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

数据类型和操作符

数据类型

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

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的语句块

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推导式,构建集合

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。

带有参数列表的方法

scala> def addAndMultiply(x:Int)(y:Int)=x+y
addAndMultiply: (x: Int)(y: Int)Int
scala> addAndMultiply(2)(3)
res0: Int = 5

无参方法

scala> def printInfo = println("scala")
printInfo: Unit
scala> printInfo
scala
scala> def printInfo1() = println("scala")
printInfo1: ()Unit
scala> printInfo1()
scala
scala> printInfo1
scala

带有默认参数的方法

可变长参数方法

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)

使用序列调用变长参数

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

函数

无参函数

scala> val fun=() => println("hello")
fun: () => Unit = $$Lambda$1209/1515342361@60e9bda0
scala> fun
res12: () => Unit = $$Lambda$1209/1515342361@60e9bda0
scala> fun()
//加上()才是无参函数的调用
hello

多参函数

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)可以把函数作为参数传递给一个方法

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.把一个方法作为参数传递给其他的方法或者函数

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.使用 方法名 _ 把一个方法显示的转换为一个函数

scala> m2 _
res20: (Int, Int) => Int = $$Lambda$1240/1778157082@3646f314

集合

什么是集合?

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

(1)是一个容器

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

(3)一般存放多个对象

集合

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

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

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

定长数组

数组的定义

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

数组的访问

scala> arr(0)
res25: Int = 1

数组的常用方法

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和函数式编程转换数组

// 对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)

变长数组

变长数组的创建

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()

数组的操作

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)

遍历数组

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+" ")

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

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)

数组变换

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)

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

// 构建数组
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:但是可以模拟修改或删除等

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中每个元素都加上指定前缀,并打印

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

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

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:

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:

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的基本操作:

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)

其他操作:

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

// 遍历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排序

// 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)

元组

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

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)

操作元组

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

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

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

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,则保留该元素,否则过滤掉该元素

scala> list1.filter(e=>e%2==0)
res139: List[Int] = List(2, 4, 6)

3.flatten

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

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

scala> list1.forall(e=>e>0)
res146: Boolean = true
scala> list1.foreach(println)
2
3
4
6
7

6.foldLeft,foldRight,reduceLeft,reduceRight

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 对元素进行两两相比,进行排序

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

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

// 使用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

类和属性

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)
}
}
// 调用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

内部类

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

构造函数

//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
}
}
// 辅助构造函数可以有多个,叫重载
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
//类自带有无参的构造函数
//主构造函数会执行类中定义的所有语句
//构造函数分为主构造函数和辅助构造函数
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了

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
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
}
}
//伴生类
class AccountInfo {
//
var id = 0
var id = AccountInfo.newUniqueNumber
}
//伴生对象和类在同一个文件中,且同名
//类的伴生对象,伴生对象和类可以互相访问彼此的私有属性,或者方法
object AccountInfo{
private var lastNumber = 0
private def newUniqueNumber: Int= {
lastNumber += 1
lastNumber
}
}
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.
//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)
}
// 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
// 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方法

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")
}
}
}

继承

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

抽象类

//定义抽象类,使用关键字: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
}
// 特质还是抽象类?
// 优先使用特质,因为一个类只能继承一个超类,但是可以混入多个特质;
//如果需要构建函数参数,只能只用抽象类,因为特质无法定义带参数的构造函数

特质

//定义一个带有抽象方法的特质,关键字: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

// 有时可以在创建类的对象时,指定该对象混入某个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调用链

// 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中覆盖抽象方法

// 在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的具体方法和抽象方法

// 在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的构造机制

// 在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的初始化

// 在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

// 将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.
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

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)
}
}

样例类

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 值 => 代码

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 变量:类型 => 代码

// 类型匹配
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!
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特有的::操作符

// 用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

偏函数

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))
}
}

密封类

用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类型

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)
}
}

字符串插值

插值器 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)
}
}

文件操作

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()
}

正则表达式

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)
}

高阶函数

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

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)
}

高阶函数的类型推断

// 高阶函数可以自动推断出参数类型,而不需要写明类型;而且对于只有一个参数的函数,还可以省去其小括号;如果仅有的一个参数在右侧的函数体内只使用一次,则还可以将接收参数省略,并且将参数用_来替代
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

闭包

什么是闭包?

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

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)
}

柯里化

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

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)(_+_))
}

方法的嵌套和多态

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

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

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))
}

隐式转换

//隐式引用,这三个包都是很默认导入的
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的上下边界特性允许泛型类型必须是某个类的子类,或者必须是某个类的父类

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

下边界

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的加强版,支持可以对类型进行隐式转换,将指定的类型进行隐式转换后,再判断是否再边界指定的类型范围内

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]这种泛型数组

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]的子类

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

隐式类

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")
}

隐式转换函数

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
}

隐式参数

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)是一个并行计算的模型。

并行和并发:

并行,同一时间多个任务同时执行
并发,同一时间段多个任务同时执行

(2)一切皆actor

消息和邮箱

任务调度:

基于线程:
基于事件:

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

最后

以上就是完美钥匙为你收集整理的Scala编程语言入门学习笔记的全部内容,希望文章能够帮你解决Scala编程语言入门学习笔记所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部