Scala笔记

Scala第一章节

章节目标

  1. 理解Scala的相关概述
  2. 掌握Scala的环境搭建
  3. 掌握Scala小案例: 做最好的自己

1. Scala简介

1.1 概述

​ Scala(斯嘎拉)这个名字来源于"Scalable Language(可伸缩的语言)", 它是一门基于JVM的多范式编程语言, 通俗的说: Scala是一种运行在JVM上的函数式的面向对象语言. 它集成了面向对象编程和面向函数式编程的各种特性, 以及更高层的并发模型.

​ 总而言之, Scala融汇了许多前所未有的特性, 而同时又运行于JVM之上
基于JVM解释:Scala的运行环境和Java类似, 也是依赖JVM的.

多范式解释: Scala支持多种编程风格

1.2 Scala之父

Scala之父是: Martin·Odersky(马丁·奥德斯基), 他在整个职业生涯中一直不断追求着一个目标:让写程序这样一个基础工作变得高效、简单、且令人愉悦

在这里插入图片描述

1.3 语言特点
  • Scala的兼容性

    兼容Java,可以访问庞大的Java类库,例如:操作mysql、redis、freemarker、activemq等等

  • Scala的精简性

    Scala表达能力强,一行代码抵得上多行Java代码,开发速度快

  • Scala的高级性

    Scala可以让你的程序保持短小, 清晰, 看起来更简洁, 更优雅

  • Scala的静态类型

    Scala拥有非常先进的静态类型系统, 支持: 类型推断和模式匹配等

  • Scala可以开发大数据应用程序

    例如: Spark程序、Flink程序等等...

2. Scala程序和Java程序对比

2.1 程序的执行流程对比

Java程序编译执行流程
在这里插入图片描述
Scala程序编译执行流程

在这里插入图片描述

2.2 代码对比

**需求: **

​ 定义一个学生类, 属性为: 姓名和年龄, 然后在测试类中创建对象并测试.

Java代码

//定义学生类
public class Student{
   
    private String name;		//姓名
    private int age;			//年龄
    
    //空参和全参构造
    public Student(){
   }
    
    public Student(String name, int age){
   
        this.name = name;
        this.age = age;
    }
    
    //getXxx()和setXxx()方法
    public String getName() {
   
        return name;
    }
    public void setName(String name) {
   
        this.name = name;
    }
    public int getAge() {
   
        return age;
    }
    public void setAge(int age) {
   
        this.age = age;
    }
}

//测试类
public class StudentDemo {
   
     public static void main(String[] args) {
   
        Student s1 = new Student("张三", 23);	//创建Student类型的对象s1, 并赋值
        System.out.println(s1);				 //打印对象, 查看结果.
    }
}

Scala代码

case class Student(var name:String, var age:Int)		//定义一个Student样例类
val s1 = Student("张三", 23)							  //创建Student类型的对象s1, 并赋值
println(s1)											   //打印对象, 查看结果.

3. Scala环境搭建

3.1 概述

scala程序运行需要依赖于Java类库,那么必须要有Java运行环境,scala才能正确执行. 所以要编译运行scala程序,需要:

  • JDK(JDK包含JVM)
  • Scala编译器(Scala SDK)

接下来,需要依次安装以下内容:

  • 安装JDK
  • 安装Scala SDK
  • 在IDEA中安装Scala插件
3.2 安装JDK

安装JDK 1.8 64位版本

3.3 安装Scala SDK

Scala SDK是scala语言的编译器,要开发scala程序,必须要先安装Scala SDK

步骤

  1. 下载Scala SDK.

    官方下载地址: scala-lang.org/download/

  2. 安装Scala SDK.

    2.1 双击scala-xxxx.msi,将scala安装在指定目录, 傻瓜式安装, 下一步下一步即可.
    2.2 安装路径要合法, 不要出现中文, 空格等特殊符号.

  3. 测试是否安装成功

    打开控制台,输入: scala -version

3.4 安装IDEA scala插件

IDEA默认是不支持scala程序开发的,所以需要在IDEA中安装scala插件, 让它来支持scala语言。

4. Scala解释器

4.1 概述

scala解释器像Linux命令一样,执行一条代码,马上就可以让我们看到执行结果,用来测试比较方便。

我们接下来学习:

  • 启动scala解释器
  • 在scala解释器中执行scala代码
  • 退出scala解释器
4.2 启动scala解释器

要启动scala解释器,只需要以下几步:

  • 按住windows键 + r
  • 输入scala即可
4.3 执行scala代码

在scala的命令提示窗口中输入println("hello, world"),回车执行

4.4 退出解释器

方式一: 点击右上角的"×"

方式二: 输入:quit退出

5. 案例: 做最好的自己.

5.1 需求

​ 提示用户录入他/她最想对自己说的一句话, 然后将这句话打印到控制台上.

5.2 目的

​ 测试Scala和Java之间可以无缝互调(即: Scala兼容Java,可以访问庞大的Java类库).

5.3 思路分析
1. 因为涉及到键盘录入了, 所以先导包.
2. 提示用户录入他/她最想对自己说的一句话.
3. 接收用户录入的内容, 并打印.
5.4 参考代码
//1. 导入Java中的Scanner类.							引入Java类库
import java.util.Scanner
//2. 提示用户录入他/她最想对自己说的一句话.			   Scala代码
println("请录入一句您最想对自己说的一句话: ")
//3. 打印用户录入的内容.								 Scala代码 + Java类库
//不忘初心, 方得始终, 做最好的自己!
println("我最想对自己说: " + new Scanner(System.in).nextLine())

Scala第二章节

章节目标

  1. 掌握变量, 字符串的定义和使用
  2. 掌握数据类型的划分和数据类型转换的内容
  3. 掌握键盘录入功能
  4. 理解Scala中的常量, 标识符相关内容

1. 输出语句和分号

1.1 输出语句

方式一: 换行输出

格式:  println(里边写你要打印到控制台的数据);

方式二: 不换行输出

格式: print(里边写你要打印到控制台的数据);

注意: 不管是println(), 还是print()语句, 都可以同时打印多个值.格式为: println(值1, 值2, 值3...)

1.2 分号

Scala语句中, 单行代码最后的分号可写可不写. 如果是多行代码写在一行, 则中间的分号不能省略, 最后一条代码的分号可省略不写.

示例:

println("Hello, Scala!")			//最后的分号可写可不写
//如果多行代码写在一行, 则前边语句的分号必须写, 最后一条语句的分号可以省略不写.
println("Hello"); println("Scala")	

2. Scala中的常量

2.1 概述

常量指的是: 在程序的运行过程中, 其值不能发生改变的量.

2.2 分类
  • 字面值常量(常用的有以下几种)
    • 整型常量
    • 浮点型常量
    • 字符常量
    • 字符串常量
    • 布尔常量
    • 空常量
  • 自定义常量(稍后解释)
2.3 代码演示
//整型常量
println(10)
//浮点型常量
println(10.3)
//字符常量, 值要用单引号括起来
println('a')
//字符串常量, 值要用双引号括起来
println("abc")
//布尔常量, 值只有true和false
println(true)
//空常量
println(null)

3. Scala中的变量

3.1 概述

我们将来每一天编写scala程序都会定义变量, 那什么是变量, 它又是如何定义的呢?

变量, 指的就是在程序的执行过程中, 其值可以发生改变的量. 定义格式如下:

3.2 语法格式

Java变量定义

int a = 0;

在scala中,可以使用val或者var来定义变量,语法格式如下:

val/var 变量名:变量类型 = 初始值

其中

  • val定义的是不可重新赋值的变量, 也就是自定义常量.
  • var定义的是可重新赋值的变量

注意: scala中定义变量时, 类型写在变量名后面

3.3 示例

需求: 定义一个变量保存一个人的名字"tom"

步骤

  1. 打开scala解释器
  2. 定义一个字符串类型的变量用来保存名字

参考代码

scala> val name:String = "tom"
name: String = tom
3.4 val和var变量的区别

示例

给名字变量进行重新赋值为Jim,观察其运行结果

参考代码

scala> name = "Jim"
<console>:12: error: reassignment to val
       name = "Jim"

示例

使用var重新定义变量来保存名字"tom",并尝试重新赋值为Jim,观察其运行结果

参考代码

scala> var name:String = "tom"
name: String = tom

scala> name = "Jim"
name: String = Jim

注意: 优先使用val定义变量,如果变量需要被重新赋值,才使用var

3.5 使用类型推断来定义变量

scala的语法要比Java简洁,我们可以使用一种更简洁的方式来定义变量。

示例

使用更简洁的语法定义一个变量保存一个人的名字"tom"

参考代码

scala> val name = "tom"
name: String = tom

scala可以自动根据变量的值来自动推断变量的类型,这样编写代码更加简洁。

4. 字符串

scala提供多种定义字符串的方式,将来我们可以根据需要来选择最方便的定义方式。

  • 使用双引号
  • 使用插值表达式
  • 使用三引号
4.1 使用双引号

语法

val/var 变量名 = “字符串”

示例

有一个人的名字叫"hadoop",请打印他的名字以及名字的长度。

参考代码

scala> println(name + name.length)
hadoop6
4.2 使用插值表达式

scala中,可以使用插值表达式来定义字符串,有效避免大量字符串的拼接。

语法

val/var 变量名 = s"${变量/表达式}字符串"

注意:

  • 在定义字符串之前添加s
  • 在字符串中,可以使用${}来引用变量或者编写表达式

示例

请定义若干个变量,分别保存:“zhangsan”、23、“male”,定义一个字符串,保存这些信息。

打印输出:name=zhangsan, age=23, sex=male

参考代码

scala> val name = "zhangsan"
name: String = zhangsan

scala> val age = 23
age: Int = 23

scala> val sex = "male"
sex: String = male

scala> val result = s"name=${name}, age=${age}, sex=${sex}"
result: String = name=zhangsan, age=23, sex=male

scala> println(result)
name=zhangsan, age=23, sex=male
4.3 使用三引号

如果有大段的文本需要保存,就可以使用三引号来定义字符串。例如:保存一大段的SQL语句。三个引号中间的所有内容都将作为字符串的值。

语法

val/var 变量名 = """字符串1
字符串2"""

示例

定义一个字符串,保存以下SQL语句

select
	*
from
    t_user
where
    name = "zhangsan"

打印该SQL语句

参考代码

val sql = """select
     | *
     | from
     |     t_user
     | where
     |     name = "zhangsan""""

println(sql)
4.4 扩展: 惰性赋值

在企业的大数据开发中,有时候会编写非常复杂的SQL语句,这些SQL语句可能有几百行甚至上千行。这些SQL语句,如果直接加载到JVM中,会有很大的内存开销, 如何解决这个问题呢?

当有一些变量保存的数据较大时,而这些数据又不需要马上加载到JVM内存中。就可以使用惰性赋值来提高效率。

语法格式:

lazy val/var 变量名 = 表达式

示例

在程序中需要执行一条以下复杂的SQL语句,我们希望只有用到这个SQL语句才加载它。

"""insert overwrite table adm.itcast_adm_personas
    select
    a.user_id,
    a.user_name,
    a.user_sex,
    a.user_birthday,
    a.user_age,
    a.constellation,
    a.province,
    a.city,
    a.city_level,
    a.hex_mail,
    a.op_mail,
    a.hex_phone,
    a.fore_phone,
    a.figure_model,
    a.stature_model,
    b.first_order_time,
    b.last_order_time,
      ...
    d.month1_hour025_cnt,
    d.month1_hour627_cnt,
    d.month1_hour829_cnt,
    d.month1_hour10212_cnt,
    d.month1_hour13214_cnt,
    d.month1_hour15217_cnt,
    d.month1_hour18219_cnt,
    d.month1_hour20221_cnt,
    d.month1_hour22223_cnt
    from gdm.itcast_gdm_user_basic a
      left join gdm.itcast_gdm_user_consume_order b on a.user_id=b.user_id
    left join gdm.itcast_gdm_user_buy_category c on a.user_id=c.user_id
    left join gdm.itcast_gdm_user_visit d on a.user_id=d.user_id;"""

参考代码

scala> lazy val sql = """insert overwrite table adm.itcast_adm_personas
     |     select
     |     a.user_id,
	....
     |     left join gdm.itcast_gdm_user_buy_category c on a.user_id=c.user_id
     |     left join gdm.itcast_gdm_user_visit d on a.user_id=d.user_id;"""
sql: String = <lazy>

5. 标识符

5.1 概述

​ 实际开发中, 我们会编写大量的代码, 这些代码中肯定会有变量, 方法, 类等. 那它们该如何命名呢? 这就需要用到标识符了. 标识符就是用来给变量, 方法, 类等起名字的. Scala中的标识符和Java中的标识符非常相似.

5.2 命名规则
  • 必须由大小写英文字母, 数字, 下划线_, 美元符$, 这四部分任意组合组成.
  • 数字不能开头.
  • 不能和Scala中的关键字重名.
  • 最好做到见名知意.
5.3 命名规范
  • 变量或方法: 从第二个单词开始, 每个单词的首字母都大写, 其他字母全部小写(小驼峰命名法).

    zhangSanAge, student_Country, getSum
    
  • 类或特质(Trait): 每个单词的首字母都大写, 其他所有字母全部小写(大驼峰命名法)

    Person, StudentDemo, OrderItems
    
  • 包: 全部小写, 一般是公司的域名反写, 多级包之间用.隔开.

    com.itheima.add,  cn.itcast.update
    

6. 数据类型

6.1 简述

数据类型是用来约束变量(常量)的取值范围的. Scala也是一门强类型语言, 它里边的数据类型绝大多数和Java一样.我们主要来学习

  • 与Java不一样的一些用法
  • scala中数据类型的继承体系
6.2 数据类型
基础类型 类型说明
Byte 8位带符号整数
Short 16位带符号整数
Int 32位带符号整数
Long 64位带符号整数
Char 16位无符号Unicode字符
String Char类型的序列(字符串)
Float 32位单精度浮点数
Double 64位双精度浮点数
Boolean true或false

注意下 scala类型与Java的区别

[!NOTE]

  1. scala中所有的类型都使用大写字母开头
  2. 整形使用Int而不是Integer
  3. scala中定义变量可以不写类型,让scala编译器自动推断
  4. Scala中默认的整型是Int, 默认的浮点型是: Double
6.3 Scala类型层次结构

在这里插入图片描述

类型 说明
Any 所有类型的父类,它有两个子类AnyRef与AnyVal
AnyVal 所有数值类型的父类
AnyRef **所有对象类型(引用类型)**的父类
Unit 表示空,Unit是AnyVal的子类,它只有一个的实例{% em %}() {% endem %} 它类似于Java中的void,但scala要比Java更加面向对象
Null Null是AnyRef的子类,也就是说它是所有引用类型的子类。它的实例是{% em %}null{% endem %} 可以将null赋值给任何对象类型
Nothing 所有类型的子类, 不能直接创建该类型实例,某个方法抛出异常时,返回的就是Nothing类型,因为Nothing是所有类的子类,那么它可以赋值为任何类型
6.4 思考题

以下代码是否有问题?

val b:Int = null

Scala会解释报错: Null类型并不能转换为Int类型,说明Null类型并不是Int类型的子类

7. 类型转换

7.1 概述

当Scala程序在进行运算或者赋值动作时, 范围小的数据类型值会自动转换为范围大的数据类型值, 然后再进行计算.例如: 1 + 1.1的运算结果就是一个Double类型的2.1. 而有些时候, 我们会涉及到一些类似于"四舍五入"的动作, 要把一个小数转换成整数再来计算. 这些内容就是Scala中的类型转换.

Scala中的类型转换分为值类型的类型转换引用类型的类型转换, 这里我们先重点介绍:值类型的类型转换.

值类型的类型转换分为:

  • 自动类型转换
  • 强制类型转换
7.2 自动类型转换
  1. 解释

    范围小的数据类型值会自动转换为范围大的数据类型值, 这个动作就叫: 自动类型转换.

    自动类型转换从小到大分别为:Byte, Short, Char -> Int -> Long -> Float -> Double

  2. 示例代码

    val a:Int = 3
    val b:Double = 3 + 2.21	//因为是int类型和double类型的值进行计算, 所以最终结果为: Double类型
    val c:Byte = a + 1	//这样写会报错, 因为最终计算结果是Int类型的数据, 将其赋值Byte类型肯定不行.
    
7.3 强制类型转换
  1. 解释

    范围大的数据类型值通过一定的格式(强制转换函数)可以将其转换成范围小的数据类型值, 这个动作就叫: 强制类型转换.

    注意: 使用强制类型转换的时候可能会造成精度缺失问题!

  2. 格式

val/var 变量名:数据类型 = 具体的值.toXxx		//Xxx表示你要转换到的数据类型
  1. 参考代码
val a:Double = 5.21
val b:Int = a.toInt
7.4 值类型和String类型之间的相互转换

1. 值类型的数据转换成String类型

格式一:

val/var 变量名:String = 值类型数据 + ""

格式二:

val/var 变量名:String = 值类型数据.toString

示例

将Int, Double, Boolean类型的数据转换成其对应的字符串形式.

参考代码:

val a1:Int = 10
val b1:Double = 2.1
val c1:Boolean = true

//方式一: 通过和空字符串拼接的形式实现
val a2:String = a1 + ""
val b2:String = b1 + ""
val c2:String = c1 + ""

//方式二: 通过toString函数实现
val a3:String = a1.toString
val b3:String = b1.toString
val c3:String = c1.toString

2. String类型的数据转换成其对应的值类型

格式:

val/var 变量名:值类型 = 字符串值.toXxx	//Xxx表示你要转换到的数据类型

注意:

  • String类型的数据转成Char类型的数据, 方式有点特殊, 并不是调用toChar, 而是toCharArray
  • 这点目前先了解即可, 后续我们详细解释

需求:

​ 将字符串类型的整数, 浮点数, 布尔数据转成其对应的值类型数据.

参考代码:

val s1:String = "100"
val s2:String = "2.3"
val s3:String = "false"

//将字符串类型的数据转成其对应的: Int类型
val a:Int = s1.toInt
//将字符串类型的数据转成其对应的: Double类型
val b:Double = s2.toDouble
//将字符串类型的数据转成其对应的: Boolean类型
val c:Boolean = s3.toBoolean

8. 键盘录入

8.1 概述

前边我们涉及到的数据, 都是我们写"死"的, 固定的数据, 这样做用户体验并不是特别好. 那如果这些数据是由用户录入, 然后我们通过代码接收, 就非常好玩儿了. 这就是接下来我们要学习的Scala中的"键盘录入"功能.

8.2 使用步骤
  1. 导包

    格式: import scala.io.StdIn

  2. 通过StdIn.readXxx()来接收用户键盘录入的数据

    接收字符串数据: StdIn.readLine()

    接收整数数据: StdIn.readInt()

8.3 示例
  • 提示用户录入字符串, 并接收打印.

    println("请录入一个字符串: ")
    val str = StdIn.readLine()
    println("您录入的字符串内容为: " + str)
    
  • 提示用户录入整数, 并接收打印.

    println("请录入一个整数: ")
    val num = StdIn.readInt()
    println("您录入的数字为: " + num)
    

9. 案例: 打招呼

9.1 概述

需求: 提示用户录入他/她的姓名和年龄, 接收并打印.

9.2 具体步骤
  1. 提示用户录入姓名.
  2. 接收用户录入的姓名.
  3. 提示用户录入年龄.
  4. 接收用户录入的年龄.
  5. 将用户录入的数据(姓名和年龄)打印到控制台上.
9.3 参考代码
//1. 提示用户录入姓名.
println("请录入您的姓名: ")
//2. 接收用户录入的姓名.
val name = StdIn.readLine()
//3. 提示用户录入年龄.
println("请录入您的年龄: ")
//4. 接收用户录入的年龄.
val age = StdIn.readInt()
//5. 将用户录入的数据(姓名和年龄)打印到控制台上.
println(s"大家好, 我叫${name}, 我今年${age}岁了, 很高兴和大家一起学习Scala!")

Scala第三章节

章节目标

  1. 理解运算符的相关概述
  2. 掌握算术, 赋值, 关系, 逻辑运算符的用法
  3. 掌握交换变量案例
  4. 理解位运算符的用法

1. 算术运算符

1.1 运算符简介

用来拼接变量或者常量的符号就叫: 运算符, 而通过运算符连接起来的式子就叫: 表达式. 实际开发中, 我们会经常用到它.

例如:

​ 10 + 3 这个就是一个表达式, 而+号, 就是一个运算符.

注意: 在Scala中, 运算符并不仅仅是运算符, 也是函数的一种

1.2 运算符的分类
  • 算术运算符

  • 赋值运算符

  • 关系运算符

  • 逻辑运算符

  • 位运算符

    注意: Scala中是没有三元运算符的, 被if-else给替代了.

1.3 算术运算符

算术运算符指的就是用来进行算术操作的符号, 常用的有以下几种:

运算符 功能解释
+ 加号, 功能有3点. 1) 表示正数 2) 普通的加法操作 3) 字符串的拼接
- 减号, 功能有2点. 1) 表示负数 2) 普通的减法操作
* 乘号, 用于获取两个数据的乘积
/ 除法, 用于获取两个数据的商
% 取余(也叫取模), 用于获取两个数据的余数

注意:

  1. Scala中是没有++, --这两个算术运算符的, 这点和Java中不同.

  2. 整数相除的结果, 还是整数. 如果想获取到小数, 则必须有浮点型数据参与.

    例如: 10 / 3 结果是3 10 / 3.0 结果是: 3.3333(无限循环)

  3. 关于+号拼接字符串: 任意类型的数据和字符串拼接, 结果都将是一个新的字符串.

  4. 关于%操作, 假设求a % b的值, 它的底层原理其实是: a - a/b * b

1.4 代码演示

需求: 演示算术运算符的常见操作.

参考代码:

//演示+号操作
println(+3)
println(10 + 3)
println("hello" + 10)

//演示-号操作
println(-5)
println(10 - 5)

//演示*号操作
println(5 * 3)

//演示/号操作
println(10 / 3)
println(10 / 3.0)

//演示%(取余)操作
println(10 % 3)     //结果是1, 具体运算过程: 10 - 10/3 * 3   = 10 - 3 * 3   = 1
println(10 % -3)    //结果是1, 具体运算过程: 10 - 10/-3 * -3 = 10 - -3 * -3 = 10 - 9  =  1
println(-10 % 3)   //结果是-1, 具体运算过程: -10 - -10/3 * 3 = -10 - -3 * 3 = -10 + 9 = -1 

2. 赋值运算符

2.1 概述

赋值运算符指的就是用来进行赋值操作的符号. 例如: 把一个常量值, 或者一个变量值甚至是某一段代码的执行结果赋值给变量, 这些都要用到赋值运算符.

2.2 分类
  • 赋值运算符常用的有两类

    • 基本赋值运算符

      =就是基本的赋值运算符, 例如: var a:Int = 3, 就是把常量值3赋值给变量a

    • 扩展赋值运算符

      +=, -=, *=, /=, %=

    注意:

    1. 赋值运算符的左边必须是: 变量, 不能是常量. 例如: 3 = 5, 这种写法就是错误的.

    2. 关于扩展赋值运算符, 其实就是把左边的数据和右边的数据进行指定的操作, 然后把结果赋值给左边.

      例如; a += 3 就是把变量a的值和常量3进行加法操作, 然后把结果赋值给变量a

2.3 代码演示
//将常量值1赋值给变量a
var a:Int = 1			//注意: 因为后续代码要修改变量a的值, 所以变量a要用var修饰
//对变量a进行加3操作, 然后把结果重新赋值给变量a
a += 3			//a的最终结果为: a = 4
//对变量a进行减2操作, 然后把结果重新赋值给变量a
a -= 2			//a的最终结果为: a = 2
//对变量a进行乘3操作, 然后把结果重新赋值给变量a
a *= 3			//a的最终结果为: a = 6
//对变量a进行除2操作, 然后把结果重新赋值给变量a
a /= 2			//a的最终结果为: a = 3
//对变量a和2进行取余操作, 然后把结果重新赋值给变量a
a %= 2			//a的最终结果为: a = 1

3. 关系运算符

3.1 概述

关系运算符指的就是用来进行比较操作的符号. 例如: 数据是否相等, 是否不等, 数据1大还是数据2大…等这些操作.

3.2 分类
运算符 功能解释
> 用来判断前边的数据是否大于后边的数据
>= 用来判断前边的数据是否大于或者等于后边的数据
< 用来判断前边的数据是否小于后边的数据
<= 用来判断前边的数据是否小于或者等于后边的数据
== 用来判断两个数据是否相等
!= 用来判断两个数据是否不等

注意:

  1. 关系表达式不管简单还是复杂, 最终结果一定是Boolean类型的值, 要么是true, 要么是false.
  2. 千万不要把==写成=, 否则结果可能不是你想要的.
3.3 代码演示
//定义两个Int类型的变量a, b, 分别赋值为3, 5
var a:Int = 3
var b:Int = 5
//判断a是否大于b, 并打印结果	
println(a > b)					//false
//判断a是否大于等于b, 并打印结果
println(a >= 3)					//true
//判断a是否小于b, 并打印结果
println(a < b)					//true
//判断a是否小于等于b, 并打印结果
println(a <= 3)					//true
//判断a和b是否不等, 并打印结果
println(a != b)					//true
//判断a和b是否相等, 并打印结果
println(a == b)					//false
//如果把==写成了=, 其实是把变量b的值赋值给变量a
println(a = b)					//输出结果是一对小括号"()", 即: 没有打印值.
println(a)						//再次打印变量a, 打印结果是:5
3.4 关系运算符延伸

与java不同的地方

需求描述 Scala代码 Java代码
比较数据值 == 或者 != equals()方法
比较引用值(地址值) eq方法 == 或者 !=

示例

有一个字符串"abc",再创建第二个字符串,值为:在第一个字符串后拼接一个空字符串。

然后使用比较这两个字符串是否相等、再查看它们的引用值是否相等。

参考代码

val s1 = "abc"
val s2 = s1 + ""
s1 == s2     //结果是: true,  因为比较的是 数据值
s1.eq(s2)	 //结果是: false, 因为比较的是 地址值

4. 逻辑运算符

4.1 概述

逻辑运算符指的就是用来进行逻辑操作的符号. 可以简单理解为它是: 组合判断. 例如: 判断多个条件是否都满足, 或者满足其中的某一个, 甚至还可以对某个判断结果进行取反操作.

4.2 分类
运算符 功能解释
&& 逻辑与, 要求所有条件都满足(即: 结果为true), 简单记忆: 有false则整体为false.
|| 逻辑或, 要求只要满足任意一个条件即可, 简单记忆: 有true则整体为true.
! 逻辑非, 用来进行取反操作的. 即: 以前为true, 取反后为false, 以前为false, 取反后为true.

注意:

  1. 逻辑表达式不管简单还是复杂, 最终结果一定是Boolean类型的值, 要么是true, 要么是false.
  2. 在Scala代码中, 不能对一个Boolean类型的数据进行连续取反操作, 但是在Java中是可以的.
    • 即: !!false, 这样写会报错, 不支持这种写法.
4.3 代码演示
//相当于: false && true
println(3 > 5 && 2 < 3)		//结果为: false
//我们可以简写代码为:
//逻辑与: 有false则整体为false.
println(false && true)		//结果为: false
println(true && false)		//结果为: false
println(false && false)		//结果为: false
println(true && true)		//结果为: true

println(false || true)		//结果为: true
println(true || false)		//结果为: true
println(false || false)		//结果为: false
println(true || true)		//结果为: true

println(!false)				//结果为: true
println(!true)				//结果为: false
println(!!true)				//这样写会报错, Scala不支持这种写法, 但是Java代码支持这种写法.

5. 位运算符

5.1 铺垫知识

要想学好位运算符, 你必须得知道三个知识点:

  1. 什么是进制
  2. 什么是8421码
  3. 整数的原码, 反码, 补码计算规则
5.1.1 关于进制

通俗的讲, 逢几进一就是几进制, 例如: 逢二进一就是二进制, 逢十进一就是十进制, 常用的进制有以下几种:

进制名称 数据组成规则 示例
二进制 数据以0b(大小写均可)开头, 由数字0和1组成 0b10001001, 0b00101010
八进制 数据以0开头, 由数字0~7组成 064, 011
十进制 数据直接写即可, 无特殊开头, 由数字0~9组成 10, 20, 333
十六进制 数据以0x(大小写均可)开头, 由数字0~9, 字母A-F组成(大小写均可) 0x123F, 0x66ABC

注意:

​ 关于二进制的数据, 最前边的那一位叫: 符号位, 0表示正数, 1表示负数. 其他位叫: 数值位.

​ 例如: 0b10001001 结果就是一个: 负数, 0b00101010 结果就是一个: 正数.

5.1.2 关于8421码

8421码就是用来描述二进制位和十进制数据之间的关系的, 它可以帮助我们快速的计算数据的二进制或十进制形式.

8421码对应关系如下:

二进制位 0 0 0 0 0 0 0 0

对应的十进制数据 128 64 32 16 8 4 2 1

注意:

  1. 计算规则: 二进制位从右往左数, 每多一位, 对应的十进制数据 乘以2.

  2. 二进制和十进制相互转换的小技巧:

    • 二进制转十进制: 获取该二进制位对应的十进制数据, 然后累加即可.
    • 例如: 0b101对应的十进制数据计算步骤: 4 + 0 + 1 = 5
    • 十进制转二进制: 对十进制数据进行拆解, 看哪些数字相加等于它, 然后标记成二进制即可.
      • 例如: 10 对应的二进制数据计算步骤: 10 = 8 + 2 = 0b1010
5.1.3 关于整数的原反补码计算规则

所谓的原反补码, 其实指的都是二进制数据, 把十进制的数据转成其对应的二进制数据, 该二进制数据即为: 原码.

注意: 计算机底层存储, 操作和运算数据, 都是采用数据的二进制补码形式来实现的.

  • 正数
    • 正数的原码, 反码, 补码都一样, 不需要特殊计算.
  • 负数
    • 负数的反码计算规则: 原码的符号位不变, 数值位按位取反(以前为0现在为1, 以前为1现在为0)
    • 负数的补码计算规则: 反码 + 1
5.2 概述

位运算符指的就是按照位(Bit)来快速操作数据值, 它只针对于整型数据. 因为计算机底层存储, 操作, 运算采用的都是数据的二进制补码形式, 且以后我们要经常和海量的数据打交道, 为了提高计算效率, 我们就可以使用位运算符来实现快速修改数据值的操作.

5.3 分类
运算符 功能解释
& 按位与, 规则: 有0则0, 都为1则为1.
| 按位或, 规则: 有1则1, 都为0则为0.
^ 按位异或, 规则: 相同为0, 不同为1.
~ 按位取反, 规则: 0变1, 1变0.
<< 按位左移, 规则: 每左移一位, 相当于该数据乘2, 例如: 2 << 1, 结果为4
>> 按位右移, 规则: 每右移一位, 相当于该数据除2, 例如: 6 >> 1, 结果为3

注意:

  1. 位运算符只针对于整型数据.
  2. 运算符操作的是数据的二进制补码形式.
  3. 小技巧: 一个数字被同一个数字位异或两次, 该数字值不变. 即: 10 ^ 20 ^ 20, 结果还是10
5.4 代码演示
//定义两个变量a和b, 初始化值分别为: 3, 5
val a = 3			//二进制数据: 0000 0011
val b = 5			//二进制数据: 0000 0101

//结果为: 0000 0001, 转化成十进制, 结果为: 1
println(a & b)		//打印结果为: 1

//结果为: 0000 0111, 转化成十进制, 结果为: 7
println(a | b)		//打印结果为: 7

//结果为: 0000 0110, 转换成十进制, 结果为: 6
println(a ^ b)		//打印结果为: 6

//计算流程: 1111 1100(补码) -> 1111 1011(反码) -> 1000 0100(原码) -> 十进制数据: -4
println(~ a)		//打印结果为: -4

//计算流程: 1000 0011(-3原码) -> 1111 1100(-3反码) -> 1111 1101(-3补码) -> 0000 0010(取反后新补码) -> 十进制数据: 2
println(~ -3)		//打印结果为: 2

//计算流程: 0000 0011(3的补码) -> 0000 1100(新的补码) -> 十进制数据: 12
println(a << 2)		//打印结果为: 12

//计算流程: 0000 0011(3的补码) -> 0000 0001(新的补码) -> 十进制数据: 1
println(a >> 1)		//打印结果为: 1

println(a ^ b ^ b)	//打印结果为: 3

6. 案例: 交换两个变量的值

6.1 需求

已知有两个Int类型的变量a和b, 初始化值分别为10和20, 请写代码实现变量a和变量b的值的交换.

即最终结果为: a=20, b=10.

注意: 不允许直接写a=20, b=10这种代码.

6.2 参考代码
  • 方式一: 通过算术运算符实现.

    //定义两个Int类型的变量a和b, 初始化值分别为10和20
    var a = 10
    var b = 20
    //将变量a和b的计算结果赋值给变量a
    a = a + b	//a = 30, b = 20
    //计算并赋值
    b = a - b	//a = 30, b = 10
    a = a - b	//a = 20, b = 10
    //打印结果
    println("a: " + a)		//a: 20
    println("b: " + b)		//b: 10
    
  • 方式二: 通过定义临时变量实现

    //定义两个Int类型的变量a和b, 初始化值分别为10和20
    var a = 10
    var b = 20
    //定义临时变量temp, 记录变量a的值
    var temp = a			//a = 10, b = 20, temp = 10
    //把变量b的值赋值给a
    a = b					//a = 20, b = 20, temp = 10
    //把临时变量temp的值赋值给b
    b = temp				//a = 20, b = 10, temp = 10
    //打印结果
    println("a: " + a)		//a: 20
    println("b: " + b)		//b: 10
    
  • 方式三: 通过位运算符实现

    //定义两个Int类型的变量a和b, 初始化值分别为10和20
    var a = 10
    var b = 20
    //定义临时变量temp, 记录变量a和b的位异或值(这个值不需要我们计算)
    var temp = a ^ b	//即: temp = 10 ^ 20
    //通过位异或进行交换变量值	
    a = a ^ temp		//运算流程:  = a ^ a ^ b = 10 ^ 10 ^ 20 = 20
    b = b ^ temp		//运算流程:  = b ^ a ^ b = 20 ^ 10 ^ 20 = 10
    //打印结果
    println("a: " + a)	//a: 20
    println("b: " + b)	//b: 10
    

Scala第四章节

章节目标

  1. 掌握分支结构的格式和用法
  2. 掌握for循环和while循环的格式和用法
  3. 掌握控制跳转语句的用法
  4. 掌握循环案例
  5. 理解do.while循环的格式和用法

1. 流程控制结构

1.1 概述

在实际开发中, 我们要编写成千上万行代码, 代码的顺序不同, 执行结果肯定也会受到一些影响, 并且有些代码是满足特定条件才能执行的, 有些代码是要重复执行的. 那如何合理规划这些代码呢? 这就需要用到: 流程控制结构了.

1.2 分类
  • 顺序结构

  • 选择(分支)结构

  • 循环结构

    注意: Scala和Java中的流程控制结构是基本一致的.

2. 顺序结构

2.1 概述

顺序结构是指: 程序是按照从上至下, 从左至右的顺序, 依次逐行执行的, 中间没有任何判断和跳转.

如图:
在这里插入图片描述

注意: 顺序结构是Scala代码的默认流程控制结构.

2.2 代码演示
val a = 10
println("a: " + a)	//打印结果为10

println("键盘敲烂, ")
println("月薪过万! ")
2.3 思考题

下边这行代码的打印结果应该是什么呢?

println(10 + 10 + "Hello,Scala" + 10 + 10)

提示: 代码是按照从上至下, 从左至右的顺序, 依次逐行执行的.

3. 选择结构(if语句)

3.1 概述

选择结构是指: 某些代码的执行需要依赖于特定的判断条件, 如果判断条件成立, 则代码执行, 否则, 代码不执行.

3.2 分类
  • 单分支
  • 双分支
  • 多分支
3.3 单分支

所谓的单分支是指: 只有一个判断条件的if语句.

3.3.1 格式
if(关系表达式) {
   
    //具体的代码
}

注意: 关系表达式不管简单还是复杂, 结果必须是Boolean类型的值.

3.3.2 执行流程
  1. 先执行关系表达式, 看其结果是true还是false.

  2. 如果是true, 则执行具体的代码, 否则, 不执行.

  3. 如图:
    在这里插入图片描述

3.3.3 示例

需求:

​ 定义一个变量记录某个学生的成绩, 如果成绩大于或者等于60分, 则打印: 分数及格.

参考代码

//定义变量, 记录成绩
val score = 61
//判断成绩是否不小于60分
if(score >= 60) {
   
    println("成绩及格")
}
3.4 双分支

所谓的双分支是指: 只有两个判断条件的if语句.

3.4.1 格式
if(关系表达式) {
   
    //代码1
} else {
   
    //代码2
}
3.4.2 执行流程
  1. 先执行关系表达式, 看其结果是true还是false.
  2. 如果是true, 则执行代码1. 如果是false, 则执行代码2.
  3. 如图:
    在这里插入图片描述
3.4.3 示例

需求:

​ 定义一个变量记录某个学生的成绩, 如果成绩大于或者等于60分, 则打印: 分数及格, 否则打印分数不及格.

参考代码

//定义变量, 记录成绩
val score = 61
//判断成绩是否不小于60分
if(score >= 60) {
   
    println("成绩及格")
} else {
   
    println("成绩不及格")
}
3.5 多分支

所谓的多分支是指: 有多个判断条件的if语句.

3.5.1 格式
if(关系表达式1) {
   
    //代码1
} else if(关系表达式2) {
   
    //代码2
}else if(关系表达式n) {
   	//else if可以有多组
    //代码n
} else {
   
    //代码n+1			  //所有的关系表达式都不成立的时候, 执行这里的代码.
}
3.5.2 执行流程
  1. 先执行关系表达式1, 看其结果是true还是false.
  2. 如果是true, 则执行代码1, 分支语句结束. 如果是false, 则执行关系表达式2, 看其结果是true还是false.
  3. 如果是true, 则执行代码2. 分支语句结束. 如果是false, 则执行关系表达式3, 看其结果是true还是false.
  4. 以此类推, 直到所有的关系表达式都不满足, 执行最后一个else中的代码.
  5. 如图:
    在这里插入图片描述
3.5.3 示例

需求:

​ 定义一个变量记录某个学生的成绩, 根据成绩发放对应的奖

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值