240508Scala笔记
Scala概述:
SCala是Java的拓展,在Java的基础上又拓展了一些语法,例如: 输出Hello World
println("HelloWorld") System.out.println("Hello Scala from Java")
上面两段代码都可以输出内容.
package chapter01 /* object: 关键字,声明一个单例对象 */ object HelloWorld { /* main 方法: 从外部可以直接调用执行的方法 def 方法名称(参数名称:参数类型):返回值类型 = {方法体} */ def main(args: Array[String]): Unit = { println("HelloWorld") System.out.println("Hello Scala from Java") } }
其中上面的object是一个单例对象.
object : 关键字,声明一个单例对象
main 方法:从外部可以直接调用执行的方法
def 方法名称(参数名称:参数类型) : 返回值类型={方法体}
Scala入门:
(下面是一段java代码)创建一个学生类:(对方法的引用)
Java代码:
import scala.io.StdIn; public class Student { private String name; private Integer age; private static String school= "YelloRiwer"; public Student(String name,Integer age){ this.name = name; this.age = age; } public void printInfo(){ System.out.println(this.name+" "+this.age+" "+ Student.school); } public static void main(String[] args){ Student alice = new Student("alice",20); Student bob = new Student("bob",23); alice.printInfo(); bob.printInfo(); } }
运行结果:
alice 20 YelloRiwer bob 23 YelloRiwer
如果我想要静态且不想要他的属性那就需要Scala. 下面这段Scala代码和上面的Java代码一样,但是比Java代码简洁了许多:
Scala代码:
package chapter01 class Student(name : String,age:Int) { def printInfo():Unit = { println(name+" "+age+" "+Student.school) } } //引入伴生对象 object Student{ val school:String = "YelloRiwer" def main(args: Array[String]): Unit = { val alice = new Student("alice",20) val bob = new Student("bob",23) alice.printInfo() bob.printInfo() } }
运行结果:
alice 20 YelloRiwer bob 23 YelloRiwer
Scala基本操作:
IDEA快捷键: 快速格式化: Ctrl + Alt + L
2.2变量和常量(重点)
常量:在程序执行的过程中,其值不会被改变的变量
0)回顾:Java 变量和常量语法
变量类型 变量名称 = 初始值 int a = 10 final 常量类型 常量名称 = 初始值 final int b = 20
1)Scala基本语法
var 变量名 [: 变量类型] = 初始值 var i:Int = 10 val 常量名 [: 常量类型] = 初始值 val j:Int = 20
注意:能用常量的地方不用变量
chapter02
Text02
变量与常量
package chapter02 import chapter01.Student object Test02_Variable { def main(args: Array[String]): Unit = { // 声明一个变量的通用语法 var a: Int = 10 //(1)声明变量时,类型可以省略,编译器自动推导,即类型推导 var a1 = 10 val b1 = 23 //(2)类型确定后,就不能修改,说明Scala是强数据类型语言。 var a2 = 15 // a2类型为Int // a2 = "hello" //(3)变量声明时,必须要有初始值 // var a3: Int //(4)在声明/定义一个变量时,可以使用var或者val来修饰,var修饰的变量可改变,val修饰的变量不可改。 a1 = 12 // b1 = 25 var alice = new Student("alice", 20) alice = new Student("Alice", 20) alice = null val bob = new Student("bob", 23) bob.age = 24 bob.printInfo() // bob = new Student("bob", 24) } }
Text03
标识符
package chapter02 object Test03_Identifier { def main(args: Array[String]): Unit = { //(1)以字母或者下划线开头,后接字母、数字、下划线 val hello: String = "" var Hello123 = "" val _abc = 123 // val h-b = "" // val 123abc = 234 //(2)以操作符开头,且只包含操作符(+ - * / # !等) val -+/% = "hello" println(-+/%) //(3)用反引号`....`包括的任意字符串,即使是Scala关键字(39个)也可以 val `if` = "if" println(`if`) } }
Text04
字符串拼接
package chapter02 object Test04_String { def main(args: Array[String]): Unit = { //(1)字符串,通过+号连接 val name: String = "alice" val age: Int = 18 println(age + "岁的" + name + "在尚硅谷学习") // *用于将一个字符串复制多次并拼接 println(name * 3) //(2)printf用法:字符串,通过%传值。 printf("%d岁的%s在尚硅谷学习", age, name) println() //(3)字符串模板(插值字符串):通过$获取变量值 println(s"${age}岁的${name}在尚硅谷学习") val num: Double = 2.3456 println(f"The num is ${num}%2.2f") // 格式化模板字符串 println(raw"The num is ${num}%2.2f") // 三引号表示字符串,保持多行字符串的原格式输出 val sql = s""" |select * |from | student |where | name = ${name} |and | age > ${age} |""".stripMargin println(sql) } }
println() printf() System.out.println()
上面三个都可以输出内容
println和System.out.println一样
printf("%d岁的%s在尚硅谷学习", age, name)
println(s"")#字符串模板
println(f"")#快速格式化字符串
println(raw"")#原始格式输出
Text05
键盘输入
package chapter02 import scala.io.StdIn object Test05_StdIn { def main(args: Array[String]): Unit = { // 输入信息 println("请输入您的大名:") val name: String = StdIn.readLine() println("请输入您的芳龄:") val age: Int = StdIn.readInt() // 控制台打印输出 println(s"欢迎${age}岁的${name}来到尚硅谷学习") } }
Text06
读写文件
package chapter02 import java.io.{File, PrintWriter} import scala.io.Source object Test06_FileIO { def main(args: Array[String]): Unit = { // 1. 从文件中读取数据 Source.fromFile("src/main/resources/test.txt").foreach(print) // 2. 将数据写入文件 val writer = new PrintWriter(new File("src/main/resources/output.txt")) writer.write("hello scala from java writer") writer.close() } }
Text07
文件类型
package chapter02 import chapter01.Student object Test07_DataType { def main(args: Array[String]): Unit = { // 1. 整数类型 val a1: Byte = 127 val a2: Byte = -128 // val a2: Byte = 128 // error val a3 = 12 // 整数默认类型为Int val a4: Long = 1324135436436L // 长整型数值定义 val b1: Byte = 10 val b2: Byte = 10 + 20 println(b2) // val b3: Byte = b1 + 20 val b3: Byte = (b1 + 20).toByte println(b3) // 2. 浮点类型 val f1: Float = 1.2345f val d1 = 34.2245 // 3. 字符类型 val c1: Char = 'a' println(c1) val c2: Char = '9' println(c2) // 控制字符 val c3: Char = '\t' // 制表符 val c4: Char = '\n' // 换行符 println("abc" + c3 + "def") println("abc" + c4 + "def") // 转义字符 val c5 = '\\' // 表示\自身 val c6 = '\"' // 表示" println("abc" + c5 + "def") println("abc" + c6 + "def") // 字符变量底层保存ASCII码 val i1: Int = c1 println("i1: " + i1) val i2: Int = c2 println("i2: " + i2) val c7: Char = (i1 + 1).toChar println(c7) val c8: Char = (i2 - 1).toChar println(c8) // 4. 布尔类型 val isTrue: Boolean = true println(isTrue) // 5. 空类型 // 5.1 空值Unit def m1(): Unit = { println("m1被调用执行") } val a: Unit = m1() println("a: " + a) // 5.2 空引用Null // val n: Int = null // error var student: Student = new Student("alice", 20) student = null println(student) // 5.3 Nothing def m2(n: Int): Int = { if (n == 0) throw new NullPointerException else return n } val b: Int = m2(2) println("b: " + b) } }
Text08
自动类型转换:
package chapter02 object Test08_DataTypeConversion { def main(args: Array[String]): Unit = { // 1. 自动类型转换 // (1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。 val a1: Byte = 10 val b1: Long = 2353 val result1: Long = a1 + b1 val result11: Int = (a1 + b1.toInt) // 强转 // (2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。 val a2: Byte = 10 val b2: Int = a2 // val c2: Byte = b2 // error // (3)(byte,short)和char之间不会相互自动转换。 val a3: Byte = 10 val b3: Char = 'b' // val c3: Byte = b3 // error val c3: Int = b3 println(c3) // (4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。 val a4: Byte = 12 val b4: Short = 25 val c4: Char = 'c' val result4: Int = a4 + b4 val result44: Int = a4 + b4 + c4 println(result44) // 2. 强制类型转换 // (1)将数据由高精度转换为低精度,就需要使用到强制转换 val n1: Int = -2.9.toInt println("n1: " + n1) // (2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级 val n2: Int = 2.6.toInt + 3.7.toInt val n3: Int = (2.6 + 3.7).toInt println("n2: " + n2) println("n3: " + n3) // 3. 数值类型和String类型的转换 // (1) 数值转String val n: Int = 27 val s: String = n + "" println(s) // (2) String转数值 val m: Int = "12".toInt val f: Float = "12.3".toFloat val f2: Int = "12.3".toDouble.toInt println(f2) } }
Text09
package chapter02 /* 128: Int类型,占据4个字节,32位 原码 0000 0000 0000 0000 0000 0000 1000 0000 补码 0000 0000 0000 0000 0000 0000 1000 0000 截取最后一个字节,Byte 得到补码 1000 0000 表示最大负数 -128 130: Int类型,占据4个字节,32位 原码 0000 0000 0000 0000 0000 0000 1000 0010 补码 0000 0000 0000 0000 0000 0000 1000 0010 截取最后一个字节,Byte 得到补码 1000 0010 对应原码 1111 1110 -126 */ object Test09_Problem_DataTypeConversion { def main(args: Array[String]): Unit = { var n: Int = 130 val b: Byte = n.toByte println(b) } }
范围数据循环(Until)
1)基本语法
for(i <- 1 until 3) { print(i + " ") } println()
(1)这种方式和前面的区别在于 i 是从 1 到 3-1
(2)即使前闭合后开的范围
2)案例实操
需求:输出 5 句 "宋宋,告别海狗人参丸吧"
object TestFor { def main(args: Array[String]): Unit = { for(i <- 1 until 5 + 1){ println("宋宋,告别海狗人参丸吧" + i) } } }
循环守卫
1)基本语法
for(i <- 1 to 3 if i != 2) { print(i + " ") } println()
说明:
(1)循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为 true 则进入循环
体内部,为 false 则跳过,类似于 continue。
(2)与上面的代码等价
for (i <- 1 to 3){ if (i != 2) { print(i + " ") } }
2)案例实操
需求:输出 1 到 5 中,不等于 3 的值
object TestFor { def main(args: Array[String]): Unit = { for (i <- 1 to 5 if i != 3) { println(i + "宋宋") } } }
循环步长
1)基本语法
for (i <- 1 to 10 by 2) { println("i=" + i) }
说明:by 表示步长
2)案例实操
需求:输出 1 到 10 以内的所有奇数 by表示步长
for (i <- 1 to 10 by 2) { println("i=" + i) }
输出结果
i=1 i=3 i=5 i=7 i=9
嵌套循环
1)基本语法
for(i <- 1 to 3; j <- 1 to 3) { println(" i =" + i + " j = " + j) }
说明:没有关键字,所以范围后一定要加;来隔断逻辑
2)基本语法
上面的代码等价
for (i <- 1 to 3) { for (j <- 1 to 3) { println("i =" + i + " j=" + j) } }
引入变量
1)基本语法
for(i <- 1 to 3; j = 4 - i) { println("i=" + i + " j=" + j) }
说明:
(1)for 推导式一行中有多个表达式时,所以要加 ; 来隔断逻辑
(2)for 推导式有一个不成文的约定:当 for 推导式仅包含单一表达式时使用圆括号,
当包含多个表达式时,一般每行一个表达式,并用花括号代替圆括号,如下
for { i <- 1 to 3 j = 4 - i } { println("i=" + i + " j=" + j) }
2)案例实操
上面的代码等价于
for (i <- 1 to 3) { var j = 4 - i println("i=" + i + " j=" + j) }
循环返回值
1)基本语法
val res = for(i <- 1 to 10) yield i println(res)
说明:将遍历过程中处理的结果返回到一个新 Vector 集合中,使用 yield 关键字。
注意:开发中很少使用。
2)案例实操
需求:将原数据中所有值乘以 2,并把数据返回到一个新的集合中。
object TestFor { def main(args: Array[String]): Unit = { var res = for(i <-1 to 10) yield { i * 2 } println(res) } }
输出结果:
Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
倒序打印
1)说明:如果想倒序打印一组数据,可以用 reverse。 2)案例实操: 需求:倒序打印 10 到 1 for(i <- 1 to 10 reverse){ println(i) }
While和do...While循环控制
While和do...While的使用和Java语言中用法相同
While循环控制
1)基本语法
循环变量初始化; while (循环条件) { 循环体(语句) 循环变量迭代 }
说明:
(1)循环条件是返回一个布尔值的表达式
(2)while 循环是先判断再执行语句
(3)与 for 语句不同,while 语句没有返回值,即整个 while 语句的结果是 Unit 类型()
(4)因为 while 中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免
的使用变量,而变量需要声明在 while 循环的外部,那么就等同于循环的内部对外部的变量
造成了影响,所以不推荐使用,而是推荐使用 for 循环。
2)案例实操
需求:输出 10 句 "宋宋,喜欢海狗人参丸"
object TestWhile { def main(args: Array[String]): Unit = { var i = 0 while (i < 10) { println("宋宋,喜欢海狗人参丸" + i) i += 1 } } }
do...while循环控制
1)基本语法
循环变量初始化; do{ 循环体(语句) 循环变量迭代 } while(循环条件)
说明
(1)循环条件是返回一个布尔值的表达式
(2)do..while 循环是先执行,再判断
2)案例实操
需求:输出 10 句 "宋宋,喜欢海狗人参丸"
object TestWhile { def main(args: Array[String]): Unit = { var i = 0 do { println("宋宋,喜欢海狗人参丸" + i) i += 1 } while (i < 10) } }
循环中断
1)基本说明
Scala 内置控制结构特地去掉了 break 和 continue,是为了更好的适应函数式编程,推
荐使用函数式的风格解决break和continue的功能,而不是一个关键字。Scala中使用breakable
控制结构来实现 break 和 continue 功能。
2)案例实操
需求 1:采用异常的方式退出循环
def main(args: Array[String]): Unit = { try { for (elem <- 1 to 10) { println(elem) if (elem == 5) throw new RuntimeException } }catch { case e => } println("正常结束循环") }
需求 2:采用 Scala 自带的函数,退出循环
import scala.util.control.Breaks def main(args: Array[String]): Unit = { Breaks.breakable( for (elem <- 1 to 10) { println(elem) if (elem == 5) Breaks.break() } ) println("正常结束循环") }
需求 3:对 break 进行省略
import scala.util.control.Breaks._ object TestBreak { def main(args: Array[String]): Unit = { breakable { for (elem <- 1 to 10) { println(elem) if (elem == 5) break } } println("正常结束循环") } }
需求 4:循环遍历 10 以内的所有数据,奇数打印,偶数跳过(continue)
object TestBreak { def main(args: Array[String]): Unit = { for (elem <- 1 to 10) { if (elem % 2 == 1) { println(elem) } else { println("continue") } } } }
多重循环
1)基本说明
(1)将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for,while,do…while
均可以作为外层循环和内层循环。【建议一般使用两层,最多不要超过 3 层】
(2)设外层循环次数为 m 次,内层为 n 次,则内层循环体实际上需要执行 m*n 次。
2)案例实操
需求:打印出九九乘法表
object TestWhile { def main(args: Array[String]): Unit = { for (i <- 1 to 9) { for (j <- 1 to i) { print(j + "*" + i + "=" + (i * j) + "\t") } println() } } }
输出结果: