Scala 一文搞定
Posted 在奋斗的大道
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala 一文搞定相关的知识,希望对你有一定的参考价值。
第一节:概述
为什么学习Scala ?
Apache Spark 是专为大规模数据快速实时处理的计算引擎/内存级大数据计算框架。Apache Spark 是由Scala 语言编写。
Scala 与Java 关系
总结三点:
java 编译器与Scala 编译器可以相互使用。
Java SDK 的类库可以被Scala使用,Scala支持对Java 类库进行封装。Java 无法访问Scala特有类库
Scala 支持Java语法,JDK不支持Scala 特有语法。
Scala 语言特性
Scala 环境搭建
请参考文章:Windows 安装Scala 详情
IDEA 安装Scala 插件
默认情况下IDEA不支持Scala的开发,需要安装Scala插件。
我这里选择离线安装Scala 插件
a. IDEA的Scala插件地址: https://plugins.jetbrains.com/plugin/1347-scala/versions,找到自己的IDEA版本所对应的版本下载。
知识拓展:如何查看IDEA 是否支持Scala插件
b. 下载后是一个压缩包,将插件放于Scala安装目录下的plugin目录下
c. IDEA进入Settings,选择Plugins,选择从磁盘安装,然后选择Scala插件压缩包即可。
Scala 之Hello World
创建IDEA项目工程
1)打开IDEA->点击左侧的Flie->选择New->选择Project…
2)在src包下,创建包com.zzg.chapt01名和Hello类名,
右键点击src目录->New->Package->输入com.zzg.chapt01->点击OK。
右键点击com.zzg.chapt01->New->Scala Class->Kind项选择Object->Name项输入Hello
编写输出Hello Scala案例
在类中中输入main,然后回车可以快速生成main方法;
在main方法中输入println(“Hello World Scala”)
package com.zzg.chapt01
object Hello
def main(args: Array[String]): Unit =
println("Hello World Scala");
控制台结果输出:
Hello World 程序详细说明
//main 方法名、程序入口
//小括号表示参数列表
// Java 与scala 参数声明方式: java -> 类型 参数名
// scala -> 参数名 : 类型
// public修饰符: scala中没有public关键字,如果不声明访问权限,那么就是公共的
// static修饰符: scala中没有静态方法,所以没有static关键字
// void关键字: 表示返回值,但是不遵守面向对象语法,所以scala中没有,但是又Unit类型,表示没有返回值
// scala中: 方法名(参数列表):返回值类型
// scala中方法必须采用关键字def声明
// scala中方法实现赋值给方法声明,所以中间需要等号连接
// scala是一个完全面向对象的语言,所以没有静态语法,为了能调用静态语法(模仿静态语法)
// 采用伴生对象单例的方式调用方法
/*
* Scala 完全面向对象,故scala去掉了Java中非面向对象的元素,如static关键字,void类型
* 1) static
* scala无static关键字,由object实现类似静态方法的功能(类名.方法名)
* class关键字和Java中的class关键字作用相同,用来定义一个类
* 2) void
* 对于无返回值的函数,scala定义其返回值类型为Unit类型
*
* */
package com.zzg.chapt01
object Hello
def main(args: Array[String]): Unit =
println("Hello World Scala");
第二节:Scala 变量和支持数据类型
2.1 注释
Scala 注释与Java 注释完全一样。
基本语法:
(1)单行注释://
(2)多行注释:/* */
(3)文档注释:/**
*
*/
知识拓展:编码规范
(1)使用一次tab操作,实现缩进,默认整体向右边移动,用shift+tab整体向左移
(2)或者使用ctrl + alt + L来进行格式化
(3)运算符两边习惯性各加一个空格。比如:2 + 4 * 5
(4)一行最长不超过80个字符,超过的请使用换行展示,尽量保持格式优雅
2.2 变量和常量(重点)
Java 变量和常量语法声明:
变量类型 变量名称 = 初始值
eg:int a = 1
final 常量类型 常量名称 = 初始值
eg: final int b = 2
Scala 变量和常量语法声明:
var 变量名 [: 变量类型] = 初始值
eg:var i:Int = 10
val 常量名 [: 常量类型] = 初始值
eg:val j:Int = 20
知识拓展:能用常量就不要使用变量。
Scala 实例:
(1)声明变量时,类型可以省略,编译器自动推导,即类型推导
(2)类型确定后,就不能修改,说明Scala是强数据类型语言。
(3)变量声明时,必须要有初始值
(4)在声明/定义一个变量时,可以使用var或者val来修饰,var修饰变量可改变,val修饰常量不可改。
package com.zzg.chapt02
object VariableAndConstantDemo
def main(args: Array[String]): Unit =
// 定义Int 类型变量
var a:Int = 10;
// 类型推导
var b = 10;
// 定义Double 类型变量
var c:Double = 3.1415;
// 变量类型确定,不允许修改, 编译直接提示错误
// var d:Int = c;
// 定义变量, 不赋值, 编译器直接提示 错误
// var e;
// 定义常量
val f:Int = 10;
// 修改常量, 编译器直接提示错误
// f = 11;
(5)var修饰的对象引用可以改变,val修饰的对象则不可改变,但对象的状态(值)却是可以改变的。(比如:自定义对象、数组、集合等等)
package com.zzg.chapt02
/**
* 复杂对象
*/
object ComplexObjectDemo
def main(args: Array[String]): Unit =
// a对象使用var变量声明, 对象属性可以修改,对象状态也可以修改
var a = new Person();
// 对象属性修改
a.name = "Jane";
// 对象状态修改
a = null;
// b 对象使用val 常量声明,对象属性可以修改,对象状态不可以修改
val b = new Person();
// 对象属性修改
b.name = "Tom";
// 对象状态修改, 编译器直接提示错误。
// b = null;
/**
* 内部类定义
*/
class Person
var name = "Jack";
2.3 标识符命名规范
Scala 命名规范与Java 命名规范一致
(1)以字母或者下划线开头,后接字母、数字、下划线
(2)以操作符开头,且只包含操作符(+ - * / # !等)
(3)用反引号....包括的任意字符串,即使是Scala关键字(39个)也可以
• package, import, class, object, trait, extends, with, type, for
• private, protected, abstract, sealed, final, implicit, lazy, override
• try, catch, finally, throw
• if, else, match, case, do, while, for, return, yield
• def, val, var
• this, super
• new
• true, false, null
2.4 字符串输出
基本语法:
(1)字符串,通过+号连接
(2)printf用法:字符串,通过%传值。
(3)字符串模板(插值字符串):通过$获取变量值
package com.zzg.chapt02
object StringInputDemo
def main(args: Array[String]): Unit =
var str1:String = "Hello ";
var str2:String = "Scala"
// 字符串输出:使用 +号 连接
println(str1 + str2)
// 字符串输出: 使用%号传值
printf("my name is =%s", str2);
/**
* 多行字符串输出:
* 1、 在Scala中,利用三个双引号包围多行字符串就可以实现。
* 2、 问题:输入的内容,带有空格、\\t之类,导致每一行的开始位置不能整洁对齐。
* 3、 解决办法:使用Scala中stripMargin, 默认是“|”作为连接符, 要求:多行字符串的每一行的行头前面加一个“|”符号, 实现格式化
*/
val sql =
"""
|select
|name
|from
|base_user
|where
|id = 1
""".stripMargin
println(sql);
var id:Int =1;
// 字符串输出: 使用$号传值
val formateSql =
s"""
|select
|name
|from
|base_user
|where
|id = $id
""".stripMargin
println(formateSql);
2.5 键盘输入
基本语法:
StdIn.readLine() : 读取行记录
StdIn.readShort():读取Short
StdIn.readDouble(): 读取Double
package com.zzg.chapt02
import scala.io.StdIn
object KeyWordInouDemo
def main(args: Array[String]): Unit =
// 输入姓名
println("input name:")
var name = StdIn.readLine()
// 输入年龄
println("input age:")
var age = StdIn.readShort()
printf("my name is =%s", name);
println();
printf("my age is =%d", age);
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 数据类型
2.7 整数类型
整数分类
数据类型 | 描述 |
Byte [1] | 8位有符号补码整数。数值区间为 -128 到 127 |
Short [2] | 16位有符号补码整数。数值区间为 -32768 到 32767 |
Int [4] | 32位有符号补码整数。数值区间为 -2147483648 到 2147483647 |
Long [8] | 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807 = 2的(64-1)次方-1 |
Scala 实例:
(1)Scala各整数类型有固定的表示范围和字段长度,不受具体操作的影响,以保证Scala程序的可移植性。
(2)Scala的整型,默认为Int型,声明Long型,须后加‘l’或‘L’
package com.zzg.chapt02
object DataTypeDemo
def main(args: Array[String]): Unit =
// Scala各整数类型有固定的表示范围和字段长度
// 正确
var a: Byte = 127
var b: Byte = -128
// 错误
// var c:Byte = 128
// var d:Byte = -129
// Scala的整型,默认为Int型,声明Long型,然后加”i“ 或者 ”L“
var e = 10
println(e)
var f = 98989898989898989L
println(f)
2.8 浮点类型
浮点型分类
数据类型 | 描述 |
Float [4] | 32 位, IEEE 754标准的单精度浮点数 |
Double [8] | 64 位 IEEE 754标准的双精度浮点数 |
Scala 实例:
(1)Scala的浮点型常量默认为Double型,声明Float型常量,须后加‘f’或‘F’。
package com.zzg.chapt02
object DataTypeDemo
def main(args: Array[String]): Unit =
// Scala各整数类型有固定的表示范围和字段长度
// 正确
var a: Byte = 127
var b: Byte = -128
// 错误
// var c:Byte = 128
// var d:Byte = -129
// Scala的整型,默认为Int型,声明Long型,然后加”i“ 或者 ”L“
var e = 10
println(e)
var f = 98989898989898989L
println(f)
//Scala 声明Float类型,须后加‘f’或‘F’。
var g =1283732f
println(g)
2.9 字符类型
基本说明:
字符类型可以表示单个字符,字符类型是Char。
Scala 实例:
(1)字符常量是用单引号 ’ ’ 括起来的单个字符。
(2)\\t :一个制表位,实现对齐的功能
(3)\\n :换行符
(4)\\ :表示\\
(5)" :表示"
package com.zzg.chapt02
object CharTypeDemo
def main(args: Array[String]): Unit =
// 字符定义使用''括起来
var a:Char = 'a';
println(a);
//注意:这里涉及自动类型提升,其实编译器可以自定判断是否超出范围
// var b:Char = 'a' + 1
// \\t :一个制表位,实现对齐的功能
println("姓名\\t年龄")
// \\n :换行符
println("西门庆\\n潘金莲")
//(4)\\\\ :表示\\
println("c:\\\\天黑了\\\\饿狼来了")
//(5)\\" :表示"
println("你过来:\\"看我一拳打死你\\"")
控制台输出:
D:\\Java\\jdk1.8.0_121\\bin\\java.exe -Dvisualvm.id=756107015780000 "-javaagent:D:\\Program Files\\JetBrains\\IntelliJ IDEA Community Edition 2022.1\\lib\\idea_rt.jar=52353:D:\\Program Files\\JetBrains\\IntelliJ IDEA Community Edition 2022.1\\bin" -Dfile.encoding=UTF-8 -classpath D:\\java\\jdk1.8.0_121\\jre\\lib\\charsets.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\deploy.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\access-bridge-64.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\cldrdata.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\dnsns.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\jaccess.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\jfxrt.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\localedata.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\nashorn.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\sunec.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\sunjce_provider.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\sunmscapi.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\sunpkcs11.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\zipfs.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\javaws.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\jce.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\jfr.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\jfxswt.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\jsse.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\management-agent.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\plugin.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\resources.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\rt.jar;E:\\scala_workspace\\ScalaDemo\\out\\production\\ScalaDemo;D:\\scala\\lib\\scala-library.jar;D:\\scala\\lib\\scala-reflect.jar com.zzg.chapt02.CharTypeDemo
a
姓名 年龄
西门庆
潘金莲
c:\\天黑了\\饿狼来了
你过来:"看我一拳打死你"
2.10 布尔类型
基本说明:
(1)布尔类型也叫Boolean类型,Booolean类型数据只允许取值true和false
(2)boolean类型占1个字节。
Scala 实例:
package com.zzg.chapt02
class BooleanTypeDemo
def main(args: Array[String]): Unit =
var isTrue:Boolean =true;
var isFalse:Boolean = false;
2.11 Unit类型、Null类型和Nothing类型(重点)
基本说明:
Scala 实例:
(1)、Unit 修饰没有返回值函数。
(2)、Null类只有一个实例对象,Null类似于Java中的null引用。Null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)
(3)、Nothing,可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回,而且由于Nothing是其他任意类型的子类,他还能跟要求返回值的方法兼容。
package com.zzg.chapt02
object NullAndNullAndNothingDemo
def main(args: Array[String]): Unit =
// 调用Unit 函数
println(num)
// null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)
var person = new Person()
person = null
//var a: Int = null // IDEA编译错误:an expression of type Null is ineligible for implicit conversion
//println("a is:" + a)
// 调用过期函数, 抛出异常信息。
calculate();
/**
* 定义Unit 函数
*/
def num:Unit =
println("Unit 函数被调用")
/**
* 定义引用类型(AnyRef)
*/
class Person
/**
* 定义calculate函数,会抛出异常
* @return
*/
def calculate():Nothing=
throw new Exception;
2.12 类型转换
当Scala程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数值类型,这个就是自动类型转换(隐式转换)。数据类型按精度(容量)大小排序为:
基本说明
(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。
(2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
(3)(byte,short)和char之间不会相互自动转换。
(4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。
Scala 实例:
package com.zzg.chapt02
object ValueTransDemo
def main(args: Array[String]): Unit =
//(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数值类型,然后再进行计算。
var a = 1 + 2.2222
println(a) //Double
//(2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
var b: Double = 2.2222
// var c: Int = b //报错
//(3)(byte,short)和char之间不会相互自动转换。
var d: Byte = 44
// var e : Char = d//报错
var f: Int = d
//(4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。
var g: Byte = 66
var h: Char = 22
// var l : Short = g + b //报错,结果是Int类型
// var m : Short = 10 + 20 //报错,byte,short,char他们三者可以计算,在计算时首先转换为int类型。
强制类型转换
基本说明:
自动类型转换的逆过程,将精度大的数值类型转换为精度小的数值类型。使用时要加上强制转函数,但可能造成精度降低或溢出,格外要注意。
语法说明:
Java : int num = (int)2.1
Scala : var num : Int = 2.1.toInt
Scala 实例:
(1)将数据由高精度转换为低精度,就需要使用到强制转换
(2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
def main(args: Array[String]): Unit =
//(1)将数据由高精度转换为低精度,就需要使用到强制转换
var n1: Int = 2.5.toInt // 这个存在精度损失
//(2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
var r1: Int = 10 * 3.5.toInt + 6 * 1.5.toInt // 10 *3 + 6*1 = 36
var r2: Int = (10 * 3.5 + 6 * 1.5).toInt // 44.0.toInt = 44
println("r1=" + r1 + " r2=" + r2)
数值类型和String类型间转换
基本说明:
在程序开发中,我们经常需要将基本数值类型转成String类型。或者将String类型转成基本数值类型。
Scala 实例:
(1)基本类型转String类型(语法:将基本类型的值+“” 即可)
(2)String类型转基本数值类型(语法:s1.toInt、s1.toFloat、s1.toDouble、s1.toByte、s1.toLong、s1.toShort)
def main(args: Array[String]): Unit =
//(1)基本类型转String类型(语法:将基本类型的值+"" 即可)
var str1: String = true + "你kin"
println(str1)
var str2: String = 4.444 + "拜拜"
println(str2)
var str3: String = 4444 + ""
println(str3)
//(2)String类型转基本数值类型(语法:调用相关API)
var s1: String = "11"
var n1: Byte = s1.toByte
var n2: Short = s1.toShort
var n3: Int = s1.toInt
var n4: Long = s1.toLong
println(s1)
println(n1)
println(n2)
println(n3)
println(n4)
第三节: Scala 运算符
Scala运算符的使用和Java运算符的使用基本相同,只有个别细节上不同。
算术运算符
(1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。小数之间做除法时,保留整数和小数部分
(2)对一个数取模a%b,和Java的取模规则一样。
Scala 实例:
package com.zzg.chapt02
object ArithmeticDemo
def main(args: Array[String]): Unit =
// 1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
var a: Int = 10 / 3
println(a) //3
var b: Double = 10 / 3
println(b) //3.0
var c: Double = 10.0 / 3
println(c) //3.3333333333333335
println(c.formatted("%.2f")) //3.33 含义:保留小数点2位,使用四舍五入
//(2)对一个数取模a%b,和Java的取模规则一样。
var d = 10 % 3
println(d) //1
关系运算符(比较运算符)
Scala 实例:
package com.zzg.chapt02
object RelationDemo
def main(args: Array[String]): Unit =
var a:Int = 1
var b:Int = 2
println(a > b) // false
println(a >= b) // false
println(a < b) // true
println(a <= b) // true
println(a == b) // false
println(a != b) // true
知识拓展:Java和Scala中关于==的区别
Java:==比较两个对象在内存地址;equals比较两个对象toString生成内容是否相同。
Scala: == 等价于Java 的equals 方法。
逻辑运算符
Scala 实例:
package com.zzg.chapt02
object LogicDemo
def main(args: Array[String]): Unit =
var a: Boolean = true;
var b: Boolean = false;
println(a && b) // false
println(a || b) // true
println(!a || !b) // true
赋值运算符
温馨提示:Scala中没有++、– –操作符,可以通过+=、-=来实现同样的效果;
Scala 实例:
package com.zzg.chapt02
object AssignmentDemo
def main(args: Array[String]): Unit =
var a:Int =10;
a += 1 // 11
println(a);
a -= 1 // 10
println(a);
位运算符
表中变量 a 为 60,b 为 13
Scala运算符本质
在Scala中其实是没有运算符的,所有运算符都是方法。
1)当调用对象的方法时,点.可以省略
2)如果函数参数只有一个,或者没有参数,()可以省略
package com.zzg.chapt02
object OperateDemo
def main(args: Array[String]): Unit =
// 标准的加法运算
val i:Int = 1.+(1)
// (1)当调用对象的方法时,.可以省略
val j:Int = 1 + (1)
// (2)如果函数参数只有一个,或者没有参数,()可以省略
val k:Int = 1 + 1
println(1.toString())
println(1.toString)
第四节: Scala 流程控制
if语句
if单分支语句
基本语法:
if (条件表达式)
执行代码块
温馨提示:当条件表达式为ture时,就会执行 的代码。
if 双分支语句
基本语法:
if (条件表达式)
执行代码块1
else
执行代码块2
温馨提示:当条件表达式为true 时,执行代码块1,否则执行代码块2。
if 多分支语句
基本语法:
if (条件表达式1)
执行代码块1
else if (条件表达式2)
执行代码块2
……
else
执行代码块n
温馨提示:有满足结果为true的条件表达式,就执行条件表达式代码,否则执行else 代码。
Scala 实例:
package com.zzg.chapt02
import scala.io.StdIn
object IfExpressionDemo
def main(args: Array[String]): Unit =
println("input age:")
var age: Int = StdIn.readInt();
if(age <= 18)
println("儿童")
else if(age > 18 && age <= 45)
println("青年")
else if(age > 45 && age <= 60)
println("中年");
else
println("老年")
嵌套分支
在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层。分支外面的分支结构称为外层分支。温馨提示:嵌套分支不要超过3层。
基本语法:
if()
if()
else
Scala 实例:针对年龄类判断,优化调整:对于小于等于18条件,在细分:小于等于6 为儿童,其他为少年。
package com.zzg.chapt02
import scala.io.StdIn
object IfExpressionDemo
def main(args: Array[String]): Unit =
println("input age:")
var age: Int = StdIn.readInt();
if(age <= 18)
if(age <= 6)
println("儿童")
else
println("少年")
else if(age > 18 && age <= 45)
println("青年")
else if(age > 45 && age <= 60)
println("中年");
else
println("老年")
Switch分支结构
在Scala中没有Switch语句,而是使用模式匹配来处理。
此章节在模式匹配/正则表达式再详细讲解。
For循环控制/For 推导式/For 表达式
Scala 为For 循环控制这一常见的控制结构提供了非常多的特性。
范围数据循环(To)
基本语法:
for(i <- start to end)
println(i + " ")
说明:
(1)i 表示循环的变量,初始值start
(2)i 将会从 start-end 循环,前后闭合/[]
范围数据循环(Until)
基本语法:
for(i <- start until end)
println(i + " ")
说明:
(1)这种方式和前面的区别在于i是从start到start - end
(2)即使前闭合后开的范围/[)
循环守卫
基本语法:
for(i <- start to end if condition)
println(i + " ")
说明:
(1)循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为true则进入循环体内部,为false则跳过,类似于continue。
对等代码
for(i <- start to endd)
if(condition)
println(i + " ")
循环步长
基本语法:
for (i <- start to end by step)
println(“i=” + i)
嵌套循环
基本语法:
for(i <- start to end; j <- start to end)
println(" i =" + i + " j = " + j)
说明:没有关键字,所以范围后一定要加;来隔断逻辑
引入变量
基本语法
for(i <- start to end; j = parameter - i)
println("i=" + i + " j=" + j)
说明:
(1)for推导式一行中有多个表达式时,所以要加 ; 来隔断逻辑
(2)for推导式有一个不成文的约定:当for推导式仅包含单一表达式时使用圆括号,当包含多个表达式时,一般每行一个表达式,并用花括号代替圆括号,如下
Scala 实例
package com.zzg.chapt03
object ForVariableDemo
def main(args: Array[String]): Unit =
// For 引入变量, 形式一
for(i <- 1 to 3; j= 5 -i)
println("i =" + i + ", j =" + j);
println("----------------------------")
// For 引入变量, 形式二
for
i <- 1 to 3
j = 5 -i
println("i =" + i + ", j =" + j);
循环返回值
基本语法:
val result = for(i <- start to end) yield i
说明: 将遍历过程中处理的结果返回到一个新Vector集合中,使用yield关键字。
温馨提示:在开发中使用场景较少。
倒序打印
基本语法:
for(i <- start to end reverse)
println(“i=” + i)
说明:倒序打印一组数据,可以使用reverse
While和do…While循环控制
While和do…While的使用和Java语言中用法相同。
While循环控制
基本语法:
循环变量初始化
while (循环条件)
循环体(语句)
循环变量迭代
说明:
(1)循环条件是返回一个布尔值的表达式
(2)while循环是先判断再执行语句
(3)与for语句不同,while语句没有返回值,即整个while语句的结果是Unit类型()
(4)因为while中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免的使用变量,而变量需要声明在while循环的外部,那么就等同于循环的内部对外部的变量造成了影响,所以不推荐使用,而是推荐使用for循环。
Scala 实例
package com.zzg.chapt03
object WhileDemo
def main(args: Array[String]): Unit =
var a: Int = 10;
while (a > 1)
println("a =" + a)
a -=1
do…while循环控制
基本语法:
循环变量初始化;
do
循环体(语句)
循环变量迭代
while(循环条件)
说明:
(1)循环条件是返回一个布尔值的表达式
(2)do…while循环是先执行,再判断
Scala 实例
package com.zzg.chapt03
object DoWhileDemo
def main(args: Array[String]): Unit =
var a:Int = 0;
do
println("a =" + a);
a += 1
while(a < 10)
循环中断
Scala内置控制结构特地去掉了break和continue,是为了更好的适应函数式编程.
Scala 推荐使用Breaks.break()控制结构来实现break和continue功能。
Scala 实例:采取异常方式,跳出for 循环
package com.zzg.chapt03
object ForExceptionDemo
def main(args: Array[String]): Unit =
try
for (i <- 1 to 10)
println("i = " + i);
if (i == 8)
throw new RuntimeException()
println("for 循环正常结束")
catch
case e =>
println("for 循环通过异常结束")
Scala 实例:通过Scala 自带函数(Breaks.break()),退出for循环
package com.zzg.chapt03
import scala.Console.println
import scala.util.control.Breaks
object BreaksDemo
def main(args: Array[String]): Unit =
Breaks.breakable(
for (i <- 1 to 10)
println("i = " + i);
if (i == 8)
println("通过Breaks中止for 循环")
Breaks.break()
)
println("for 循环正常中止")
第五节:Scala 函数式编程
面向对象编程、函数式编程区别
1)面向对象编程
解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。
对象:用户
行为:登录、连接JDBC、读取数据库
属性:用户名、密码
Scala语言是一个完全面向对象编程语言。万物皆对象
对象的本质:对数据和行为的一个封装
2)函数式编程
解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题。
例如:请求->用户名、密码->连接JDBC->读取数据库
Scala语言是一个完全函数式编程语言。万物皆函数。
函数的本质:函数可以当做一个值进行传递
3)在Scala中函数式编程和面向对象编程完美融合在一起了。
函数
基本语法:
Scala 实例
package com.zzg.chapt04
object FunctionDemo
def main(args: Array[String]): Unit =
/**
* 自定义sum 函数
* @param x
* @param y
* @return
*/
def sum(x:Int, y:Int):Int =
x + y
// 调用sum 函数
println("sum is =" + sum(1, 2))
函数和方法的区别
核心概念
(1)为完成某一功能的程序语句的集合,称为函数。
(2)类中的函数称之方法。
Scala 实例
(1)Scala语言可以在任何的语法结构中声明任何的语法
(2)函数没有重载和重写的概念;方法可以进行重载和重写
(3)Scala中函数可以嵌套定义
package com.zzg.chapt04
object Function01Demo
// 2.方法可以进行重载和重写,程序可以执行
def main(): Unit =
println("main 方法重新")
def main(args: Array[String]): Unit =
// 1.Scala语言可以在任何的语法结构中声明任何的语法
import java.util.Date
new Date()
// 3.函数没有重载和重写的概念,程序报错
def test(): Unit =
println("无参,无返回值")
test()
// def test(): Unit =
// println()
//
// 4.Scala 中函数可以嵌套定义
def test2() :Unit =
def test3(name:String):Unit=
println("函数可以嵌套定义")
test3("函数嵌套")
test2()
函数定义
1)函数定义
(1)函数1:无参,无返回值
(2)函数2:无参,有返回值
(3)函数3:有参,无返回值
(4)函数4:有参,有返回值
(5)函数5:多参,无返回值
(6)函数6:多参,有返回值
Scala 实例
package com.zzg.chapt04
object FunctionDefinitionDemo
def main(args: Array[String]): Unit =
// 无参函数, 调用函数省略()
this.one;
this.two();
this.three("Scala");
this.four("Scala");
this.five(1, 2);
this.six(1, 2);
/**
* 函数1:无参,无返回值
*/
def one :Unit =
println("无参,无返回值")
/**
* 函数2:无参,有返回值
*/
def two() :Int =
println("无参,有返回值")
return 1
/**
* 函数3:有参,无返回值
*/
def three(x:String) :Unit =
println("x =" + x)
println("有参,无返回值")
/**
* 函数4:有参,有返回值
* @return
*/
def four(x:String) :String =
println("x =" + x)
return x;
/**
* 函数5:多参,无返回值
* @param a
* @param b
*/
def five(a: Int, b:Int) : Unit =
println("a =" + a +", b=" + b)
/**
* 函数6:多参,有返回值
* @param a
* @param b
* @return
*/
def six(a:Int, b:Int) : Int =
println("a =" + a +", b=" + b)
return a + b
函数参数
1)参数说明
(1)可变参数
(2)如果参数列表中存在多个参数,那么可变参数一般放置在最后
(3)参数默认值,一般将有默认值的参数放置在参数列表的后面
(4)带名参数
package com.zzg.chapt04
object FunctionParamterDemo
def main(args: Array[String]): Unit =
this.one("Hello", "Scala")
this.two("Hi", "Scala", "!")
// 如果参数有默认值,在调用的时候,可以省略这个参数
this.three("zzx");
// 如果参数传递了值,那么会覆盖默认值
this.three("zzy", 12);
// 默认调用不传递参数名称
this.four("zzh");
// 调用传递参数名称
this.four(name="zty");
/**
* 函数:可变参数
* @param parame
*/
def one(parameters:String*):Unit=
println(parameters)
/**
* 函数:参数列表中存在多个参数,那么可变参数一般放置在最后
* @param name
* @param paramters
*/
def two(name:String, paramters:String*):Unit=
println("name =" + name);
println(paramters)
/**
* 函数:参数默认值
* @param name
* @param age
*/
def three(name:String, age:Int = 18):Unit=
println(s"$name = $age")
/**
* 函数:参数携带参数名称传递
* @param name
*/
def four(name:String):Unit=
println("name =" + name)
函数至简原则(重点)
函数至简原则:能省则省
1)至简原则细节
(1)return可以省略,Scala会使用函数体的最后一行代码作为返回值
(2)如果函数体只有一行代码,可以省略花括号
(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
(4)如果有return,则不能省略返回值类型,必须指定
(5)如果函数明确声明unit,那么即使函数体中使用return关键字也不起作用
(6)Scala如果期望是无返回值类型,可以省略等号
(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
Scala 实例
待补充。
函数高级
在Scala中,函数是一等公民。
Scala 实例
package com.zzg.chapt04
object FunctionAdvancedDemo
def main(args: Array[String]): Unit =
this.one()
/**
* Scala 函数是第一公民
*/
def one():Unit=
println("函数未声明, 直接调用")
函数高级用法
函数值传递
(1)、函数赋值给变量
(2)、被调用函数后面加上 _, 相当于把函数当成一个整体,再赋值给变量
(3)、明确变量类型,不适用下划线也可以将函数作为整体传递给变量
Scala 实例
package com.zzg.chapt04
object FunctionAdvancedDemo
def main(args: Array[String]): Unit =
this.one()
// 函数赋值给变量 方式一
var func = this.two();
println(func)
// 变量直接赋值
var b = func;
println(b)
// 函数赋值给变量 方式二
var c = this.two _; // 等价于拷贝two 函数源码
println(c) // 输出函数地址引用
println(c()) // 整体调用函数
// 函数赋值给变量 方式三
var d : () => Int = two // 通过匿名函数, 接受函数返回值,再赋值给变量。
println(d())
/**
* Scala 函数是第一公民
*/
def one():Unit=
println("函数未声明, 直接调用")
/**
* Scala 函数赋值给变量
* @return
*/
def two():Int =
return 1
函数参数传递
package com.zzg.chapt04
object Function02Demo
def main(args: Array[String]): Unit =
// (1)定义一个函数,函数参数还是一个函数签名,f表示函数名称;(Int,Int)表示输入两个Int参数;Int表示函数返回值
def complexF(f:(Int,Int) =>Int) :Int=
return this.add(2, 4)
// (3) 将add函数作为参数传递给complexF函数,如果能够推断出来不是调用,_可以省略
println(complexF(add));
println(complexF(add _))
// (2) 定义一个函数,参数和返回值类型和complexF的输入参数一致
def add(a:Int, b:Int):Int=
return a + b;
函数作为返回值返回
package com.zzg.chapt04
/**
* 函数作为返回值返回
*/
object Function03Demo
def main(args: Array[String]): Unit =
def a() =
def b() =
println("函数嵌套")
println("-------------------")
// 函数b后面加上 _, 相当于把函数b当成一个整体。
b _
var c = a();
println(c) // 打印函数整体的内存地址
println("---------------")
println(c()) // 执行函数
匿名函数
基本说明:
没有名字的函数就是匿名函数。
基本语法:
(x:Int)=>函数体
温馨提示:x:表示输入参数类型;Int:表示输入参数类型;函数体:表示具体代码逻辑。
Scala 实例
功能需求:传递的函数有一个参数
传递匿名函数至简原则:
(1)参数的类型可以省略,会根据形参进行自动的推导
(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过1的永远不能省略圆括号。
(3)匿名函数如果只有一行,则大括号
以上是关于Scala 一文搞定的主要内容,如果未能解决你的问题,请参考以下文章
Spark SQL functions.scala 源码解析String functions (基于 Spark 3.3.0)
Spark SQL functions.scala 源码解析Aggregate functions(基于 Spark 3.3.0)