Scala学习笔记

累了,基础配置不想写了,直接抄了→Scala的环境搭建

这里需要注意的是,创建新项目时,不要用默认的Class类,用Object,原因看→scala中的object为什么可以直接运行

Scala学习笔记_第1张图片

一、Scala简介

1.1 图解Scala和Java的关系

Scala学习笔记_第2张图片

1.2 关键字说明

package: 包,等同于java中的package

object:关键字,声明一个单例对象(伴生对象)

main方法:从外部可以直接调用执行的方法

def 方法名称 ( 参数名称 : 参数类型 ) : 返回值类型 = { 方法体 }

Scala 完全面向对象,故scala去掉了Java中非面向对象的元素,如static关键字,void类型
1) static
scala无static关键字,由object实现类似静态方法的功能(类名.方法名)
class关键字和Java中的class关键字作用相同,用来定义一个类
2) void
对于无返回值的函数,scala定义其返回值类型为Unit类型

1.3 代码案例


     
     
       
       
       
       
  1. package com.scala.chapter1
  2. object Hello {
  3. def main (args: Array[String]): Unit = {
  4. println( "hello scala")
  5. System.out.println( "hello scala")
  6. }
  7. }

1.4 Scala语言特点

Scala是一门以Java虚拟机 (JVM)为运行环境并将面向对象函数式编程的最佳特性结合在一起的静态类型编程语言(静态语言需要提前编译的如: Java、C、C++等,动态语言如:JS)。

1)Scala是一门多范式的编程语言,Scala支持面向对象和函数式编程。 (多范式,就是多种编程方法的意思。有面向过程、面向对象、泛型、函数式四种程序设计方法。)

2)Scala源代码 (.scala) 会被编译成Java字节码 (.class),然后运行于JVM之上,并可以调用现有的Java类库实现两种语言的无缝对接

3)Scala单作为一门语言来看,非常的简洁高效

4)Scala在设计时,马丁·奥德斯基是参考了Java的设计思想,可以说Scala是源于Java,同时马丁·奥德斯基也加入了自己的思想,将函数式编程语言的特点融合到JAVA中,因此,对于学习过Java的同学,只要在学习Scala的过程中,搞清楚Scala和Java相同点和不同点,就可以快速的掌握Scala这门语言。

二、变量和数据类型

Scala学习笔记_第3张图片
Any: 所有类型的超类(顶级类型)
AnyVal: 值类型的超类
AnyRef: 引用类型的超类,对应java.lang.Object
Unit: 无值,类似java中的void
Nothing: 所有类型的子类
Null: 表示null或空引用

2.1 注释

Scala注释使用和Java完全一样。

注释是一个程序员必须要具有的良好编程习惯。将自己的思想通过注释先整理出来,再用代码去体现。

1)基本语法


     
     
       
       
       
       
  1. 1)单行注释: //
  2. 2)多行注释: /* */
  3. 3)文档注释: /**
  4. *
  5. */

2)案例实操


     
     
       
       
       
       
  1. object Test1 {
  2. def main(args: Array[ String]): Unit = {
  3. //单行注释
  4. println( "单行")
  5. //多行
  6. /*
  7. println("多行")
  8. */
  9. //文档注释
  10. /**
  11. * println("文档注释")
  12. */
  13. }
  14. }

3) 代码规范

(1)使用一次tab操作,实现缩进,默认整体向右边移动,用shift+tab整体向左移

(2)或者使用ctrl + alt + L来进行格式化

(3)运算符两边习惯性各加一个空格。比如:2 + 4 * 5

(4)一行最长不超过80个字符,超过的请使用换行展示,尽量保持格式优雅

2.2 变量和常量(重点)

常量:在程序执行的过程中,其值不会被改变的变量

1)基本语法

var 变量名 [: 变量类型] = 初始值 var i:Int = 10

val 常量名 [: 常量类型] = 初始值 val j:Int = 20

注意:能用常量的地方不用变量

2)案例实操

(1)声明变量时,类型可以省略,编译器自动推导,即类型推导

(2)类型确定后,就不能修改,说明Scala是强数据类型语言。

(3)变量声明时,必须要有初始值

(4)在声明/定义一个变量时,可以使用var或者val来修饰,var修饰的变量可改变,val修饰的变量不可改。


     
     
       
       
       
       
  1. object TestValueTransfer {
  2. def main(args: Array[ String]): Unit = {
  3. var n = 1 + 2.2222
  4. println(n) //Double
  5. var n2: Double = 2.2222
  6. // var n3: Int = n2 //报错
  7. var n4 : Byte = 44
  8. // var c1 : Char = n4 //报错
  9. var n5 : Int = n4
  10. var n6 : Byte = 66
  11. var c2 : Char = 22
  12. // var n : Short = n6 + c2 //报错,结果是Int类型
  13. // var n7 : Short = 10 + 20 //报错,byte,short,char他们三者可以计算,在计算时首先转换为int类型。
  14. }
  15. }

(5)var修饰的对象引用可以改变,val修饰的对象则不可改变,但对象的状态(值)却是可以改变的。(比如:自定义对象、数组、集合等等)


     
     
       
       
       
       
  1. object TestVar {
  2. def main(args: Array[ String]): Unit = {
  3. var age = 22
  4. age = 29
  5. // age = "hh" //报错
  6. var n1 = 1 //可变
  7. n1 = 2
  8. val n2 = 2 //不可变
  9. //n2 = 3
  10. //p1 是var修饰的,p1的属性可以变,p1本身也可以变
  11. var p1 = new Person()
  12. p1.name = "varp1"
  13. p1 = null
  14. val p2 = new Person()
  15. p2.name = "valp2"
  16. // p2 = null //报错
  17. }
  18. class Person {
  19. var name: String = "who"
  20. }
  21. }

2.3 标识符的命名规范

Scala对各种变量、方法、函数等命名时使用的字符序列称为标识符。即:凡是自己可以起名字的地方都叫标识符。

1)命名规则

Scala中的标识符声明,基本和Java是一致的,但是细节上会有所变化,有以下三种规则:

(1)以字母或者下划线开头,后接字母、数字、下划线

(2)以操作符开头,且只包含操作符(+ - * / # !等)

(3)用反引号....包括的任意字符串,即使是Scala关键字(39个)也可以


     
     
       
       
       
       
  1. package, import, class, object, trait, extends, with, type, for
  2. private, protected, abstract, sealed, final, implicit, lazy, override
  3. try, catch, finally, throw
  4. if, else, match, case, do, while, for, return, yield
  5. def, val, var
  6. this, super
  7. new
  8. true, false, null

2)案例实操

需求:判断hello、Hello12、1hello、h-b、x h、h_4、ab、Int、、+-/#!、+-/#!1、if、if,这些名字是否合法。


     
     
       
       
       
       
  1. object TestName {
  2. def main(args: Array[ String]): Unit = {
  3. //1.以字母或者下划线开头,后接字母、数字、下划线
  4. var hello: String = ""
  5. var hello2: String = " "
  6. // var 1 hello:String = "" 数字不能开头
  7. // var h - b: String = "" 不能用-
  8. // var x h: String = "" 不能用空格
  9. var h_4: String = ""
  10. val _ab: String = ""
  11. var Int: String = "" //ok 因为在Scala中Int是预定义的字符,不是关键字,但不推荐
  12. var _: String = "" // ok 单独一个下划线不可以作为标识符,因为_被认为是一个方法
  13. //2.以操作符开头,且只包含操作符(+ - * / # ! 等)
  14. var +*-/#! : String = ""
  15. // var +*-/#!1 : String = "" 以操作符开头必须都是操作符
  16. //3.用反引号`...`包括的任意字符串,即使是Scala关键字(39)个也可以
  17. // var if:String = "" 不用用关键字
  18. var ` if`: String = ""
  19. }
  20. }

2.4 字符串输出

1)基本语法

(1)字符串,通过+号连接

(2)printf用法:字符串,通过%传值。

(3)字符串模板(插值字符串):通过$获取变量值

2)案例实操


     
     
       
       
       
       
  1. object TestCharType {
  2. def main(args: Array[ String]): Unit = {
  3. var name: String = "zhangsan"
  4. var age: Int = 22
  5. //1.字符串 通过 + 号连接
  6. println(name + " " + age)
  7. //2.printf 用法字符串,通过%传值
  8. printf( "name=%s age=%d\n", name, age)
  9. //3.字符串,通过$引用
  10. //多行字符串,在Scala中,利用三个双引号包围多行字符串就可以实现。//输入的内容,带有空格、\t之类,导致每一行的开始位置不能整洁对齐。
  11. //应用scala的stripMargin方法,在scala中stripMargin默认是“|”作为连接符,//在多行换行的行头前面加一个“|”符号即可。
  12. val s =
  13. """
  14. | select
  15. | name
  16. |,
  17. |age
  18. |from user
  19. |where name = "zhangsan"
  20. """.stripMargin
  21. println(s)
  22. //如果需要对变量进行运算,那么可以加${}
  23. val s1 =
  24. s"" "
  25. | select
  26. | name
  27. |,
  28. |age
  29. |from user
  30. |where name="$ name" and age=${age + 2}
  31. " "".stripMargin
  32. val s2 = s"name=$name"
  33. println(s2)
  34. }
  35. }

2.5 键盘输入

在编程中,需要接收用户输入的数据,就可以使用键盘输入语句来获取。

1)基本语法

StdIn.readLine()、StdIn.readShort()、StdIn.readDouble()

2)案例实操

需求:可以从控制台接收用户信息,【姓名,年龄,薪水】。


     
     
       
       
       
       
  1. import scala.io. StdIn
  2. object TestInput {
  3. def main(args: Array[ String]): Unit = {
  4. // 输入姓名
  5. println( "input name:")
  6. var name = StdIn.readLine()
  7. // 输入年龄
  8. println( "input age:")
  9. var age = StdIn.readShort()
  10. // 输入薪水
  11. println( "input sal:")
  12. var sal = StdIn.readDouble()
  13. // 打印
  14. println( "name=" + name)
  15. println( "age=" + age)
  16. println( "sal=" + sal)
  17. }
  18. }

从文件中读取数据:


     
     
       
       
       
       
  1. import scala.io. Source;
  2. Source.fromFile( "C:\\Users\\90513\\Desktop\\datas.csv").foreach(print)
Scala学习笔记_第4张图片

2.6 数据类型(重点)

  • Java 数据类型

Java基本数据类型:char、byte、short、int、long、float、double、boolean

Java引用类型:(对象类型)

由于Java有基本类型,而且基本类型不是真正意义的对象,即使后面产生了基本类型的包装类,但是仍然存在基本数据类型,所以Java语言并不是真正意义上的面向对象

Java基本类型的包装类:Character、Byte、Short、Integer、Long、Float、Double、Boolean

注意:Java中基本类型和引用类型没有共同的祖先

  • Scala 数据类型

Scala学习笔记_第5张图片

2.7 整数类型(Byte、Short、Int、Long)

Scala的整数类型就是用于存放整数值的,比如12,30,3456等等。

1)整型分类

数据类型

描述

Byte [1]

8位有符号补码整数。数值区间为 -128 到 127

Short [2]

16位有符号补码整数。数值区间为 -32768 到 32767

Int [4]

32位有符号补码整数。数值区间为 -2147483648 到 2147483647

Long [8]

64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807 = 2的(64-1)次方-1

2)案例实操

(1)Scala各整数类型有固定的表示范围和字段长度,不受具体操作的影响,以保证Scala程序的可移植性。

(2)Scala的整型,默认为Int型,声明Long型,须后加‘l’或‘L’


     
     
       
       
       
       
  1. object TestDataType {
  2. def main (args: Array[String]): Unit = {
  3. // 正确
  4. var n1: Byte = 127
  5. var n2: Byte = - 128
  6. // 错误
  7. // var n3:Byte = 128
  8. // var n4:Byte = -129
  9. // Scala的整型,默认为Int型,声明Long型,然后加”i“ 或者 ”L“
  10. var n5 = 10
  11. println(n5)
  12. var n6 = 98989898989898989L
  13. println(n6)
  14. var n7 = 2.43434309898f
  15. var n8 = 2.4343662343223
  16. println(n7)
  17. println(n8)
  18. var God = new God()
  19. God = null
  20. //var n1 : Int = null //错误
  21. //println("n1:" + n1)
  22. }
  23. class God {
  24. }
  25. }

(3)Scala程序中变量常声明为Int型,除非不足以表示大数,才使用Long

2.8 浮点类型(Float、Double)

Scala的浮点类型可以表示一个小数,比如123.4f,7.8,0.12等等。

1)浮点型分类

数据类型

描述

Float [4]

32 位, IEEE 754标准的单精度浮点数

Double [8]

64 位 IEEE 754标准的双精度浮点数

2)案例实操

Scala的浮点型常量默认为Double型,声明Float型常量,须后加‘f’或‘F’。


     
     
       
       
       
       
  1. object TestDataType {
  2. def main (args: Array[String]): Unit = {
  3. // 正确
  4. var n1: Byte = 127
  5. var n2: Byte = - 128
  6. // 错误
  7. // var n3:Byte = 128
  8. // var n4:Byte = -129
  9. // Scala的整型,默认为Int型,声明Long型,然后加”i“ 或者 ”L“
  10. var n5 = 10
  11. println(n5)
  12. var n6 = 98989898989898989L
  13. println(n6)
  14. var n7 = 2.43434309898f
  15. var n8 = 2.4343662343223
  16. println(n7)
  17. println(n8)
  18. var God = new God()
  19. God = null
  20. //var n1 : Int = null //错误
  21. //println("n1:" + n1)
  22. }
  23. class God {
  24. }
  25. }

2.9 字符类型(Char)

1)基本说明

字符类型可以表示单个字符,字符类型是Char。

2)案例实操

(1)字符常量是用单引号 ’ ’ 括起来的单个字符。

(2)\t :一个制表位,实现对齐的功能

(3)\n :换行符

(4)\\ :表示\

(5)" :表示"


     
     
       
       
       
       
  1. package com.atguigu.chapter1
  2. object TestCharType2 {
  3. def main (args: Array[String]): Unit = {
  4. var c1: Char = 'a'
  5. println( "c1=" + c1)
  6. //注意:这里涉及自动类型提升,其实编译器可以自定判断是否超出范围
  7. //不过idea提示报错
  8. var c2: Char = 'a' + 1
  9. println(c2)
  10. // \t :一个制表位,实现对齐的功能
  11. println( "姓名\t年龄")
  12. // \n :换行符
  13. println( "西门庆\n潘金莲")
  14. //(4)\\ :表示\
  15. println( "c:\\天黑了\\饿狼来了")
  16. //(5)\" :表示"
  17. println( "你过来:\"看我一拳打死你\"")
  18. }
  19. }

2.10 布尔类型:Boolean

1)基本说明

(1)布尔类型也叫Boolean类型,Booolean类型数据只允许取值true和false

(2)boolean类型占1个字节。

2)案例实操


     
     
       
       
       
       
  1. object TestBooleanType {
  2. def main (args: Array[String]): Unit = {
  3. var isResult : Boolean = false
  4. var isResult2 : Boolean = true
  5. }
  6. }

2.11 Unit类型、Null类型和Nothing类型(重点)

1)基本说明

数据类型

描述

Unit

表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。

Null

null , Null 类型只有一个实例值null

Nothing

Nothing类型在Scala的类层级最低端;它是任何其他类型的子类型。 当一个函数,我们确定没有正常的返回值(如抛出异常),可以用Nothing来指定返回类型,这样有一个好处,就是我们可以把返回的值(异常)赋给其它的函数或者变量(兼容性

在Java中有时候有返回值,如int,但有些情况下会抛出异常。为了兼容多种可能性,就可以使用nothing类型。

2)案例实操

(1)Unit类型用来标识过程,也就是没有明确返回值的函数。

由此可见,Unit类似于Java里的void。Unit只有一个实例——( ),这个实例也没有实质意义


     
     
       
       
       
       
  1. def m1(): Unit={
  2.     println( "m1被执行")
  3. }
  4. val a: Unit=m1()
  5. println( "a="+a)
  6. // 输出:a=()

(2)Null类只有一个实例对象,Null类似于Java中的null引用。Null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)


     
     
       
       
       
       
  1. object TestDataType {
  2. def main(args: Array[ String]): Unit = {
  3. // 正确
  4. var n1: Byte = 127
  5. var n2: Byte = -128
  6. // 错误
  7. // var n3:Byte = 128
  8. // var n4:Byte = -129
  9. // Scala的整型,默认为Int型,声明Long型,然后加”i“ 或者 ”L“
  10. var n5 = 10
  11. println(n5)
  12. var n6 = 98989898989898989L
  13. println(n6)
  14. var n7 = 2.43434309898f
  15. var n8 = 2.4343662343223
  16. println(n7)
  17. println(n8)
  18. // null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)
  19. var God = new God()
  20. God = null
  21. // var n1: Int = null //错误
  22. // println("n1:" + n1)
  23. }
  24. class God {
  25. }
  26. }

(3)Nothing,可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回,而且由于Nothing是其他任意类型的子类,他还能跟要求返回值的方法兼容。


     
     
       
       
       
       
  1. object TestSpecialType {
  2. def test(): Nothing = {
  3. throw new Exception
  4. }
  5. test()
  6. }
  7. }

2.12 类型转换

2.12.1 数值类型自动转换

当Scala程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数值类型,这个就是自动类型转换(隐式转换)。数据类型按精度(容量)大小排序为:

1)基本说明

(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。

(2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。

(3)(byte,short)和char之间不会相互自动转换。

(4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。

2)案例实操


     
     
       
       
       
       
  1. object TestValueTransfer {
  2. def main(args: Array[ String]): Unit = {
  3. //(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数值类型,然后再进行计算。
  4. var n = 1 + 2.2222
  5. println(n) //Double
  6. //(2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
  7. var n2: Double = 2.2222
  8. // var n3: Int = n2 //报错
  9. //(3)(byte,short)和char之间不会相互自动转换。
  10. var n4: Byte = 44
  11. // var c1 : Char = n4 //报错
  12. var n5: Int = n4
  13. //(4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。
  14. var n6: Byte = 66
  15. var c2: Char = 22
  16. // var n : Short = n6 + c2 //报错,结果是Int类型
  17. // var n7 : Short = 10 + 20 //报错,byte,short,char他们三者可以计算,在计算时首先转换为int类型。
  18. }
  19. }

注意:Scala还提供了非常强大的隐式转换机制(隐式函数,隐式类等),我们放在高级部分专门用一个章节来讲解。

2.12.2 强制类型转换

1)基本说明

自动类型转换的逆过程,将精度大的数值类型转换为精度小的数值类型。使用时要加上强制转函数,但可能造成精度降低或溢出,格外要注意。

2)案例实操

(1)将数据由高精度转换为低精度,就需要使用到强制转换

(2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级


     
     
       
       
       
       
  1. object TestForceTransfer {
  2. def main(args: Array[ String]): Unit = {
  3. //(1)将数据由高精度转换为低精度,就需要使用到强制转换
  4. var n1: Int = 2.5.toInt // 这个存在精度损失
  5. //(2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
  6. var r1: Int = 10 * 3.5.toInt + 6 * 1.5.toInt // 10 *3 + 6*1 = 36
  7. var r2: Int = ( 10 * 3.5 + 6 * 1.5).toInt // 44.0.toInt = 44
  8. println( "r1=" + r1 + " r2=" + r2)
  9. }
  10. }

2.12.3 数值类型和String类型间转换

1)基本说明

在程序开发中,我们经常需要将基本数值类型转成String类型。或者将String类型转成基本数值类型。

2)案例实操

(1)基本类型转String类型(语法:将基本类型的值+“” 即可)

(2)String类型转基本数值类型(语法:s1.toInt、s1.toFloat、s1.toDouble、s1.toByte、s1.toLong、s1.toShort)


     
     
       
       
       
       
  1. object TestStringTransfer {
  2. def main(args: Array[ String]): Unit = {
  3. //(1)基本类型转String类型(语法:将基本类型的值+"" 即可)
  4. var str1: String = true + "你kin"
  5. println(str1)
  6. var str2: String = 4.444 + "拜拜"
  7. println(str2)
  8. var str3: String = 4444 + ""
  9. println(str3)
  10. //(2)String类型转基本数值类型(语法:调用相关API)
  11. var s1: String = "11"
  12. var n1: Byte = s1.toByte
  13. var n2: Short = s1.toShort
  14. var n3: Int = s1.toInt
  15. var n4: Long = s1.toLong
  16. println(s1)
  17. println(n1)
  18. println(n2)
  19. println(n3)
  20. println(n4)
  21. }
  22. }

(3)注意事项

在将String类型转成基本数值类型时,要确保String类型能够转成有效的数据,比如我们可以把"123",转成一个整数,但是不能把"hello"转成一个整数。

var n5:Int = “12.6”.toInt会出现NumberFormatException异常。

2.13 字符串String

Scala中本身没有String数据类型,字符串本质上是Java String。和Java String 一样,String是一个不可变对象,该对象不可修改。

三、运算符

Scala运算符的使用和Java运算符的使用基本相同,只有个别细节上不同。

3.1 算术运算符

1)基本语法

运算符

运算

范例

结果

+

正号

+3

3

-

负号

b=4; -b

-4

+

5+5

10

-

6-4

2

*

3*4

12

/

5/5

1

%

取模(取余)

7%5

2

+

字符串相加

“He”+”llo”

“Hello”

(1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。

(2)对一个数取模a%b,和Java的取模规则一样。

2)案例实操


     
     
       
       
       
       
  1. object TestArithmetic {
  2. def main(args: Array[ String]): Unit = {
  3. // 1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
  4. var r1: Int = 10 / 3
  5. println(r1) //3
  6. var r2: Double = 10 / 3
  7. println(r2) //3.0
  8. var r3: Double = 10.0 / 3
  9. println(r3) //3.3333333333333335
  10. println(r3.formatted( "%.2f")) //3.33 含义:保留小数点2位,使用四舍五入
  11. //(2)对一个数取模a%b,和Java的取模规则一样。
  12. var r4 = 10 % 3
  13. println(r4) //1
  14. }
  15. }

3.2 关系运算符(比较运算符)

1)基本语法

运算符

运算

范例

结果

==

相等于

4==3

false

!=

不等于

4!=3

true

<

小于

4<3

false

>

大于

4>3

true

<=

小于等于

4<=3

false

>=

大于等于

4>=3

true

2)案例实操

(1)需求1:


     
     
       
       
       
       
  1. object TestRelation {
  2. def main(args: Array[ String]): Unit = {
  3. // 测试:>、>=、<=、<、==、!=
  4. var a: Int = 2
  5. var b: Int = 1
  6. println(a > b) // true
  7. println(a >= b) // true
  8. println(a < b) // false
  9. println(a <= b) // false
  10. println( "a==b" + (a == b)) // false
  11. println(a != b) // true
  12. }
  13. }

(2)需求2:Java和Scala中关于==的区别

Java:==比较两个变量本身的值,即两个对象在内存中的首地址;equals比较字符串中所包含的内容是否相同。


     
     
       
       
       
       
  1. public class TestRelation2 {
  2. public static void main( String[] args) {
  3. String s1 = "hhhh";
  4. String s2 = new String( "hhhh");
  5. System.out.println(s1 == s2); // false
  6. System.out.println(s1.equals(s2)); // true
  7. }
  8. }

Scala:==更加类似于Java中的equals,参照jd工具


     
     
       
       
       
       
  1. object TestRelationScala {
  2. def main(args: Array[ String]): Unit = {
  3. val s1 = "aaa"
  4. val s2 = new String( "aaa")
  5. println(s1 == s2) // true
  6. println(s1.eq(s2)) // false
  7. }
  8. }

3.3 逻辑运算符

1)基本语法

用于连接多个条件(一般来讲就是关系表达式),最终的结果也是一个Boolean值。

假定:变量A为true,B为false

运算符

描述

实例

&&

逻辑与

(A && B) 运算结果为 false

||

逻辑或

(A || B) 运算结果为 true

!

逻辑非

!(A && B) 运算结果为 true

2)案例实操


     
     
       
       
       
       
  1. object TestLogic {
  2. def main(args: Array[ String]): Unit = {
  3. // 测试:&&、||、!
  4. var a = true
  5. var b = false
  6. println( "a&&b=" + (a && b)) // a&&b=false
  7. println( "a || b =" + (a || b)) // a || b =true
  8. println( "!(a&&b)" + (!(a && b))) // !(a&&b)true
  9. }
  10. }

3.4 赋值运算符

1)基本语法

赋值运算符就是将某个运算后的值,赋给指定的变量。

运算符

描述

实例

=

简单的赋值运算符,将一个表达式的值赋给一个左值

C = A + B 将 A + B 表达式结果赋值给 C

+=

相加后再赋值

C += A 等于 C = C + A

-=

相减后再赋值

C -= A 等于 C = C - A

*=

相乘后再赋值

C *= A 等于 C = C * A

/=

相除后再赋值

C /= A 等于 C = C / A

%=

求余后再赋值

C %= A 等于 C = C % A

<<=

左移后赋值

C <<= 2等于 C = C << 2

>>=

右移后赋值

C >>= 2 等于 C = C >> 2

&=

按位与后赋值

C &= 2 等于 C = C & 2

^=

按位异或后赋值

C ^= 2 等于 C = C ^ 2

|=

按位或后赋值

C |= 2 等于 C = C | 2

注意:Scala中没有++、–操作符,可以通过+=、-=来实现同样的效果;

2)案例实操


     
     
       
       
       
       
  1. object TestAssignment {
  2. def main(args: Array[ String]): Unit = {
  3. var r1 = 11
  4. // 没有++
  5. r1 += 1 //12
  6. println(r1)
  7. // 没有--
  8. r1 -= 2 //10
  9. println(r1)
  10. }
  11. }

3.5 位运算符

1)基本语法

下表中变量 a 为 60,b 为 13。

运算符

描述

实例

&

按位与运算符

(a & b) 输出结果 12 ,二进制解释: 0000 1100

|

按位或运算符

(a | b) 输出结果 61 ,二进制解释: 0011 1101

^

按位异或运算符

(a ^ b) 输出结果 49 ,二进制解释: 0011 0001

~

按位取反运算符

(~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。

<<

左移动运算符

a << 2 输出结果 240 ,二进制解释: 0011 0000

>>

右移动运算符

a >> 2 输出结果 15 ,二进制解释: 0000 1111

>>>

无符号右移

a >>>2 输出结果 15, 二进制解释: 0000 1111

2)案例实操


     
     
       
       
       
       
  1. object TestPositon {
  2. def main(args: Array[ String]): Unit = {
  3. // 测试:1000 << 1 =>10000
  4. var n1: Int = 8
  5. n1 = n1 << 1
  6. println(n1) // 16
  7. }
  8. }

3.6 Scala运算符本质

在Scala中其实是没有运算符的,所有运算符都是方法

1)当调用对象的方法时,点.可以省略

2)如果函数参数只有一个,或者没有参数,()可以省略


     
     
       
       
       
       
  1. object TestOpt {
  2. def main(args: Array[ String]): Unit = {
  3. // 标准的加法运算
  4. val i: Int = 1.+( 1)
  5. // (1)当调用对象的方法时,.可以省略
  6. val j: Int = 1 + ( 1)
  7. // (2)如果函数参数只有一个,或者没有参数,()可以省略
  8. val k: Int = 1 + 1
  9. println( 1.toString())
  10. println( 1 toString())
  11. println( 1 toString)
  12. }
  13. }

四、流程控制

4.1 分支控制if-else

让程序有选择的的执行,分支控制有三种:单分支、双分支、多分支

4.1.1 单分支

1)基本语法

if (条件表达式) {
执行代码块
}

说明:当条件表达式为ture时,就会执行{ }的代码。

2)案例实操

需求:输入人的年龄,如果该同志的年龄小于18岁,则输出“童年”


     
     
       
       
       
       
  1. if (age < 18){
  2.     println( "童年")
  3. }

4.1.2 双分支

1)基本语法

if (条件表达式) {
执行代码块1
} else {
执行代码块2
}

2)案例实操

需求:输入年龄,如果年龄小于18岁,则输出“童年”。否则,输出“成年”。


     
     
       
       
       
       
  1. if (age < 18) {
  2.     println( "童年")
  3. } else {
  4.     println( "成年")
  5. }

4.1.3 多分支

1)基本语法

if (条件表达式1) {
执行代码块1
}
else if (条件表达式2) {
执行代码块2
}
……
else {
执行代码块n
}

2)案例实操

(1)需求1:需求:输入年龄,如果年龄小于18岁,则输出“童年”。如果年龄大于等于18且小于等于30,则输出“中年”,否则,输出“老年”。


     
     
       
       
       
       
  1. if (age < 18) {
  2.     println( "童年")
  3. } else if (age >= 18 && age < 30) {
  4.     println( "中年")
  5. } else {
  6.     println( "老年")
  7. }

(2)需求2:Scala中if else表达式其实是有返回值的,具体返回值取决于满足条件的代码体的最后一行内容。


     
     
       
       
       
       
  1. val res : String = if (age < 18) {
  2.     "童年"
  3. } else if (age >= 18 && age < 30) {
  4.     "中年"
  5. } else {
  6.     "老年"
  7. }
  8. println(res)

(3)需求3:Scala中返回值类型不一致,取它们共同的祖先类型。


     
     
       
       
       
       
  1. val res : Any = if (age < 18) {
  2.     "童年"
  3. } else if (age >= 18 && age < 30) {
  4.     "中年"
  5. } else {
  6.     100
  7. }
  8. println(res)

(4)需求4:Java中的三元运算符可以用if else实现

如果大括号{}内的逻辑代码只有一行,大括号可以省略。如果省略大括号,if只对最近的一行逻辑代码起作用。


     
     
       
       
       
       
  1. // Java中三元运算符:a?b:c
  2. // 如:int result = flag ? 1 : 0
  3. // Scala
  4. val res:String = if(age>= 18) "成年" else "未成年"
  5. println(res)

4.2 嵌套分支

在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层。分支外面的分支结构称为外层分支。嵌套分支不要超过3层。

1)基本语法

if(){
if(){
}else{
}
}

2)案例实操

需求:如果输入的年龄小于18,返回“童年”。如果输入的年龄大于等于18,需要再判断:如果年龄大于等于18且小于30,返回“中年”;如果其他,返回“老年”。


     
     
       
       
       
       
  1. import scala.io.StdIn
  2. object TestIfElse {
  3. def main (args: Array[String]): Unit = {
  4. // Scala
  5. println( "input age:")
  6. var age = StdIn.readShort()
  7. val res: Any = if (age < 18) {
  8. "童年"
  9. } else {
  10. if (age >= 18 && age < 30) {
  11. "中年"
  12. } else {
  13. "老年"
  14. }
  15. }
  16. println(res)
  17. }
  18. }

4.3 Switch分支结构

在Scala中没有Switch,而是使用模式匹配来处理。

模式匹配涉及到的知识点较为综合,因此我们放在后面讲解。

4.4 For循环控制

Scala也为for循环这一常见的控制结构提供了非常多的特性,这些for循环的特性被称为for推导式或for表达式。

4.4.1 范围数据循环(To)

1)基本语法


     
     
       
       
       
       
  1. // java for循环语法
  2. for(int i = 0; i < 10; i++){
  3.     System.out.println( "i=" + i);
  4. }
  5. // scala for循环语法
  6. for(i <- 1 to 10){
  7.     println( "i=" + i)
  8. }
  9. // 输出:从1~10(包含 1 和 10 )

(1)i 表示循环的变量,<- 规定to

(2)i 将会从 1-3 循环,前后闭合

4.4.2 范围数据循环(Until)

1)基本语法


     
     
       
       
       
       
  1. // 方法一:
  2. for(i <- 1 until 10) {
  3. print( "i=" + i)
  4. }
  5. // 输出:从1~10(包含 1,不包含 10 )
  6. // 方法二:
  7. for(i <- Range( 1, 10)) {
  8. print( "i=" + i)
  9. }

(1)这种方式和前面的区别在于i是从1到3-1

(2)即使前闭合后开的范围

4.4.3 循环守卫

1)基本语法


     
     
       
       
       
       
  1. for(i <- 1 to 3 if i != 2) {
  2. print(i + " ")
  3. }

说明

(1)循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为true则进入循环体内部,为false则跳过,类似于continue。

(2)上面的代码等价


     
     
       
       
       
       
  1. for (i <- 1 to 3){
  2.     if (i != 2) {
  3. print(i + " ")
  4. }
  5. }

4.4.4 循环步长by

1)基本语法


     
     
       
       
       
       
  1. for (i <- 1 to 10 by 2) {
  2. println(“i=” + i)
  3. }

说明:by表示步长

2)案例实操

需求:输出1到10以内的所有奇数


     
     
       
       
       
       
  1. for (i <- 1 to 10 by 2) {
  2. println(“i=” + i)
  3. }
  4. 输出结果
  5. i= 1
  6. i= 3
  7. i= 5
  8. i= 7
  9. i= 9

4.4.5 嵌套循环

1)基本语法


     
     
       
       
       
       
  1. for(i <- 1 to 3; j <- 1 to 3) {
  2.     println( " i =" + i + " j = " + j)
  3. }

说明:没有关键字,所以范围后一定要加;来隔断逻辑

2)基本语法

上面的代码等价


     
     
       
       
       
       
  1. for (i <- 1 to 3) {
  2.     for (j <- 1 to 3) {
  3.         println(“i =” + i + " j=" + j)
  4.     }
  5. }

4.4.6 引入变量

1)基本语法


     
     
       
       
       
       
  1. for(i <- 1 to 3; j = 4 - i) {
  2. println( "i=" + i + " j=" + j)
  3. }

说明:

(1)for推导式一行中有多个表达式时,所以要加 ; 来隔断逻辑

(2)for推导式有一个不成文的约定:当for推导式仅包含单一表达式时使用圆括号,当包含多个表达式时,一般每行一个表达式,并用花括号代替圆括号,如下:


     
     
       
       
       
       
  1. for {
  2.     i <- 1 to 3
  3.     j = 4 - i
  4. } {
  5.     println(“i=” + i + " j=" + j)
  6. }

2)案例实操

上面的代码等价于


     
     
       
       
       
       
  1. for (i <- 1 to 3) {
  2.     var j = 4 - i
  3.     println(“i=” + i + " j=" + j)
  4. }

4.4.7 循环返回值

1)基本语法


     
     
       
       
       
       
  1. val res = for(i <- 1 to 10) yield i
  2. println(res)

说明:将遍历过程中处理的结果返回到一个新Vector集合中,使用yield关键字

注意:开发中很少使用。

2)案例实操

需求:将原数据中所有值乘以2,并把数据返回到一个新的集合中。


     
     
       
       
       
       
  1. var res = for(i < -1 to 10) yield {
  2. i * 2
  3. }
  4. println(res)

输出结果:

Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

4.4.8 倒序打印

1)说明:如果想倒序打印一组数据,可以用reverse。

2)案例实操:

需求:倒序打印10到1


     
     
       
       
       
       
  1. for(i <- 1 to 10 reverse){
  2. println(i)
  3. }

4.5 While和do…While循环控制

While和do…While的使用和Java语言中用法相同。

4.5.1 While循环控制

1)基本语法


     
     
       
       
       
       
  1. 循环变量初始化
  2. while (循环条件) {
  3. 循环体(语句)
  4. 循环变量迭代
  5. }

说明:

(1)循环条件是返回一个布尔值的表达式

(2)while循环是先判断再执行语句

(3)与for语句不同,while语句没有返回值,即整个while语句的结果是Unit类型()

(4)因为while中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免的使用变量,而变量需要声明在while循环的外部,那么就等同于循环的内部对外部的变量造成了影响,所以不推荐使用,而是推荐使用for循环


     
     
       
       
       
       
  1. object For01 {
  2. def main(args: Array[ String]): Unit = {
  3. // 1.范围循环 To
  4. for (i <- 1 to 3)
  5. println( "生如")
  6. println( "to----------------------")
  7. // 2.范围循环 Unit
  8. for (i <- 1 until 3)
  9. println( "夏花")
  10. println( "until----------------------")
  11. // 3.循环守卫
  12. for (i <- 1 to 6) {
  13. if (i != 2) {
  14. println(i)
  15. }
  16. }
  17. println( "!=----------------------")
  18. // 4.循环步长 by
  19. for (i <- 1 to 6 by 2)
  20. println(i)
  21. println( "by----------------------")
  22. for (i <- -10 to -1 by 2)
  23. println(i)
  24. println( "by----------------------")
  25. // 5.循环嵌套
  26. for (i <- 1 to 4; j <- 1 to 6) {
  27. print( "i=" + i + ",j=" + j + "\t")
  28. if (j == 6)
  29. println()
  30. }
  31. println( "嵌套----------------------")
  32. // 6.引入变量
  33. for (i <- 1 to 10; j = 10 - i) {
  34. println( "i=" + i + ",j=" + j)
  35. }
  36. println( "引入变量----------------------")
  37. for {
  38. i <- 1 to 3
  39. j = 3 - i
  40. } {
  41. println( "i=" + i + ",j=" + j)
  42. }
  43. println( "引入变量----------------------")
  44. // 7.循环返回值
  45. val res = for (i <- 1 to 10) yield i
  46. println(res)
  47. println( "----------------------")
  48. //需求:将原数据中所有值乘以2,并把数据返回到一个新的集合中。
  49. var res1 = for (i <- 1 to 10) yield {
  50. i * 2
  51. }
  52. println(res1)
  53. println( "循环返回值----------------------")
  54. // 8.倒序打印
  55. for (i <- 1 to 10 reverse) {
  56. println(i)
  57. }
  58. println( "倒序----------------------")
  59. }
  60. }

4.5.2 do…while循环控制

1)基本语法


     
     
       
       
       
       
  1. 循环变量初始化;
  2. do{
  3. 循环体(语句)
  4. 循环变量迭代
  5. } while(循环条件)

说明

(1)循环条件是返回一个布尔值的表达式

(2)do…while循环是先执行,再判断

4.6 循环中断

1)基本说明

Scala内置控制结构特地去掉了break和continue,是为了更好的适应函数式编程,推荐使用函数式的风格解决break和continue的功能,而不是一个关键字。Scala中使用breakable控制结构来实现break和continue功能。

2)案例实操

需求1:采用异常的方式退出循环


     
     
       
       
       
       
  1. // 1.正常结束循环
  2. try {
  3. for (elem <- 1 to 10) {
  4. println(elem)
  5. if (elem == 5) throw new RuntimeException
  6. }
  7. } catch {
  8. case e =>
  9. }
  10. println( "正常结束循环")
  11. }

需求2:采用Scala自带的函数,退出循环


     
     
       
       
       
       
  1. // 2.采用scala自带的函数,退出循环
  2. Breaks.breakable(
  3.     for (e <- 1 to 5) {

你可能感兴趣的:(BigData_Study,scala,学习,笔记)