文章目录
1、流程控制
1)if…else
//1、单分支的情况
/*println("请输入年龄")
val age: Int = StdIn.readInt()
if(age<18){
println("童年")
}*/
//2、双分支
/*println("请输入年龄")
val age: Int = StdIn.readInt()
if(age<18){
println("童年")
} else{
println("成年")
}*/
//3、多分支
/*println("请输入年龄")
val age: Int = StdIn.readInt()
if(age<18){
println("童年")
} else if(age>=18 && age<=40){
println("成年")
}else{
println("老年")
}*/
//4、分支语句带返回值 返回类型一致
/*println("请输入年龄")
val age: Int = StdIn.readInt()
//分支语句是有返回值的,具体返回什么,和满足条件的分支语句中的最后一行代码有关
val res: String = if (age < 18) {
"童年"
} else if (age >= 18 && age <= 40) {
"成年"
} else {
"老年"
}
println(res)*/
//5、分支语句带返回值 返回类型不一致
/*println("请输入年龄")
val age: Int = StdIn.readInt()
//如果每一个分支块返回的类型不一致,取他们共同的祖先类型
val res:Any = if (age < 18) {
"童年"
} else if (age >= 18 && age <= 40) {
"成年"
} else {
100
}
println(res)*/
//案例:通过if..。else模拟三元运算符实现 res=条件表达式?值1:值2
println("请输入年龄")
val age: Int = StdIn.readInt()
//如果分支代码块中,只有一行代码,那么花括号可以省略
var res = if (age<18) "童年" else "成年"
2)for循环控制
/**
* 1、对范围数据进行遍历 to 前后闭合
*/
//for(int i:1 to 10)错误
//1 to 10 表示产生从1到10的集合
//for (i:Int <- 1.to(10))
//在声明变量的时候,类型可以省略,因为编译器根据集合中的数据,推导出变量的类型
for (i: Int <- 1 to 10) {
println(i) //1 2 3 4 5 ...10
}
println("==========================")
/**
* 2、对范围数据进行遍历 until 前闭合后开的范围
*/
for (i <- 1 until 10) {
println(i) //1 2 3 4 5 ...9
}
println("==========================")
/**
* 3、循环守卫
* 在scala语言中,没有continue和break关键字
* 通过if来判断模拟continue跳出本次循环
* 通过调用方法模拟break跳出整个循环功能
*/
for (i <- 1 to 5) {
if (i != 3) { //利用if判断跳出3
println(i) //1 2 4 5
}
}
//循环守卫
for (i <- 1 to 5; if i != 3) println(i)
println("==========================")
/**
* 4、循环步长 by
* 步长不能为0
*/
//要求对1到10中的奇数进行遍历
for (i <- 1 to 10 by 2) println(i)
//利用循环步长另类倒序10->1
for (i <- 10 to 1 by -1) println(i)
/**
* 5、循环嵌套
*/
for (i <- 1 to 3) {
for (j <- 1 to 3) {
println("i=" + i + ",j=" + j)
}
}
println("======================")
//九九乘法表
for (i <- 1 to 9) {
for (j <- 1 to i) {
print(s" ${j} * ${i} = ${i * j} ")
}
println("")
}
//同理
/*for (i <- 1 to 9;j <- 1 to i) {
print(s" ${j} * ${i} = ${i * j} ")
if(i==j){
println()
}
}*/
/**
* 6、循环引入变量
*/
for {
i <- 1 to 5;
j = 10 - i
} {
println("i=" + i + ",j=" + j)
}
println("=" * 50)
//打印九层妖塔(等腰三角形)
for {i <- 1 to 9; j = 2 * i - 1; z = 9 - i} println(" " * z + "*" * j)
/**
* 7、循环返回值
* 将遍历过程中处理的结果返回到一个新Vector集合中,使用yield关键字。
*/
val res: immutable.IndexedSeq[Int] = for (i <- 1 to 5) yield i * 2
println(res)
/**
* 8、倒序打印
* 底层调用的是reverse方法
*/
for (i <- 1 to 10 reverse) {
println(i)
}
3)while循环
/**
* 1、while
* while循环是先判断,再执行
*/
var a: Int = 5
while (a >= 1) {
println("友培666!")
a -= 1
}
/**
* 2、do...while
* do..while循环是先执行,再判断
*/
var b: Int = 5
do {
println("友培真棒!")
b -= 1
} while (b >= 1)
4)循环中断★
Scala内置控制结构特地去掉了break和continue,是为了更好的适应函数式编程,推荐使用函数式的风格解决break和continue的功能,而不是一个关键字。Scala中使用breakable控制结构来实现break和continue功能。
/**
* 循环中断
*
* 在scala语言中,没有break和continue关键字
* 通过在循环体中加入条件判断 实现continue效果
*
*/
/**
* 1、利用抛出异常的想法
*/
/*
try{
for (i <- 1 to 5){
if(i == 3){
//抛出异常,跳出整个循环
throw new RuntimeException
}
println(111)
}
}catch {
//捕获异常,并对其进行处理
case e:Exception=>
}
*/
/**
* 2、利用Breaks类
*/
/*
//标记当前循环是可中断的
Breaks.breakable(
for (i <- 1 to 5){
if(i == 3){
//跳出整个循环
Breaks.break()
}
println(111)
}
)
*/
//3、导入静态类
breakable(
for (i <- 1 to 5){
if(i == 3){
//跳出整个循环
break
}
println(111)
}
)
println("这是循环之外的代码")
2、函数
1)函数定义
//1、函数:无参无返回值
def f1()={
println("无参,无返回值")
}
f1()
//2、无参,有返回值
def f2():Int={
println("无参,有返回值")
return 10
}
println(f2())
//3、有参,无返回值
def f3(name:String)={
println("有参,无返回值")
}
println(f3("xiaoyoupei"))
//4、有参,有返回值
def f4(name:String):String={
println("有参,有返回值")
return "hello-->" + name
}
println(f4("xiao"))
//5、多参,无返回值
def f5(name:String,age:Int)={
println("多参,无返回值")
println(s"${name}今年${age}岁了")
}
println(f5("xiao",21))
//6、多参,有返回值
def f6(a:Int,b:Int):Int={
println("多参,有返回值")
return a + b
}
println(f6(10,20))
2)函数参数
//1、可变参数 底层使用集合来接收参数
def f1(s : String *)={
println(s)
}
f1() //List()
f1("aaa","bbb") //WrappedArray(aaa, bbb)
//2、如果在参数列表中存在多个参数,那么可变参数应该放在最后
//在一个参数列表中,至多有一个可变长参数
def f2(s1:String,s2:String*)={
}
//3、参数默认值,一般将有默认值的参数放在参数列表后面
def f3(name:String="xiao")={
println(name)
}
f3()
f3("youpei")
//4、带名参数
def f4(name:String="liyan",sex:String)={
println(name+":::"+sex)
}
f4("xiao","man")
f4(sex="woman")
3)函数至简原则
/**
* 函数正常的定义与调用
*/
def sayHi(name:String):String={
return name
}
println(sayHi("xiaoyoupei"))
//1、return可以省略,scala会使用函数体的最后一行代码作为返回值
def f1(name:String):String={
name
}
println(f1("xiaoyoupei"))
//2、函数只有一行代码,花括号可以省略
def f2(name:String):String=name
println(f2("xiao"))
//3、返回值类型可以推断,那可以省略(:和返回值类型一起省略)
def f3(name:String)=name
println(f3("xiao"))
//4、如果有return,则不能省略返回值类型,必须指定
def f4(name:String):String= {
return name
}
println(f4("xiao"))
//5、如果函数声明unit,即使函数体中使用return关键字也不起作用
def f5(name:String):Unit={
return name
}
println(f5("xiao"))
//6、scala如果期望是无返回值类型,可以省略等号 这种写法称为过程
def f6(name:String){
name
}
println(f6("xiao"))
//7、如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
def f7():Unit={
println("hello")
}
f7
f7()
//8、如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
def f8:Unit={
println("hello")
}
f8//f8()括号必须省略
//9、如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
//函数类型 ff:(参数列表声明)=>返回值
def f10 (s:String):Unit={
println(s)
}
def f9(f:(String)=>Unit):Unit={
f("xiao")
}
f9(f10)
//上面的写法过于繁琐,每次调用f9的时候还得调用f10
//可以调用匿名函数 通过Lambda表达式实现 (参数列表)->{函数体}
f9((s:String)=>{println(s)})
//1、参数类型可以省略,会根据形参自动推导
f9((s)=>{println(s)})
//2、类型省略后,发现只有一个参数,则圆括号可以省略,其他情况:没有参数和参数超过1的永远不能省略圆括号
f9(s=>{println(s)})
//3、匿名函数如果是一行,则大括号也可以省略
f9((s)=>println(s))
//4、如果参数只出现一次,则参数省略用_(下划线)代替
f9(println(_))
//如果在进行println输出的时候,可以推断是一个函数,那么下划线可以省略
f9(println)
4)高阶函数
① 函数作为值传递
/**
* 函数作为值传递
*/
//函数的正常声明与调用
def foo(): Int = {
println("foo")
10
}
//将foo函数的执行结果赋值给res变量
val res: Int = foo()
println(10)
//函数作为值进行传递,语法:在函数名称的后面加上+ 空格 加下划线
//注意:将foo函数作为一个整体,赋值给f变量,f是函数类型 ()=>Int
val f: () => Int = foo _
//这个时候,f是一个函数,如果要想运行f函数的话,必须得加()
println(f) //输出的结果为<function0>
println(f()) //输出的结果为函数执行结果
//var ff = foo //将函数执行结果赋值给ff
//var ff = foo _ //将函数本身作为值赋给ff
var ff: () => Unit = foo //将函数本身作为值赋给ff
println(ff)
println("=" * 100)
/**
* 函数可以作为参数,进行传递(大多数情况都是通过匿名函数的形式)
*/
//定义一个函数calculator,该函数接收一个函数类型的参数op,定义了对两个整数要进行什么样的操作
def calculator(a: Int, b: Int, f1: (Int, Int) => Int): Int = {
f1(a, b)
}
//定义一个函数f1,完成两个整数的加法运算
def f1(a: Int, b: Int): Int = {
a + b
}
println(calculator(10, 20, f1))
//利用匿名函数的方式
println(calculator(50, 20, (a: Int, b: Int) => {
a - b
}))
println("=" * 100)
/**
* 函数作为返回值返回 -- 函数的嵌套
*/
def ff1(): () => Unit = {
def ff2(): Unit = {
println("ff2被调用了")
}
//将ff2作为返回值返回给ff1
ff2
}
//fff就是ff2
//val fff = ff1()
//fff()
ff1()()
② 函数作为参数传递
/**
* 将函数作为参数传递
* 扩展函数的功能
* 提高函数的灵活度
*/
//需求:提供一个函数,对数组中的元素进行处理,处理完毕后返回一个新的数组 目前处理方式:元素 + 1
//创建一个数据对象 val arr:Array[Int] = Array(1,2,3,4)
def operationArray(arr: Array[Int], op: Int => Int): Array[Int] = {
//遍历数组中的元素
for (elem <- arr) yield op(elem)
}
def op(elem: Int): Int = {
elem + 1
}
//调用函数,实现+1功能
val newArray: Array[Int] = operationArray(Array(1,2,3,4),op)
//打印输出,mkString:用指定的字符串连接数组中的元素,形成一个新的字符串
println(newArray.mkString(","))
//通过匿名函数,对数组元素*3
operationArray(Array(1,2,3,4),_*3)
5)函数的柯里化和闭包
/*def f1(): (Int => Int) = {
var a: Int = 10
def f2(b: Int): Int = {
a + b
}
f2 _
}
//执行f1函数返回f2,将返回的f2赋值给ff变量
val ff: Int => Int = f1()
//闭包:内层函数f2要访问外层函数f1局部变量a,当外层函数f1执行结束后,f1会释放内存,但是会自动延长f1函数的局部变量的生命周期,
// 和内层函数f2形成一个闭合的效果,我们称这种闭合的效果称之为闭包
// 闭包 = 外层函数的局部变量 + 内层函数
//调用ff函数,其实就是调用f2
println(ff(20))
//也可以直接通过如下方式调用
println(f1()(20))
*/
println("=" * 100)
//以上的代码可以转换为以下代码
def f1(): (Int) => Int = {
var a: Int = 10
def f2(b: Int): Int = {
a + b
}
f2 _
}
def f3() = {
var a: Int = 10
(b: Int) => a + b
}
/**
* 柯里化
*/
//将一个函数的一个参数列表的的多个参数,拆分成为多个参数列表
def f4()(b: Int) = {
var a: Int = 10
a + b
}
//f4在执行的时候会转为以下结构
def f5() = {
var a: Int = 10
(b: Int) => a + b
}
6)递归
/**
* 递归调用
*/
}
def digui(n:Int):Int={
if(n==1) {
return 1
}
n * digui(n-1)
}
digui(2)
7)控制抽象
/**
* 控制抽象
*
* 值调用 :将函数计算后的值进行传递
*
* 名调用 :传递的是代码块
*/
//值调用
//数据类型 Int,String,函数 参数类型=>返回值,代码块
//a : => Int 返回值是Int类型的代码块
def foo(a : => Int):Unit={
println(a)
println(a)
}
def f():Int={
println("f...")
10
}
foo(f) //结果为:f... 10 f... 10
def f1(ss: =>Unit):Unit={
ss
}
f1(
{
println("xiao")
}
)
}
8)自定义函数,实现while循环
/**
* 自定义函数,实现while循环
*/
//while循环
/*var n =10
while(n>=1){
println(n)
n-=1
}*/
//使用柯里化 实现 mywhile(循环条件)(循环体)
/**
* 柯里化的好处:
* 1、将一个参数列表的多个参数,拆分成多个参数列表,这样参数所表示的含义:清晰、明确
* 2、简化闭包的编写
*/
def mywhile(condition: => Boolean)(op: => Unit): Unit = {
if (condition) {
op
mywhile(condition)(op)
}
}
var n = 10
mywhile(n >= 1) {
println("mywhile-->" + n)
n -= 1
}
//直接使用普通的函数,实现while循环
def mywhile1(condition: => Boolean, op: => Unit): Unit = {
if (condition) {
op
mywhile1(condition, op)
}
}
var n1 = 10
mywhile1(n1 >= 1, {
println("mywhile1-->" + n1)
n1 -= 1
})
//使用闭包的形式,实现mywhile循环
def mywhile2(condition: => Boolean): (=> Unit) => Unit = {
//内层函数表示循环体
def ff(op: => Unit): Unit = {
if (condition) {
op
mywhile2(condition)(op)
}
}
ff _
}
var n2 = 10
mywhile2(n2 >= 1) {
println("mywhile2-->" + n2)
n2 -= 1
}
9)惰性函数
/**
* 惰性加载
*/
//lazy惰性加载,函数的执行会往后延,什么时候用到结果,什么时候执行函数
lazy val res: Int = sum(2,3)
println("1.------------------")
println("2."+res)
}
def sum(a: Int, b: Int): Int = {
println("3.sum被执行")
a + b
}