1.scala环境搭建
网址:https://www.scala-lang.org/
-
安装步骤
-
Scala需要使用JVM来运行字节码文件,所以需要确保安装了jdk1.8
-
下载对应的scala安装文件scala-2.12.15.msi
-
解压安装包到C:\Program Files (x86)
-
配置scala环境变量
-
-
安装完成后与
JAVA_HOME
类似的为Scala配置SCALA_HOME
,并将%SCALA_HOME%\bin
添加到Path
-
在cmd尝试运行scala,安装正确会进入如下界面
2.scala特性:
-
面向对象特性:每个值都是对象
-
函数式编程
-
静态类型
-
扩展性
-
并发性
3.scala和java的关系
Scala与Java和众多JVM语言的共通之处在于,使用专门的编译器(Compiler)将源代码编译成字节码(Bytecode)文件,并最终使用JVM(Java Virtual Machine)执行程序,所以具有和Java相同的优良移植性。
4.第一个scala程序
4.1为IDEA下载Scala插件
4.2 创建空的maven工程
4.3创建Scala源代码目录
4.4 标记为源码目录
4.5添加ScalaSDK全局库
4.6创建HelloWorld单例对象
4.7 编写HelloWrold
1 /* 2 object:关键字,声明一个单例对象 3 4 */ 5 object Test { 6 /* 7 main方法:从外部可以直接调用执行的方法 8 def 方法名称(参数名称 : 参数类型):返回值类型 = {方法体} 9 */ 10 def main(args: Array[String]): Unit = { 11 print("helloWord") 12 println(3) 13 //var\val 变量名 : 数据类型 [= 变量值] 14 var aa=3; 15 val bb="qqqq" 16 var f:Int=3 17 println(aa) 18 println(bb) 19 } 20 }
5.基本语法
-
区分大小写
-
类名 - 对于所有的类名的第一个字母要大写。 如果需要使用几个单词来构成一个类的名称,每个单词的第一个字母要大写。
-
方法名称 - 所有的方法名称的第一个字母用小写。
注释:
①单行注释//
②多行注释/* */
③文档注释/** */
变量和常量
①基本语法
var 变量名 [:变量类型] = 初始值 var i:Int =10
val 常量名 [:常量类型] = 初始值 val j:Int =20
能使用常量的地方不用变量
-
声明变量时,类型可以省略,编译器自动推导
1 var a1=10 2 val b1=20
-
类型确定后,就不能修改,说明scala是强数据类型语言
1 var a2=12 //a2为int类型 2 a2="hello" //报错
-
变量声明时,必须有初始值
-
在声明定义一个变量时,可以使用var或val修饰,var修饰的变量可改变,val修饰的变量不可改
字符串拼接
-
字符串,通过+号连接
1 val name: String = "aa" 2 val age: Int = 18; 3 println(age + "岁的" + name + "在学习") 4 //*用于将一个字符串重复多次并拼接 5 println(name*3)//aaaaaa
-
printf用法:字符串,通过%传值
printf("%d岁的%s在学习",age,name)
-
字符串模板(插值字符串):通过$获取变量值
1 println(s"${age}岁的${name}在学习")
-
格式化模板字符串
1 //the num is 2.33 2 println(f"the num is ${num}%2.2f")
-
三引号表示字符串,保持多行字符串原格式输出
1 /* 2 select * 3 from 4 Test 5 where 6 name=aa 7 and 8 age>18 9 */ 10 val sql = 11 s""" 12 |select * 13 |from 14 | Test 15 | where 16 | name=${name} 17 | and 18 | age>${age} 19 |""".stripMargin 20 println(sql)
键盘输入
-
输入信息
1 import scala.io.StdIn 2 3 object Test1 { 4 def main(args: Array[String]): Unit = { 5 //输入信息 6 println("请输入你的姓名") 7 val name:String=StdIn.readLine() 8 println("请输入你的年龄") 9 val age:Int=StdIn.readInt() 10 //从控制台打印输出 11 println(s"${age}岁的${name}") 12 } 13 }
-
从文件中读取数据
1 import scala.io.Source 2 3 object Test2 { 4 def main(args: Array[String]): Unit = { 5 //从文件中读取数据 6 Source.fromFile("path").foreach(print) 7 } 8 }
-
将数据写入文件
1 val writer=new PrintWriter(new File("path")) 2 writer.write("hello") 3 writer.close()
6.数据类型
-
与Java类似的Scala有Byte、Short、Int、Long、Float、Double、Char、Boolean,8种常用值类型。
-
与Java不同的是,Scala中 真·万物皆对象,所以没有所谓包装类,上面这八个值类型就是对象。
①整数类型
1 //1.整数类型 2 val a1:Byte=127 3 val a2:Byte=-128 4 5 val a3=12//整数默认类型为Int 6 val a4=1823737493939L//长整型数值定义 7 8 val b1:Byte=10 9 val b2:Byte=(b1+20).toByte//强制类型转换
②浮点类型
1 val f1:Float=1.23f 2 val d1:Double=23.333
③字符类型
1 val c1:Char='a'//a 2 val c2:Char='9'//9
④控制字符
1 val c3:Char='\t'//制表符 2 val c4:Char='\n'//换行符
⑤转义字符
1 val c5='\\'//表示\自身 2 val c6='\“'//表示”
⑥布尔类型
布尔型字面量有 true 和 false
⑦空类型
-
Nothing和Null
-
Nothing是所有类型的子类型,也称为底部类型。没有一个值是Nothing类型的。它的用途之一是给出非正常终止的信号,如抛出异常、程序退出或者一个无限循环(可以理解为它是一个不对值进行定义的表达式的类型,或者是一个不能正常返回的方法)。
-
Null是所有引用类型的子类型(即AnyRef的任意子类型)。它有一个单例值由关键字null所定义。Null主要是使得Scala满足和其他JVM语言的互操作性,但是几乎不应该在Scala代码中使用。我们将在后面的章节中介绍null的替代方案。
1 object Test3 { 2 def main(args: Array[String]): Unit = { 3 //1.空值Unit 4 def m1():Unit={ 5 println("m1被调用")//m1被调用 6 } 7 val a=m1() 8 println(a)//() 9 10 //2.空引用Null 11 var student:Student=new Student("alice",23) 12 student=null 13 println(student)//null 14 15 //3.Nothing 16 def m2(n:Int):Int={ 17 if(n==0) 18 throw new NullPointerException//抛出异常 19 else 20 return n 21 } 22 val b=m2(2) 23 println(b)//2 24 } 25 }
自动类型转换
-
值类型可以按照下面的方向进行转换:
-
自动提升原则:有多种类型的数据混合运算时,系统优先自动将所有数据转换成精度大的数据类型,然后再进行计算
1 val a1:Byte=10; 2 val b1:Long=122333333L 3 val result:Long=a1+b1 4 val result1:Int=(a1+b1).toInt//强制转换
-
把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之会进行自动类型转换
1 val a2:Byte=10 2 val b2:Int=a2 3 //val c2:Byte=b2//报错
-
(byte、short)和char之间不能进行类型转换
1 val a3:Byte=10 2 val c3:Char='b' 3 val c4:Byte=c3 4 println(c4)//运行报错
-
byte、short、char三者可以计算时,要先转换成int类型
1 val a4:Byte=10; 2 val b4:Short=12 3 val c5:Char='c' 4 //val result2:Short=a4+b4//报错 5 val result2:Int=a4+b4 6 println(result2)//22
强制类型转换
-
将数据从高精度转换为低精度,就需要进行强制类型转换,但数据会丢失精度
1 val n1:Int=2.5.toInt 2 println(n1)//2 3 val n1:Int=-2.9.toInt 4 println(n1)//-2
-
强转符号只针对最近的操作符有效,往往会使用小括号提升优先级
1 val n2:Int=(2.6+3.7).toInt 2 println(n2)//6
数值类型和String类型的转换
-
数值转String
1 val n3:Int=27 2 val s:String=n3+" " 3 println(s)
-
String转数值
1 val m:Int="12".toInt 2 println(m)
继承层次
-
与Java不同的是Scala的类型转换通过
asInstanceOf[目标类型]
进行类型强转
1 package com.bd2108.jwl.scala 2 3 object scala08_继承层次 { 4 def main(args: Array[String]): Unit = { 5 def f1()={ 6 throw new NullPointerException 7 } 8 //scala中判断类型 9 val bool = "aa".isInstanceOf[String] 10 11 //scala中类型强转 12 val i = 11.asInstanceOf[Long] 13 } 14 }
7.运算符
-
+-*/%可以完成和 Java 中相同的工作,但是有一点区别,他们都是方法。你几乎可以用任何符号来为方法命名。
算术运算符+、-、*、/、%
1 object Test { 2 def main(args: Array[String]) { 3 var a = 10; 4 var b = 20; 5 var c = 25; 6 var d = 25; 7 println("a + b = " + (a + b) );//30 8 println("a - b = " + (a - b) );//-10 9 println("a * b = " + (a * b) );//200 10 println("b / a = " + (b / a) );//2 11 println("b % a = " + (b % a) );//0 12 println("c % a = " + (c % a) );//5 13 } 14 }
关系运算符==、!=、>、<、>=、<=
1 object Test { 2 def main(args: Array[String]) { 3 var a = 10; 4 var b = 20; 5 println("a == b = " + (a == b) );//false 6 println("a != b = " + (a != b) );//true 7 println("a > b = " + (a > b) );//false 8 println("a < b = " + (a < b) );//true 9 println("b >= a = " + (b >= a) );//true 10 println("b <= a = " + (b <= a) );//false 11 } 12 }
逻辑运算符&&、||、!
1 object Test { 2 def main(args: Array[String]) { 3 var a = true; 4 var b = false; 5 6 println("a && b = " + (a&&b) );//false 7 println("a || b = " + (a||b) );//true 8 println("!(a && b) = " + !(a && b) );//true 9 } 10 }
位运算符~、&、|、^、<<、>>、>>>
1 object Test { 2 def main(args: Array[String]) { 3 var a = 60; /* 60 = 0011 1100 */ 4 var b = 13; /* 13 = 0000 1101 */ 5 var c = 0; 6 7 c = a & b; /* 12 = 0000 1100 */ 8 println("a & b = " + c );//12 9 10 c = a | b; /* 61 = 0011 1101 */ 11 println("a | b = " + c );//61 12 13 c = a ^ b; /* 49 = 0011 0001 */ 14 println("a ^ b = " + c );//49 15 16 c = ~a; /* -61 = 1100 0011 */ 17 println("~a = " + c );//-61 18 19 c = a << 2; /* 240 = 1111 0000 */ 20 println("a << 2 = " + c );//240 21 22 c = a >> 2; /* 15 = 1111 */ 23 println("a >> 2 = " + c );//15 24 25 c = a >>> 2; /* 15 = 0000 1111 */ 26 println("a >>> 2 = " + c );//15 27 } 28 }
赋值运算符=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=
1 object Test { 2 def main(args: Array[String]) { 3 var a = 10; 4 var b = 20; 5 var c = 0; 6 7 c = a + b; 8 println("c = a + b = " + c );//30 9 10 c += a ; 11 println("c += a = " + c );//40 12 13 c -= a ; 14 println("c -= a = " + c );//30 15 16 c *= a ; 17 println("c *= a = " + c );//300 18 19 a = 10; 20 c = 15; 21 c /= a ; 22 println("c /= a = " + c );//1 23 24 a = 10; 25 c = 15; 26 c %= a ; 27 println("c %= a = " + c );//5 28 29 c <<= 2 ; 30 println("c <<= 2 = " + c );//20 31 32 c >>= 2 ; 33 println("c >>= 2 = " + c );//5 34 35 c >>= a ; 36 println("c >>= a = " + c );//0 37 38 c &= a ; 39 println("c &= 2 = " + c );//0 40 41 c ^= a ; 42 println("c ^= a = " + c );//10 43 44 c |= a ; 45 println("c |= a = " + c );//10 46 } 47 }
运算符重载
-
中缀表达式
-
scala中可以将对象.方法(参数)简写成对象 方法 参数
1 package com.bd2108.jwl.scala 2 3 object scala09_运算符重载 { 4 def main(args: Array[String]): Unit = { 5 ==|==>() 6 def ==|==>():Unit={ 7 // println("11111") 8 } 9 10 //scala中万物皆对象 11 1+1 12 //本质上也是对象调用方法:对象.方法名(参数) 13 1.+(1) 14 //scala中允许使用中缀表达式简化以上操作 15 //简化前:对象.方法名(参数) 16 //简化后:对象 方法名 参数 17 val str = "a,b,c".split(",") 18 val ss="a,b,c" split "," 19 20 //中缀表达式的变形 21 //对象.方法 22 //对象 方法 23 val trim = " qqq ".trim//返回无空格的字符串 24 println(trim) 25 }
8.流程控制
1.if-else表达式
-
Scala中提供与大部分编程语言中类似的if-else选择结构语句
-
语法:
if(expr) { expr为true时执行的语句 } else { expr为false时执行的语句 }
1 package com.bd2108.jwl.scala 2 3 object scala12_if_else { 4 def main(args: Array[String]): Unit = { 5 //缺省的else分支返回值的类型是空代码的类型Unit,在处理返回值类型时需要注意 6 val a=10 7 val b=12 8 val c= if (a>b){ 9 a 10 }else{ } 11 println(c) 12 13 if (a>b) a else b 14 } 15 }
2.while和do-while表达式
-
while和do-while表达式固定返回Unit
-
while语法:
while(expr){ expr为true时反复执行的语句 }
1 var first = 0 2 var second = 1 3 var fibonacci = 0 4 while (fibonacci < 50) { 5 println(fibonacci) 6 first = second 7 second = fibonacci 8 fibonacci = first + second 9 }
- do-while语法:
do{ expr为true时反复执行的语句 } while (expr)
1 var i = 53672 2 var sum = 0 3 do { 4 sum += i % 10 5 i /= 10 6 } while (i > 0) 7 println(sum) // 23
-
需要注意的是Scala中没有提供break和continue的关键字
-
如果要实现类似的功能,可以使用控制循环条件、函数封装+return或BreaksAPI
1 var i=1 2 Breaks.breakable{ 3 while (i<11){ 4 println(i) 5 if (i==5) Breaks.break() 6 i+=1 7 } 8 }
3.for推导式
-
语法:for (enumerators) { 循环体 }
-
枚举器(enumerators):指的是一组以分号分割的枚举器,枚举器可以由一个产生新变量的生成器(generator)以及一个守卫(guard)组成。
-
1 //for中可以添加多个枚举器,类似java的嵌套循环 2 for (i <-1 to 9;j <-1 to i){ 3 print(s"${j}*${i}=${i*j}\t") 4 if (i==j) println() 5 }
-
- 生成器(generator):指的是一个形如
变量名 <- 集合
的表达式,生成器会在每次迭代时从<-
右边的集合中取一个元素赋值给<-
左边的变量。
- 生成器(generator):指的是一个形如
1 //for(元素 <- 集合){ 2 // } 3 val str = Array("a", "b", "c") 4 for (arr<-str){ 5 println(arr) 6 }
-
- 守卫(guard):指的是一个形如
if expr
的表达式,expr
为true时执行循环体,为false时类似Java中的continue操作,跳过当此继续下一次循环。
- 守卫(guard):指的是一个形如
1 //for中可以添加守卫 2 for(i <-1 to 10 if i%2==0){ 3 println(i) 4 }
1 val inclusive = 1.to(100) 2 println(inclusive)//Range 1 to 100
-
scala的for推导式
1 //Int.to(范围的重点,自增的步长) 2 for (i<-2.to(100,2)){ 3 println(i)//打印100以内的偶数 4 } 5 6 //打印一个集合,将集合中后一位元素与前一位元素拼接,形成一个新的元素 7 val arr=Array("a","b","c") 8 for (i<-arr.indices){ 9 if (i+1<arr.length){ 10 println(arr(i)=arr(i)+arr(i+1)) 11 } 12 } 13 println(arr.toList)//集合List(ab, bc, c) 14 println(arr)//地址 15 }
-
yield收集:加在for推导式末尾,可以将满足条件的元素收集到新的集合并返回
1 //yield收集 2 val ints = Array(12, 34, 56, 231, 456, 789) 3 //声明集合用于存储结果res 4 //遍历原有集合 5 //判断满足添加,则加入res 6 //yield加在for推导式末尾,可以将满足条件的元素收集到新的集合并返回 7 val res=for (x<-ints if x %2!=0) yield x 8 println(util.Arrays.toString(res))
9.表达式
-
表达式是可以计算的语句
-
scala表达式可以省略分号;
-
scala表达式的值可以不被变量接收
1 package com.bd2108.jwl.scala 2 3 object scala01_表达式 { 4 def main(args: Array[String]): Unit = { 5 //1.scala表达式中可以省略分号; 6 3+2 7 //2.scala表达式的值可以不被变量接收 8 2 9 "aqaa" 10 } 11 }
-
值类型
-
与java类似,有Byte、Short、Int、Long、Float、Double、Char、Boolean8中常用值类型
-
与java不同的是scala中万物皆对象,所以没有包装类,值类型就是对象
-
10.代码块
-
可以使用{ }将0行或若干行语句包裹起来形成一个整体,这个整体被称作代码块
-
代码块的值是块中最后一行表达式的值
1 package com.bd2108.jwl.scala 2 3 object scala02_代码块 { 4 def main(args: Array[String]): Unit = { 5 //1.可以使用{}将0行或若干行语句包裹起来形成一个整体,这个整体被称作代码块 6 //2.代码块的值是块中最后一行表达式的值 7 val res={ 8 1 9 2 10 3 11 } 12 println(res)//3 13 } 14 }
11.方法
-
方法由def关键字定义,def后面跟着一个名字、参数列表、返回类型和方法体
-
语法:def 方法名 (参数名:参数类型):返回值类型={方法体}
1 def add(x: Int, y: Int): Int ={ 2 x + y 3 } 4 println(add(1, 2)) // 3
-
与java类似,scala的方法就是将代码块加上 方法名 参数 返回值
-
scala返回值类型默认为Unit
1 //1.返回值 2 //1.1 scala返回值类型默认为Unit 3 def m1():Unit={ } 4 //也可以写成 5 def m2(){ }
- 如果需要有返回值,就要在参数列表和方法体之间加上=,scala会自动根据方法体的最后一行语句推断返回值类型
1 //1.2 如果需要有返回值,就要在参数列表和方法体之间加上= 2 //scala会自动根据方法体的最后一行语句推断返回值类型 3 def m3(a:Int)={ 4 a+1 5 "sss" 6 } 7 println(m3(2))//sss,代码块内最后一行语句是代码块的值
-
scala允许在方法声明时为参数添加默认值
-
scala方法调用时可以使用匿名参数的方式
1 package com.bd2108.jwl.scala 2 3 object scala03_方法 { 4 def main(args: Array[String]): Unit = { 5 //2.参数 6 //2.1 scala允许在方法声明时为参数添加默认值 7 def sum(a:Int=1,b:Int=2)={ 8 a+b 9 } 10 sum(4,8) 11 sum(5) 12 sum() 13 println(sum())//3 14 15 //2.2 scala方法调用时可以使用匿名参数的方式 16 sum(b=12,a=30) 17 }
- scala中也可以支持可变长度参数,与java类似 一个方法只能包含一个可变长度参数,可变长度参数必须放在参数列表末尾
1 //2.3 scala中也可以支持可变长度参数 2 //与java类似 一个方法只能包含一个可变长度参数,可变长度参数必须放在参数列表末尾 3 def sum1(x:Int*)={ 4 println(x.sum)//15 5 } 6 sum1(1,2,3,4,5)
- scala方法的参数列表为空时,可以省略()
1 //2.4 scala方法的参数列表为空时,可以省略() 2 f1() 3 //f1,省略()的写法也是正确的,但是不提倡这么用 4 f2 5 } 6 def f1()=123//方法,参数列表为空 7 val f2=456//常量
12.函数
-
函数是带有参数的表达式
-
语法:(参数名:参数类型)=>{函数体}
-
scala中main方法使用def声明,除了书写位置,其他语法和方法与java类似
-
method 方法,声明在类中(直接属于类的代码块),用于描述类的行为
-
function 函数,声明在任意位置(可以属于类,可以属于方法,可以属于其它函数)用于描述参数与 返回值之间的映射关系
-
scala中也提供了使用匿名函数的方式声明函数,(参数)=>{函数体}
-
匿名函数f作为其他函数的参数时,参数类型可以省略不写
-
如果是二元匿名函数,并且参数的声明顺序和使用顺序一致,并且都只用了一次,可以使用_代替
-
1 package com.bd2108.jwl.scala 2 3 object scala04_函数 { 4 // java中的main方法: void main(String[] args) { } 5 // scala中的main方法: main(args: Array[String]): Unit = { } 6 //使用def声明的函数,除了书写位置,其他语法和方法与java类似 7 def main(args: Array[String]): Unit = { 8 9 //scala中也提供了使用匿名函数的方式声明函数 10 //(参数)=>{函数体} 11 val f1:Int=>Int=(b:Int)=>{ 12 b+1 13 } 14 15 //一元函数 16 val i:Int=2 17 val s:String="SSS" 18 val res=f1(2) 19 println(res)//3 20 21 //实现加减乘除运算 22 val calc=(x:Int,y:Int,op:(Int,Int)=>Int)=>{ 23 op(x,y) 24 } 25 def calc1(x:Int,y:Int,op:(Int,Int)=>Int):Int={ 26 op(x,y) 27 } 28 val res1=calc1(1,2,(a:Int,b:Int)=>a+b) 29 println(res1)//3 30 31 //匿名函数calc1作为其他函数的参数时,参数类型可以省略不写 32 val res2=calc1(1,2,(a,b)=>a+b) 33 34 //如果是二元匿名函数,并且参数的声明顺序和使用顺序一致,并且都只用了一次,可以使用_代替 35 calc1(1,2,_ + _) 36 calc1(1,2,(x,y)=>x*x+y*y*y) 37 38 39 val array = new Array[String](3) 40 //foreach[U](f:String=>U) 41 array.foreach(x=>println(x))//null null null 42 46 } 47 }
-
我们可以定义一个匿名函数(即没有名字),来返回一个给定整数加一的结果。
(x: Int) => x + 1
-
我们也可以将函数赋值给一个变量,相当于给匿名函数起一个名字。
-
访问这个变量时,就是在调用这个函数。
-
这时这个变量的类型就是一个函数,在函数式编程范式中,函数是一等公民,与Int、String等对象一样,可以作为一个变量的类型。
1 val addOne = (x: Int) => x + 1 2 println(addOne(1)) // 2
-
函数可以带有多个参数
1 val add = (x: Int, y: Int) => x + y 2 println(add(1, 2)) // 3
-
函数可以不带参数
1 val getTheNum = () => 23 2 println(getTheNum()) // 23
13.类
-
scala中类的声明语法
1 //class 类名{ 2 //构造器 3 //成员属性 4 //成员方法 5 //}
-
scala中class的【主构造器】写在类的声明位置
-
【主构造器】的参数列表中,如果使用var/val修饰的参数会直接作为类的成员属性
-
成员变量如果是常量 必须设置初始值
-
成员变量如果是变量 不需要设值初始值,可以使用_代替
-
@BeanProperty:自动根据权限生成符合java bean规范的访问接口,java代码通过get、set方法获得类的属性
-
可以使用private将成员设值为类内私有访问,scala也支持为私有属性提供例外
-
scala由于只有一个主构造器,所以通过辅助构造器的语法 扩展构造器重载
-
辅助构造器使用def声明,方法名为this,必须直接或间接调用主构造器
1 package com.bd2108.jwl.scala 2 import scala.beans.BeanProperty 3 4 object scala05_类 { 5 def main(args: Array[String]): Unit = { 6 //class 类 object 对象 7 //类 是一系列具有相同属性和方法的实体的抽象(模板) 8 //对象 是使用new关键字和class构造器创建的一个类的实例 9 val stu = new Student("1001") 10 stu.id="aaa" 11 12 val t = new Teacher("admin",12,'1') 13 val t1 = new Teacher("aa",'2') 14 val t2 = new Teacher(11,'1') 15 val t3 = new Teacher("ss") 16 } 17 18 } 19 20 //scala中class的【主构造器】写在类的声明位置 21 //【主构造器】的参数列表中,如果使用var/val修饰的参数会直接作为类的成员属性 22 class Student(var id:String){ 23 //成员变量如果是常量 必须设置初始值 24 @BeanProperty 25 //自动根据权限生成符合java bean规范的访问接口,java代码通过get、set方法获得类的属性 26 val name:String="admin" 27 //成员变量如果是变量 不需要设值初始值,可以使用_代替 28 @BeanProperty 29 var age:Int=_ 30 //可以使用private将成员设值为类内私有访问 31 //scala也支持为私有属性提供例外 32 private var gender:Char='2' 33 //设值包级别的外部访问 34 private[bd2108] var weight:Int=_ 35 36 def eat()={ 37 } 38 private def play()={ 39 } 40 } 41 42 //scala由于只有一个主构造器,所以通过辅助构造器的语法 扩展构造器重载 43 class Teacher(var name:String,var age:Int,val gender:Char){ 44 //使用def声明 方法名为this 45 //辅助构造器 必须直接或间接调用主构造器 46 def this(name:String,gender:Char){ 47 this(name,0,gender) 48 } 49 def this(age:Int,gender:Char){ 50 this("0",age,gender) 51 } 52 def this(name:String){ 53 this(name,0,'0') 54 } 55 }
java调用scala
1 package com.bd2108.jwl.scala; 2 3 public class Test { 4 public static void main(String[] args) { 5 Student stu=new Student("1001"); 6 System.out.println(stu.getName()); 7 stu.setAge(12); 8 System.out.println(stu.getAge()); 9 } 10 }
14.对象
-
scala为了方便开发者声明单例对象,提供了object关键字,本质上scala会编译出一个匿名类作为模板,并未这个模板创建一个单例对象
1 package com.bd2108.jwl.scala 2 3 //如果一个class和一个object声明在同一个scala源代码文件中,class和object的名字完全一致 4 //此时,我们将class称为object的伴生类,object称为class的伴生对象 5 class Person { 6 var name:String=_ 7 var age:Int=_ 8 } 9 object Person{ 10 //object中可以使用apply声明一些特殊方法 11 //当调用这些方法时,可以直接使用 对象名(参数) 12 def apply(name: String): Person = { 13 val p = new Person 14 p.name=name 15 p 16 } 17 18 def apply(name: String, age: Int): Person = { 19 val p=new Person 20 p.name=name 21 p.age=age 22 p 23 } 24 25 def eat():Unit={ 26 } 27 }
-
案例类,用case修饰
1 package com.bd2108.jwl.scala 2 3 //case修饰的class称之为案例类 4 //案例类可以自动生成伴生对象和全参的apply用于类的实例化 5 case class Person1(var name:String,var age:Int)
-
可以通过引用类的名字来访问一个对象
1 package com.bd2108.jwl.scala 2 3 object scala06_对象 { 4 def main(args: Array[String]): Unit = { 5 //希望可以直接通过"类名"调用 6 //并且希望JVM中的全局变量唯一 7 var name="aaa" 8 9 //scala为了方便开发者声明单例对象,提供了object关键字 10 //本质上scala会编译出一个匿名类作为模板,并未这个模板创建一个单例对象 11 val p = Person("admin") 12 val p1 = Person("admin", 12) 13 val P2 = Person1("ROSE", 10) 14 } 15 }
15.特质
-
特质是一个使用
trait
关键字声明的包含某些字段和方法的结构,类似于Java中的接口(interface)。特质允许多继承。
1 trait Person { 2 def eat(food: String): Unit 3 }
-
特质也可以有默认的实现。
1 trait Person { 2 def eat(food: String): Unit = { 3 println("用碗吃" + food) 4 } 5 }
-
可以使用extends关键字来继承特质,使用override关键字来覆盖默认的实现。
1 class NormalPerson extends Person 2 3 class GanfanPerson extends Person { 4 override def eat(food: String): Unit = { 5 println("用盆吃" + food) 6 } 7 }
1 val normalPerson = new NormalPerson 2 normalPerson.eat("臊子面") // 用碗吃臊子面 3 val ganfanPerson = new GanfanPerson 4 ganfanPerson.eat("臊子面") // 用盆吃臊子面
-
scala为了提高程序的灵活性,允许在创建对象时,临时进行特质的混入
-
混入本质上是创建了一个匿名子类,同时继承了当前类和混入的所有特质,并使用匿名子类创建实例
1 package com.bd2108.jwl.scala 2 3 object scala07_特质 { 4 def main(args: Array[String]): Unit = { 5 //类似于java代码中的interface接口 6 //scala也提供了trait 7 //scala为了提高程序的灵活性,允许在创建对象时,临时进行特质的混入 8 //混入本质上是创建了一个匿名子类,同时继承了当前类和混入的所有特质,并使用匿名子类创建实例 9 val student = new Student with Gamer with Coder 10 student.study() 11 student.play() 12 student.coding() 13 //接口的作用:为了解决类的多继承中,多个父类拥有相同的实现方法,导致子类调用时,会出现二义性问题 14 //接口中默认所有方法都声明成抽象方法,即使多个父接口中有相同的方法,调用时也需要重写并调用实现方法 15 //无法直接调用父接口中的抽象方法,不存在二义性 16 val x = new X 17 x.study() 18 x.play() 19 x.coding() 20 } 21 } 22 class X extends Student with Gamer with Coder 23 //class Student extends Gamer with Coder{ 24 class Student{ 25 def study():Unit={ 26 println("学习") 27 } 28 } 29 trait Gamer{ 30 def play():Unit={ 31 println("游戏") 32 } 33 } 34 trait Coder{ 35 def coding():Unit={ 36 println("编程") 37 } 38 }
16.隐式操作
-
apply和update方法
-
定义在object中名为apply的一系列方法在调用时可以直接使用
对象名(参数)
的形式完成调用 -
Scala中不可变数组被定义为Array对象,更新数组中的元素时,可以使用update方法,或其隐式形式
-
数组对象(索引)=值等价于 数组对象.update(索引,值)
1 //数组: 2 //java中写法:int[] arr=new Array[Int](3); 3 //arr[0]=12; 4 //int i=arr[0]; 5 val arr = new Array[Int](5) 6 7 //scala虽然提供了完全面向对象的语法操作,但是为了简化或者适应其他语言规范,同步提供了一些【隐式操作】 8 //数组的取值 9 //val i = arr.apply(0) 10 val i = arr(0) 11 arr.update(0,22) 12 arr(0)=22 13 }
17.Option类型
-
Scala为单个值提供了对象的包装器,表示那种可能存在也可能不存在的值。
-
他只有两个有效的子类对象,一个是Some,表示某个值,另外一个是None,表示为空,通过Option的使用,避免了使用null、空字符串等方式来表示缺少某个值的做法。
1 package com.bd2108.jwl.scala 2 3 import scala.collection.mutable 4 5 object scala10_Option { 6 def main(args: Array[String]): Unit = { 7 //scala中设计了一个Option用来返回可能为空的返回值 8 //Option有两个子类 9 //None 当值为空时返回None实例 10 //Some 当有值时,将返回值封装在Some中并返回Some对象 11 val map = new mutable.HashMap[String, String]() 12 /* val key = map.get("k") 13 println(key.get)*/ 14 val maybeString:Option[String] = map.get("k") 15 if (maybeString.isInstanceOf[Some[String]]){ 16 println(maybeString.get) 17 }else{ 18 println("值不存在") 19 } 20 val str:String = map.getOrElse("k1", "v1") 21 println(str) 22 } 23 }
18.异常
-
与Java类似的,Scala提供异常处理机制用于终止错误的程序运行和错误提示。
-
但是Scala没有“受检”异常,我们不需要声明说函数或者方法可能会抛出某种异常。受检异常在编译器被检查,Java必须声明方法所会抛出的异常类型
1 package com.bd2108.jwl.scala 2 import java.io.{File, FileInputStream} 3 4 object scala11_异常 { 5 def main(args: Array[String]): Unit = { 6 //scala没有提供受检异常 7 val file = new File("") 8 var stream:FileInputStream =null 9 try{ 10 stream = new FileInputStream(file) 11 }catch { 12 case e:Exception=>println("读取失败") 13 }finally { 14 try { 15 stream.close() 16 }catch { 17 case e:Exception=>println("关闭资源失败") 18 } 19 } 20 } 21 }
19.数据结构与集合
1.数据结构
-
数据结构讨论的是在
抽象层面
上一组具有一定关系
的数据元素的存储
及处理
。
-
数据元素之间逻辑关系的分类,每种逻辑关系对应的操作。
-
每种逻辑关系在计算机内部的存储模式。
-
对应于每种存储模式和操作的实现过程。
2.逻辑结构
描述数据元素之间的逻辑关系
线性结构:一对一关系
-
同一数据集合中的元素排成一个有序的序列。
-
序列的第一个元素称
起始结点(Initial Node)
,最后一个元素称终端结点(Terminal Node)
。 -
任意一对相邻元素,前者是后者的
直接前驱(Directly Predecessor)
,后者是前者的直接后继(Directly Successor)
-
起始结点只有直接后继没有直接前驱,终端结点只有直接前驱没有直接后继。
-
除起始节点和终端节点外,每个元素都只有一个直接前驱和一个直接后继。
树状结构:一对多关系
-
同一集合中除了特殊的
根(Root)
元素之外,每个元素有且仅有一个直接前驱,后继数目不限。 -
根元素没有直接前驱。
集合结构:松散的逻辑结构
-
处于同一数据集合中的元素之间除同属于该集合这一联系外没有其他的关系。
-
集合结构通常需要借助其他数据结构,比如线性结构和树。
-
唯一专用于集合类型的数据结构是哈希表。
图状结构:多对多关系
-
数据集合中每个元素的直接前驱和直接后继数目都不限。
3.存储结构
-
顺序存储
-
链接存储
-
索引存储
-
哈希存储
4.集合
-
scala中集合分为两大类1.可变长度集合 2.不可变长度集合
-
另一方面,又分为三种类型:序列、集、映射
1.Seq 序列
-
Array封装了java中的[]
-
ArrayBuffer 可变长度数组,类似于java的ArrayList
-
String 封装了java的String char[]
-
Range 通常使用to、until用来生成连续的范围
-
List 基本链表
-
Queue 队列:先进先出
-
Stack 栈:先进后出
2.Set 集
-
HashSet
-
TreeSet
3.Map 映射
-
HashMap
-
TreeMap
4.Tuple 元祖
是一种可以保存不同类型元素的容器
语法:元祖:声明语法(元素1,元素2,...)
-
元祖访问元素,使用 元祖.序号 例如t.1
-
元祖最多存放22个元素
-
包含两个元素的元组,称为二元组
1 package com.bd2108.jwl.scala 2 3 4 object scala19_元祖 { 5 def main(args: Array[String]): Unit = { 6 val a=3 7 val b=2 8 //写入一个函数 传入两个整数 9 //返回a/b的商和余数 以及小数 10 def f1(a:Int,b:Int)={ 11 // val r = new Result 12 // r.r1 = a / b 13 // r.r2 = a % b 14 // r.r3 = a.toDouble / b 15 val r1:Int=a/b 16 val r2:Int=a%b 17 val r3:Double=a.toDouble/b 18 (r1,r2,r3) 19 } 20 val res=f1(a,b) 21 //元祖访问元素,使用 元祖._序号 例如t._1 22 //元祖最多存放22个元素 23 val r1 = res._1 24 println(r1) 25 26 //在上面的场景中,由于同时需要返回多个不同类型的对象 27 //如果使用集合 只能使用公共父类Any作为泛型 28 //如果使用对象 结构的变化不够灵活 29 //scala中提供了一种特殊的结构 元祖:声明语法(元素1,元素2,...) 30 31 32 //包含两个元素的元素称为二元组,或者叫pair 对偶 33 (1,2) 34 val tuple = (1, "2") 35 val tuple1 = 1 -> 2 36 println(tuple) 37 println(tuple1) 38 } 39 }
20.数组
-
定长Array数组
1 //1.Array 2 //1.1创建 3 val arr = new Array[Int](5) 4 val arr1 = Array(1, 2, 3, 4, 5) 5 //1.2查改 6 //访问元素 7 val i = arr(0) 8 //修改元素 9 arr1(0)=13 10 //1.3遍历 11 //方法1: 12 for (x<-arr1){ 13 println(x) 14 } 15 //方法2: 16 for (i<-arr1.indices){ 17 println(arr1(i)) 18 } 19 //方法3: 20 arr1.foreach((x:Int)=>{println(x)}) 21 arr1.foreach((x:Int)=>println(x)) 22 arr1.foreach(x=>println(x)) 23 arr1.foreach(println(_)) 24 arr1.foreach(println _ ) 25 arr1.foreach(println)
-
变长数组ArrayBuffer
1 //2.ArrayBuffer 2 //2.1创建 3 val buff = new ArrayBuffer[Int]() 4 val buff1 = ArrayBuffer[Int]() 5 //2.2增删改查 6 //增 7 buff.append(111,2222,333) 8 //删 9 buff.remove(2,1) 10 println(buff) 11 //改 12 buff(0)=11111 13 //查 14 val b=buff(0) 15 println(buff) 16 17 //2.3遍历 18 buff.foreach(x=>println(x+1))
1 //当在同一个类中存在两个相同的代码块时,代码下会出现灰色波浪线 2 //解决方法:将相同部分提升成方法进行调用 3 val array:Array[Array[Int]] = Array.ofDim[Int](3, 3) 4 def print2DArray(arr: Array[Array[Int]]):Unit={ 5 array.foreach(arr=>{ 6 arr.foreach(a=>print(a+" ")) 7 println() 8 }) 9 } 10 print2DArray(array) 11 /*array.foreach(x=>{ 12 x.foreach(a=>print(a+" ")) 13 println() 14 })*/ 15 // 0 0 0 16 // 0 0 0 17 // 0 0 0 18 19 //将二维数组第2行第三个元素改成8 20 array(1)(2)=8 21 print2DArray(array) 22 /*array.foreach(x=>{ 23 x.foreach(a=>print(a+" ")) 24 println() 25 })*/ 26 //0 0 0 27 //0 0 8 28 //0 0 0
-
java与scala集合相互转换
1 val list = Test1.getTestList 2 val strings = new ArrayBuffer[String]() 3 for (i <- 0 until list.size()){ 4 strings.append(list.get(i)) 5 } 6 println(strings)//ArrayBuffer(111, 222, 333) 7 8 9 //scala经常需要与JavaAPI互相调用 10 //为了使用方便,scala提供了与java之间集合类的转换器 11 //1.导入转换器 12 import scala.collection.JavaConverters._ 13 //2.使用java集合.asScala可以返回scala集合 14 val res = list.asScala 15 print(res)//Buffer(111, 222, 333) 16 //3.使用scala集合.asJava可以返回java集合 17 res.asJava
21.import
-
scala中允许在任意位置使用import导入资源
-
可以导入类、类的成员,允许为导入的成员设置别名
1 package com.bd2108.jwl.scala 2 3 import java.util 4 5 object scala17_import { 6 def main(args: Array[String]): Unit = { 7 //scala中允许在任意位置使用import导入资源 8 //1.除了导入类 允许导入类的成员 9 import math._ 10 sqrt(2) 11 //2.允许为导入的成员设值别名 12 import scala.collection.immutable.{HashMap=>HaHa} 13 import java.util.{HashMap=>HeiHei} 14 val map = new HaHa[String, String] 15 val map1 = new HeiHei[String, String]() 16 //3.导入时,将某些类匿名,或者时隐藏某个导入 17 import java.lang.{String=>_} 18 new String 19 } 20 }
22.List
1 package com.bd2108.jwl.scala 2 3 object scala18_List { 4 def main(args: Array[String]): Unit = { 5 //List 6 //1.创建 7 val list = List(1, 2, 3, 4, 5) 8 val list1 = List[Int]() 9 //增删改查 10 //查看 11 val i = list(2) 12 print(i) 13 //在list的头部追加元素,产生新的list 14 println(list) 15 val list2= 8+:list 16 println(list2)//List(8, 1, 2, 3, 4, 5) 17 println(list)//List(1, 2, 3, 4, 5) 18 //在list的尾部追加元素,产生新的list 19 val list3=list2:+9 20 println(list3)//List(8, 1, 2, 3, 4, 5, 9) 21 //拼接两个list 22 val list4 = List(11, 22) ++ List(22, 33) 23 println(list4.distinct)//List(11, 22, 33) 24 //将多个元素按照顺序拼接到list的头部 25 //元素1::元素2::元素3::List() 26 val list5:List[Any] = 1 :: 2 :: List(2, 3) :: 4 :: List() 27 println(list5)//List(1, 2, List(2, 3), 4) 28 29 } 30 }
23.Map
1 package com.bd2108.jwl.scala 2 3 import scala.collection.mutable 4 5 6 object scala20_Map { 7 def main(args: Array[String]): Unit = { 8 //1.创建 9 val map = mutable.HashMap[String, String]() 10 //直接使用map特质的apply方法,将元素在初始化时添加到map中 11 Map(("k1","v1"),("k2","v2")) 12 Map("k1"->"v1","k2"->"v2") 13 //增删改查 14 map.put("k1","v1") 15 map.put("k2","v2") 16 map.put("k1","v111") 17 map.put("k3","v3") 18 println(map)//Map(k2 -> v2, k1 -> v111, k3 -> v3) 19 20 //去除所有key 21 val key = map.keySet 22 //去除所有value 23 val values = map.values 24 25 //map取值 26 //1.Option[V] = map.get(key) 27 val maybeString = map.get("k3") 28 //2.可以设值如果key不存在时的默认返回值 29 map.getOrElse("k5","v5") 30 //如果你非常确定这个key的存在,则可以使用map(key)取值 31 val v3 = map("k3") 32 println(v3) 33 34 35 //习题:统计一下字符串字母出现的次数 36 val str="jdowdfjskalaooqwwjmdkaskka" 37 val resmap = new mutable.HashMap[Char, Int]() 38 for (x<-str){ 39 /* if (resmap.contains(x)){ 40 // 如果结果集中 之前存在当前字符,则取出之前的数量 +1 写回去 41 val some = resmap.get(x) 42 var count = some.get 43 count += 1 44 resmap.put(x,count) 45 }else{ 46 //如果不存在 1 47 resmap.put(x,1) 48 }*/ 49 resmap.put(x,resmap.getOrElse(x,0)+1) 50 } 51 println(resmap) 52 //遍历 53 //使用for 54 for (t<-map){ 55 val k = t._1 56 val v = t._2 57 } 58 //先获取所有key,然后再遍历keyset取出值value 59 for(k<-map.keySet){ 60 val v = map(k) 61 } 62 //使用二元组遍历 63 for ((k,v)<-map){ 64 65 } 66 val list:List[(String,String)] = map.toList 67 println(list) 68 } 69 }
24.集合算子
1 package com.bd2108.jwl.scala 2 3 object scala21_集合算子 { 4 def main(args: Array[String]): Unit = { 5 val list = List(12, 1, 78, 33, 10, 897, 344) 6 val list1 = List[Int]() 7 //1.head last headOption lastOption 8 val head = list.head//拿到第一个元素 9 val last = list.last//拿到最后一个元素 10 val headOption = list.headOption 11 val lastOption = list.lastOption 12 /* println(head)//12 13 println(last)//344 14 println(headOption)//Some(12) 15 println(lastOption)//Some(344)*/ 16 val option = list1.headOption 17 /*println(option)//None*/ 18 19 20 //2.tail init 21 //tail 去掉第一个元素,保留剩下的元素 22 //init 去掉最后一个元素,保留剩下的元素 23 //val list = List(12, 1, 78, 33, 10, 897, 344) 24 val tail = list.tail 25 val init = list.init 26 println(tail)//List(1, 78, 33, 10, 897, 344) 27 println(init)//List(12, 1, 78, 33, 10, 897) 28 29 30 31 //3.排序 32 //升序排序 sorted 33 val sorted = list.sorted 34 //降序排序 35 val reverse = list.sorted.reverse 36 //降序排序并去掉一个最小值 37 val init1 = list.sorted.reverse.init 38 println(init1)//List(897, 344, 78, 33, 12, 10) 39 40 41 //4.获取集合长度 size length 42 val size = list.size 43 val length = list1.length 44 //判断集合是否为空 isEmpty nonEmpty 45 val empty = list.isEmpty 46 val empty1 = list1.nonEmpty 47 //println(empty)//false 48 // println(empty1)//false 49 50 //5.最值和算数 51 //sum product(乘积) max min 52 val product = List(1, 2, 3).product 53 //println(product) 54 val sum = List(1, 2, 3).sum 55 val max = List(1, 2, 3).max 56 //println(sum) 57 //println(max) 58 59 60 //6.count forall exists 61 //6.1 按照条件对元素计数 62 val list2 = List("ajdjdf", "ADHDJ", "sahdw2333") 63 //计算a和A出现的次数(当str只用了一次时,可以省略用_代替 64 //val i = list2.count(str=>str.toLowerCase.contains('a')) 65 val i = list2.count(_.toLowerCase.contains('a')) 66 //println(i) 67 //6.2 用于判断集合中的元素是否全部满足某个条件 68 //当所有元素都满足条件返回为true 69 val bool = list2.forall(str => str.length > 10) 70 //println(bool) 71 val list3 = List(2, 3, 4, 5, 0, -10, 2, 4, -7) 72 val bool1 = list3.forall(x => x >= 0) 73 //println(bool1) 74 75 //6.3 用于判断满足条件的元素在集合中是否存在 76 //集合中只要有一个元素满足条件就返回为true 77 val bool2 = list3.exists(_ < 0) 78 //println(bool2) 79 80 //7.过滤 81 val list4 = for (x <- list3 if x > 0) yield x 82 //println(list4) 83 val list5 = list3.filter(x => x > 0) 84 //println(list5) 85 val list6 = list3.filterNot(x => x > 0) 86 // println(list6) 87 88 //分区 将满足要求的元素放在一个list集合,不满足的放在另一个list 89 val p = list3.partition(_ > 0) 90 println(p) 91 92 //8.take 从集合中拿取元素个数,按照个数从左往右 93 val list7 = list3.take(2) 94 //println(list7) 95 //takeRight 从右向左取值 96 val list8 = list3.takeRight(3) 97 //println(list8) 98 //takeWhile 从左向右取值,一旦遇到不满足条件的元素,就停止取值,后面的元素不在遍历 99 val list9 = list3.takeWhile(x => x > 0) 100 // println(list9) 101 102 103 //9.drop 丢弃 104 val list10 = List(122, 333, 12, -2, -78, 44) 105 //丢弃集合中最小的三个数 106 val list11 = list10.sorted.drop(3) 107 //println(list11) 108 //方式2:将集合升序排列,从右向左取出集合长度-3个数 109 list10.sorted.takeRight(list10.length-3) 110 111 //dropRight 从右向左丢值 112 //dropWhile 从左向右丢值,一旦遇到不满足条件的元素,就停止丢弃 113 114 115 //10.span 将满足条件的放在一个集合,一旦遇到一个不满足条件的不管后面的元素是否还满足条件,都放在不满足条件的集合中 116 val tuple = list10.span(_ > 0) 117 println(tuple)//(List(122, 333, 12),List(-2, -78, 44)) 118 119 //11.splitAt 120 val tuple1 = list10.splitAt(2) 121 println(tuple1)//(List(122, 333),List(12, -2, -78, 44)) 122 } 123 }
集合算子高级
1 package com.bd2108.jwl.scala 2 3 object scala22_集合算子高级 { 4 def main(args: Array[String]): Unit = { 5 val list: List[Int] = (1 to 10).toList 6 //1.map 映射 7 //1.1声明 8 //def map[B](f: A => B): 集合[B] = 9 //1.2参数 10 //参数f是一个一元函数 f的参数是源集合的元素类型 11 //f的返回值可以是任意类型 12 //1.3 返回值 13 //返回值类型与源集合类型相同,泛型是f的返回值类型 14 //1.4 作用 15 //map接收一个一元函数f,将源集合中的所有元素依次传入f,并将f的返回值收集到新的集合 16 17 //将集合中的值全部+1 18 val map = Map("k1" -> 3, "k2" -> 5) 19 map.map(t => (t._1, t._2 + 1)) 20 21 val list1 = list.map(_ + "1") 22 println(list1) 23 24 // 将集合中所有3的倍数自增1 25 // 所有2的倍数变成原来的2倍 26 // 并将所有结果放入新的集合 27 // 如果既不是3的倍数 也不是2的倍数则不保留 28 val list2 = List(1, 2, 3, 4, 5, 6, 7) 29 list2.filter(x => x % 3 == 0 || x % 2 == 0) 30 .map(x => { 31 if (x % 3 == 0) x + 1 32 else x * 2 33 }) 34 35 36 //2.foreach 37 //2.1声明 38 //def foreach[U](f: A => U) : Unit = { 39 //2.2 参数 40 //参数f是一个一元函数 f的参数是源集合的元素类型 41 //f的返回值可以是任意类型 42 //2.3 返回值 43 //Unit 44 //2.4 作用 45 //与map类似接收一个一元函数f,将源集合中的元素依次传入f中 46 //不同的是,foreach不返回处理结果 而固定返回Unit 47 //通常用于将集合中的元素遍历输出到控制台或者外部存储 48 // f: Int => Int 49 // Int => Unit 50 list2.foreach((x: Int) => println(x)) 51 // Any => Unit 52 list2.foreach(println) 53 } 54 }
1 package com.bd2108.jwl.scala 2 3 import scala.collection.mutable 4 import scala.io.Source 5 6 object scala23_集合算子高级 { 7 def main(args: Array[String]): Unit = { 8 val path="C:\\Users\\Administrator\\IdeaProjects\\bigDate1\\scala\\src\\main\\resources\\Harry.txt" 9 //读取文本文件 10 val source = Source.fromFile(path) 11 val lines:List[String] = source.getLines().toList 12 source.close() 13 //统计文件中所有单词出现的数量 14 val count = new mutable.HashMap[String, Int]() 15 for (line<-lines){ 16 val words = line.split("\\s+") 17 for (word<-words){ 18 val w = word.toLowerCase 19 .replaceAll("\\W+","") 20 count.put(w,count.getOrElseUpdate(w,0)+1) 21 } 22 } 23 //println(count) 24 25 26 // 1. flatMap 扁平化映射 27 // 1.1 声明 28 // def flatMap[B,That](f: A => 集合[B]): That = { 29 // 3.2 参数 30 // f是一个一元函数 31 // f的参数是源集合的元素类型,f的返回值是一个集合,并且集合的泛型可以是任意类型 32 // 3.3 返回值 33 // 返回值类型时源集合类型,泛型是f的返回值泛型 34 // 3.4 作用 35 // 当使用map算子时返回的结果为二维集合 36 // 而实际需求希望拿到一维集合(将所有的内层集合的元素装到统一的容器中) 37 // 则可以将map替换成flatMap 38 // flatMap在对集合进行映射的同时 将二维集合扁平化为一维集合 39 40 // lines:List[String] => words:List[String] 41 // map(String => Array[String]) List[Array[String]] 42 val list:List[Array[String]] = lines.map(line => line.split("\\s+")) 43 //def flatMap[B,That](f:String=>Array[String]):List[String]={} 44 val count1=new mutable.HashMap[String,Int]() 45 val list1 = lines.flatMap(line => line.split("\\s+")) 46 list1.foreach(word=>{ 47 val w = word.toLowerCase.replaceAll("\\W+", "") 48 count1.put(w,count1.getOrElse(w,0)+1) 49 }) 50 51 52 val str = List("shdj", "ssjffvn", "rfjfnvf", "jfnfcuds") 53 val map = new mutable.HashMap[Char, Int]() 54 //def flatMap[B,That](f:String=>Array[Char]):List[Char]={} 55 val chars:List[Char] = str.flatMap(x => x.toCharArray) 56 println(chars) 57 58 59 //2.collect 收集 60 //2.1 声明 61 //def collect(pf: PartialFunction[A, B]): That = { 62 // 2.2. 参数 63 // 2.3. 返回值 64 // 2.4. 作用 65 //配合偏函数 进行输入和输出数量不对等的操作 输出 < 输入 66 val list2 = List(1, 2, 3, 4, 5, 6, 7) 67 list2.filter(x=>x%3==0 ||x%2==0).map(x=>{ 68 if(x%3==0)x+1 69 else x*2 70 }) 71 72 val pf= new PartialFunction[Int,Int] { 73 /** 74 * 判断传入的对象是否是需要处理的对象 75 * @param x 输入的对象 76 * @return 是否需要处理 77 */ 78 override def isDefinedAt(x: Int): Boolean = { 79 x%3==0 ||x%2==0 80 } 81 82 /** 83 * 偏函数处理的具体逻辑 84 * @param v1 满足条件的输入对象 85 * @return 处理的结果 86 */ 87 override def apply(v1: Int): Int = { 88 if (v1%3==0) v1+1 89 else v1*2 90 } 91 } 92 val list3 = list2.collect(pf) 93 val list4=list2.collect{ 94 // case 变量名 if 条件 => 返回值 95 case x if x%3==0=>x+1 96 case x if x%2==0=>x*2 97 } 98 println(list4) 99 } 100 }