Scala
官方网址: http://www.scala-lang.org
1.Scala是一门面向对象的语言
2.Scala也是一门面向函数的语言。在面向函数编程的语言中,函数是一等公民,函数可以当作参数进行赋值和传递,scala是一门现代编程语言,吸收了很多语言的优点:
java,ruby, c,lisp 等语言。
Scala不适合初级的编程学习,需要有一定的语言基础。
下载地址
https://www.scala-lang.org/download/2.11.7.html-----scala
http://scala-ide.org/documentation.html-------ide
先安装scala-------可以通过命令行操作(cmd)
我这里使用eclipse-ide操作
Scala-----api手册
https://www.scala-lang.org/api/current/scala/Int.html
代码
/**
知识点
学习String类型常用的操作知识点
1.scala在返回结果时,如果没有主动接收,会默认分配一个标识符名字。形式:res递增数字
2.scala可以无缝衔接java的类库,可以调用java类库的所有方法,比如:String.split()方法
3.scala是通过scalac编译成.class文件,最终在JVM运行
4.scala底层有一种隐式转换机制,可以将java的String转换成scala的String0ps类型比如take takeRight等方法都是来自于Stringops类型。
5.scala的类型转换,格式固定: to目标类型
**/
object Demo01 {
val s1="hello world" //> s1 : String = hello world
val r1=s1.split(" ") //> r1 : Array[String] = Array(hello, world)
//前n个元素
val r2=s1.take(5) //> r2 : String = hello
//后n个元素
val r3=s1.takeRight(5) //> r3 : String = world
//删除头n个元素,并返回剩余元素
val v4=s1.drop(1) //> v4 : String = ello world
//删除尾部nN个元素,返回元素
val v5=s1.dropRight(4) //> v5 : String = hello w
val s2="doc1.txt" //> s2 : String = doc1.txt
//操作元素返回文件名 doc1
val s3=s2.split("\\.")(0) //> s3 : String = doc1
val s4=s2.dropRight(4) //> s4 : String = doc1
//重复n次
val r8=s1*3 //> r8 : String = hello worldhello worldhello world
//拼接
val r9=s1+s2 //> r9 : String = hello worlddoc1.txt
//去重
val r10=s1.distinct //> r10 : String = helo wrd
//反转
val r11=s1.reverse //> r11 : String = dlrow olleh
val s5="100" //> s5 : String = 100
val s6=s5.toInt //> s6 : Int = 100
val s7=s5.toDouble //> s7 : Double = 100.0
for(j<-1 to 9){
for(i<-1 to j){
print(i+"*"+j+"="+i*j+"\t")
}
println
} //> 1*1=1
//| 1*2=2 2*2=4
//| 1*3=3 2*3=6 3*3=9
//| 1*4=4 2*4=8 3*4=12 4*4=16
//| 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
//| 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
//| 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
//| 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
//| 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
//|
}
/**
知识点
1.scala worksheet是交互式编译模式,特点是:左侧写代码,保存后ctrl+s
这种模式一般用于测试和练习
2.scala的变量和常量类型。变量用var ,声明之后可以修改。常量用val,一经声明,不允许更改
3.scala每行语句结束后,不需要加;
4.scala如果在一行中写多条语句,需要用;隔开
5.scala不需要显示的声明数据类型,可以根据结果进行自动推断
6.scala也支持显示声明类型,形式: var(val)标识符:类型=值
**/
object Demo02 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
println("hello") //> hello
//声明一个变量
var v1=100 //> v1 : Int = 100
v1=200
//声明一个常量
val v2=100 //> v2 : Int = 100
//分号使用
var v3=100;var v4=200 //> v3 : Int = 100
//| v4 : Int = 200
val v5="hello" //> v5 : String = hello
val v6=Array(1,2,3,4) //> v6 : Array[Int] = Array(1, 2, 3, 4)
val v7:String="hello" //> v7 : String = hello
}
/**
知识点
数值类型的常用方法
1. to 方法用于生成一个指定的区间。一般用于生成循环的区间范围
2.scala的集合( collection)是一个大的概念,包含∶
Array ,List, set,Map ,Range , Tuple
3.scala中没有基本类型,都是对象和方法。所以从这个角度来看,scala的面向对象比java更彻底
4.scala底层会通过隐式转换机制,将基本类型转成scala对应的对象类型
int->RichInt
flota->RichFloat
byte->RichByte
char->Richchar
6.scala有四种前缀操作符,分别是∶正号负号布尔取反,进制取反
6.scala有四种前缀操作符,分别是:正号+,负号-,布尔取反!,进制取反~
注意︰前缀操作符需要加空格
7.在使用前缀操作符时,为了避免引起歧义,可以通过unary_(+,-, ! ,~)
8.scala的运算符优先级同java,此外scala也支持通过调用方法的形式做运算(按方法的调用顺序执行运算)
9.scala通用的化简规则:在调用方法时,如果方法的参数只有一个,则.()可以省略
**/
object Demo03 {
val i1=1 //> i1 : Int = 1
val r1=i1.to(5) //> r1 : scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
val r111=i1 to 5 //> r111 : scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
//生成区间,指定步长
val r2=i1.to(5,2) //> r2 : scala.collection.immutable.Range.Inclusive = Range(1, 3, 5)
//生成区间,不包含尾元素
val r3=i1.until(5) //> r3 : scala.collection.immutable.Range = Range(1, 2, 3, 4)
val r4=i1.until(5, 2) //> r4 : scala.collection.immutable.Range = Range(1, 3)
val r5=1.to(5) //> r5 : scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
//正数2
val r6= +2 //> r6 : Int = 2
//负数2
val r7= -2 //> r7 : Int = -2
//布尔取反
val r8= !true //> r8 : Boolean = false
//进制取反
val r9= ~0Xff //> r9 : Int = -256
val r10=2.unary_+ //> r10 : Int = 2
val r11=2.unary_- //> r11 : Int = -2
val r12=true.unary_! //> r12 : Boolean = false
val r13=0xff.unary_~ //> r13 : Int = -256
val r14=2+3*4 //> r14 : Int = 14
//利用方法运算
val r15=2.+(3).*(4) //> r15 : Int = 20
val s3=111 //> s3 : Int = 111
val s4=s3.toString() //> s4 : String = 111
}
/**
知识点
1.scala的if else用法及结构同java
2.scala的通用的化简规则:如果方法体{}里只有一行代码,则方法体可以省略
3.scala的if else有返回值,可以接(这一点不同于java)
4.scala的Unit类比于java的void,即空类型
5.scala的通过规则:会将方法体{}的最后一行代码当做返回值返回(不需要加return)
6.print函数是打印不换行。println打印换行。打印函数的返回值类型就是Unit
7.scala的Any可以类比于java的object。建议if else 的返回值类型保持一致
9.scala在通过下标操作集合类型时,用的是(index),不同于java的[index]
10.scala或spark的开发习惯:一般声明数据时用常量(val),计数或索引用变量(var)
**/
object Demo04 {
val v1=5 //> v1 : Int = 5
val r1=if(v1>5){
println("big")
"big"
100
" "
}else{
println("small")
"small"
//200
} //> small
//| r1 : String = small
if(v1>5) println("big") else println("small")
//> small
if(v1>5){
println("big")
}else if(v1==5){
println("equal")
}else{
println("small")
} //> equal
val a1=Array(1,2,3,4) //> a1 : Array[Int] = Array(1, 2, 3, 4)
var index=0 //> index : Int = 0
while(index<a1.length){
println(a1(index))
index=index+1
} //> 1
//| 2
//| 3
//| 4
}
/**
知识点
**/
object Demo05 {
var aa="aaaaa" //> aa : String = aaaaa
println("99999999") //> 99999999
val a1=Array(1,2,3,4) //> a1 : Array[Int] = Array(1, 2, 3, 4)
for(i<-a1){
println(i) //> 1
//| 2
//| 3
//| 4
}
//--要求用for循环遍历1到10的数字并打印
for(i<-1 to 10)println(i) //> 1
//| 2
//| 3
//| 4
//| 5
//| 6
//| 7
//| 8
//| 9
//| 10
//--用scala的for循环打印99乘法表
// --1*1=1
//--1*2=2 2*2=4
// --1*3=3 2*3=63*3=9
// --.... . . . . .. .
for(j<-1 to 9){
for(i<-1 to j){
if(j!=i){
print(i+"*"+j+"="+i*j+"\t")
}else{
println(i+"*"+j+"="+i*j)
} //> 1*1=1
//| 1*2=2 2*2=4
//| 1*3=3 2*3=6 3*3=9
//| 1*4=4 2*4=8 3*4=12 4*4=16
//| 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
//| 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
//| 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
//| 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
//| 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
}
}
for(j<-1 to 9){
for(i<-1 to j){
print(i+"*"+j+"="+i*j+"\t")}
println
} //> 1*1=1
//| 1*2=2 2*2=4
//| 1*3=3 2*3=6 3*3=9
//| 1*4=4 2*4=8 3*4=12 4*4=16
//| 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
//| 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
//| 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
//| 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
//| 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
//|
//--用for循环,遍历1以10的数字,只打印>6的偶数数字
for(i<-0.to(10,2)){
if(i>6){
print(i+"\t")
} //> 8 10
}
println //>
for(i<-1 to 10){
if(i>6&&i%2==0){println(i)}
//> 8
//| 10
}
for(i<-1 to 10;if(i>6&&i%2==0)){
println(i)
//> 8
//| 10
}
for(i<-1 to 10;if(i>6&&i%2==0))println(i)
//> 8
//| 10
for(a<-1 to 9;b<-1 to a;val sep=if(a==b)"\r\n" else "\t")
{print(b+"*"+a+"="+b*a+sep)}
//> 1*1=1
//| 1*2=2 2*2=4
//| 1*3=3 2*3=6 3*3=9
//| 1*4=4 2*4=8 3*4=12 4*4=16
//| 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
//| 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
//| 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
//| 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
//| 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
for(a<-1 to 9;b<-1 to a;val sep=if(a==b)"\r\n" else "\t")
{print(s"$b*$a=${b*a}$sep")}
//> 1*1=1
//| 1*2=2 2*2=4
//| 1*3=3 2*3=6 3*3=9
//| 1*4=4 2*4=8 3*4=12 4*4=16
//| 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
//| 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
//| 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
//| 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
//| 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
//map
val m1=Map("tom"->23,"rose"->30,"jim"->35)
//> m1 : scala.collection.immutable.Map[String,Int] = Map(tom -> 23, rose -> 3
//| 0, jim -> 35)
for(i<-m1){
println(i)
//> (tom,23)
//| (rose,30)
//| (jim,35)
}
for((k,v)<-m1){
println(k)
//> tom
//| rose
//| jim
}
for((k,v)<-m1){
println(v)
//> 23
//| 30
//| 35
}
//--学习for yield推导式。
//--作用:遍历某一种集合类型,并返回对应的一个新的集合类型
//--比如:遍历一个Array ,则返回一个新Array。遍历一个Map,返回一个新Map
val a2=Array(1,2,3,4)
//> a2 : Array[Int] = Array(1, 2, 3, 4)
val a3=for(i<-a2)yield{i*2}
//> a3 : Array[Int] = Array(2, 4, 6, 8)
val m2=Map("tom"->23,"rose"->30,"jim"->35)
//> m2 : scala.collection.immutable.Map[String,Int] = Map(tom -> 23, rose -> 3
//| 0, jim -> 35)
val a5=for((k,v)<-m2)yield{(k,v+10)}
//> a5 : scala.collection.immutable.Map[String,Int] = Map(tom -> 33, rose -> 4
//| 0, jim -> 45)
// 思考题
// 有一副扑克牌,现在随机抽出一张牌,要求想出一种方法,能够知道抽出的牌是什么牌(比如梅花2)
// 想出比遍历方法更好的方法来
}
import scala.util.control.Exception.Catch
import scala.util.control.Exception.Finally
/**
知识点
1.scala的异常处理机制同java I
2.scala异常捕获机制,通过case来匹配具体的异常然后进行处理
3.scala中对象都拥有match方法(用于匹配),类比于java的switch case
match语句有返回值,可以接
**/
object Demo06 {
println() //>
try{
//throw new NullPointerException
throw new RuntimeException
}catch{
case t:NullPointerException=>{
//具体的异常处理
println("null err")
}
case t:Exception=>{
println("other err")
}
}finally{
println("end")
} //> other err
//| end
val s1="hello" //> s1 : String = hello
s1 match{
case "hello"=>{
println("1")
100
}
case "world"=>{
println("2")
200
}
} //> 1
//| res0: Int = 100
}
import scala.util.control.Exception.Catch
import scala.util.control.Exception.Finally
import util.control.Breaks._
/**
知识点
1.scala实现break或continue需要导包,scala导包机制同java,同步import关键字导入
2.breakable()如果在循环外,break是跳出跳出循环的效果。
3.breakable()如果在循环内,break是continue效果
**/
object Demo07 {
//习惯将for循环写在breakable方法里,此时break是跳出循环的意思
breakable(
for(i<- 1 to 10){
if(i>8){
break
}else{
println(i)
}
}
) //> 1
//| 2
//| 3
//| 4
//| 5
//| 6
//| 7
//| 8
//此时是跳出当前循环的意思
for(i<-1 to 10){
breakable(
if(i==8){
break
}else{
println(i)
}
) //> 1
//| 2
//| 3
//| 4
//| 5
//| 6
//| 7
//| 9
//| 10
}
}
/**重点∶学习scala函数的声明和调用
知识点
1.scala通过def关键字来声明函数,格式: def 函数名参数列表):返回值类型={方法体}
2.scala函数会将方法体最后一行代码当做返回值返回,不需要加return关键字
3.scala函数有自动推断机制,可以根据返回值类型自动推断。
4.scala函数声明时如果不加=,则返回值一律为Unit.所以建议在定义函数时都加=
5.scala的泛型用[门]来声明,比如Array[Int]。不同于java的<>
6.scala函数支持默认参数机制,形式:def函数名(形参名∶参数类型=默认值)={}
7.scala函数支持变长参数机制,变长参数本质上是一种集合类型(可以认为就是一个数组)
注意∶在声明变长参数时,必须位于参数列表的最后
**/
object Demo08 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
def f1():String={
"hello"
} //> f1: ()String
def f2():Int={
100
} //> f2: ()Int
def f3()={
"hello"
} //> f3: ()String
def f4()={
Array(1,2,3,4)
} //> f4: ()Array[Int]
def f5(){
"hello"
} //> f5: ()Unit
def f6(a:Int,b:Int)={
a+b
} //> f6: (a: Int, b: Int)Int
f6(2,3) //> res0: Int = 5
//定义一个f7函数,接受一个整型数组。函数的作用---遍历数组并打印
def f7(a:Array[Int])={
for(i<-a){
println(i)
}
} //> f7: (a: Array[Int])Unit
f7(Array(1,2,3,4)) //> 1
//| 2
//| 3
//| 4
def f8(a:Int,b:Int=100,c:Int=200)={
a+b+c
} //> f8: (a: Int, b: Int, c: Int)Int
f8(5) //> res1: Int = 305
f8(5,5) //> res2: Int = 210
def f9(a:Int*)={
for(i<-a)println(i)
} //> f9: (a: Int*)Unit
f9(1,2,3,4) //> 1
//| 2
//| 3
//| 4
def f10(a:String*)={
} //> f10: (a: String*)Unit
f10("ss","aa")
def ff10(a:Int,b:Int*){
} //> ff10: (a: Int, b: Int*)Unit
}
/**
知识点
scala的函数种类共4种
1.成员函数,定义在类内部的函数,作为类的一份子,称为类的成员函数
2.本地函数:内嵌在函数内的函数,称为本地函数。本地函数无法通过对象直接调用
3.匿名函数
4.高阶函数
**/
/**
知识点
scala的函数种类共4种
1.成员函数,定义在类内部的函数,作为类的一份子,称为类的成员函数
2.本地函数:内嵌在函数内的函数,称为本地函数。本地函数无法通过对象直接调用
3.匿名函数(重点)
匿名函数的特点:1、没有函数名2、参数列表()和方法体{}的连接符是=>
匿名函数的作用:1、当以当作参数进行赋值2、当作参数进行传递
4.高阶函数(重点)
将函数当作传递的函数就是高阶函数
高阶函数是来自于函数式编程的特点。
5.所以scala语言既是面向对象的语言,也是面向函数的语言(高阶函数)
在面向函数编程语言中,函数是一等公民,即可以将函数当做参数进行赋值或传递
6.匿名函数的通用的化简规则1:如果匿名函数参数类型可以推断出来,则参数谈型可以省略
7.匿名函数的通用的化简规则2:如果匿名函数的参数列表只有1个参数,则参数列表的()可以不写
**/
object Demo09 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val p1=new Person() //> p1 : Person = Person@7a79be86
p1.say() //> hello
def f1(a:Int,b:Int)={
a+b
} //> f1: (a: Int, b: Int)Int
//定义一个匿名函数
// (a:Int,b:Int)=>{a+b}
//把匿名函数当作参数赋值
val f2=(a:Int,b:Int)=>{a+b} //> f2 : (Int, Int) => Int = <function2>
f2(2,3) //> res0: Int = 5
//当作参数进行传递
//高阶函数
def f3(a:Int,b:Int,f:(Int,Int)=>Int)={
f(a,b)
} //> f3: (a: Int, b: Int, f: (Int, Int) => Int)Int
//求a+b
f3(2,3,(a:Int,b:Int)=>{a+b}) //> res1: Int = 5
f3(2,3,(a,b)=>{a+b}) //> res2: Int = 5
//定义f4高阶函数,将两个参数拼接
def f4(a:String,b:String,f:(String,String)=>String)={
f(a,b)
} //> f4: (a: String, b: String, f: (String, String) => String)String
f4("hello","world",(a:String,b:String)=>a+b) //> res3: String = helloworld
def f5(a:String,f:(String)=>Array[String])={
f(a)
} //> f5: (a: String, f: String => Array[String])Array[String]
f5("hello,world",(a:String)=>{a.split(",")}) //> res4: Array[String] = Array(hello, world)
f5("hello,world",a=>{a.split(",")}) //> res5: Array[String] = Array(hello, world)
f5("hello,world",a=>a.split(",")) //> res6: Array[String] = Array(hello, world)
def f6(a:String,b:Int,f:(String,Int)=>String)={
f(a,b)
} //> f6: (a: String, b: Int, f: (String, Int) => String)String
f6("hello",3,(a:String,b:Int)=>a*b) //> res7: String = hellohellohello
val v1=Array(1,3,5) //> v1 : Array[Int] = Array(1, 3, 5)
for(i<-v1){
println(i) //> 1
//| 3
//| 5
}
def f7(a:Array[Int],f:(Array[Int])=>Unit)={
f(a)
} //> f7: (a: Array[Int], f: Array[Int] => Unit)Unit
f7(Array(1,2,3,4),(a:Array[Int])=>{
for(i<-a){println(i)}
}) //> 1
//| 2
//| 3
//| 4
val a1=Array(1,2,3,4,5,6) //> a1 : Array[Int] = Array(1, 2, 3, 4, 5, 6)
//操作a1,传入一个匿名函数,过滤出偶数
a1.filter {(x:Int)=>{x%2==0&&x>4}} //> res8: Array[Int] = Array(6)
val a2=Array("tom M 23","rose F 18","jim M 30")//> a2 : Array[String] = Array(tom M 23, rose F 18, jim M 30)
//操作a2过滤出男性数据
a2.filter { (x:String) => {
x.split(" ")(1)=="M"
} } //> res9: Array[String] = Array(tom M 23, jim M 30)
//数组遍历
a1.foreach { (x:Int) => {println(x)} } //> 1
//| 2
//| 3
//| 4
//| 5
//| 6
a1.foreach { x => println(x) } //> 1
//| 2
//| 3
//| 4
//| 5
//| 6
a1.count { x => x%2==0 } //> res10: Int = 3
}
/**
学习scala的柯里化机制,这种机制来自于函数式编程
作用1:可以将一个接受多个参数的函数转变为接受单一参数的函数
作用2:可以实现用户自建的控制结构def函数名(普通参数列表)(匿名函数列表)=(}
使得调用层次更加清晰
*/
object Demo10 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
def f1(a:Int,b:Int)={a+b} //> f1: (a: Int, b: Int)Int
def f11(a:Int)(b:Int)={a+b} //> f11: (a: Int)(b: Int)Int
f11(2)(3) //> res0: Int = 5
def f2(a:Int,b:Int,c:Int)={a+b+b} //> f2: (a: Int, b: Int, c: Int)Int
def f21(a:Int)(b:Int)(c:Int)={a+b+c} //> f21: (a: Int)(b: Int)(c: Int)Int
def f22(a:Int)(b:Int,c:Int)={a+b+c} //> f22: (a: Int)(b: Int, c: Int)Int
def f23(a:Int,b:Int)(c:Int)={a+b+c} //> f23: (a: Int, b: Int)(c: Int)Int
def f3(a:Int,b:Int,f:(Int,Int)=>Int)={f(a,b)} //> f3: (a: Int, b: Int, f: (Int, Int) => Int)Int
def f31(a:Int)(b:Int)(f:(Int,Int)=>Int)={f(a,b)}//> f31: (a: Int)(b: Int)(f: (Int, Int) => Int)Int
def f32(a:Int)(b:Int,f:(Int,Int)=>Int)={f(a,b)} //> f32: (a: Int)(b: Int, f: (Int, Int) => Int)Int
//--留意这种形式,特点是:一部分是普通参数,另一部分是匿名函数
//--针对这种结构,称为用户自建的控制结构,调用层次更清晰
def f33(a:Int,b:Int)(f:(Int,Int)=>Int)={f(a,b)} //> f33: (a: Int, b: Int)(f: (Int, Int) => Int)Int
f33(5,10)(_+_) //> res1: Int = 15
}
练习
/**
学习scala写递归函数
1.scala递归函数的返回值类型必须显示声明,不能用自动推断
2.写递归的技巧,掌握两个要素:要素①找出函数关系
要素②找出结束条件
3.scala递归函数的结束条件返回值必须要return关键字返回
*/
/**
学习scala写递归函数
1.scala递归函数的返回值类型必须显示声明,不能用自动推断
2.写递归的技巧,掌握两个要素:要素①找出函数关系
要素②找出结束条件
3.scala递归函数的结束条件返回值必须要return关键字返回
*/
object Demo11 {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
//--给定一个斐波那契数列
//--2 3 5 8 13 21
//--目标是写一个递归函数,判断数列第n项的数字是多少
//-一函数关系:f(n)=f(n-1)+f(n-2)
//-–结束条件:f()=2 f(1)=3
def f1(n:Int):Int={
if(n==0){return 2}
if(n==1){return 3}
else f1(n-1)+f1(n-2)
} //> f1: (n: Int)Int
f1(2) //> res0: Int = 5
//--2 3 4 9 16 81 .
//--编写递归函数f2(n) ,判断第n项的数字是多少
def f2(n:Int):Int={
if(n==0) return 2
if(n==1) return 3
else f2(n-2)*f2(n-2)
} //> f2: (n: Int)Int
f2(5) //> res1: Int = 81
// --2 3 4 9 8 27 16 81 ...
//--编写递归函数f3(n),判断第n项的数字是多少
def f3(n:Int):Int={
if(n==0) return 2
if(n==1) return 3
if(n%2==0) f3(n-2)*2
else f3(n-2)*3
} //> f3: (n: Int)Int
f3(8) //> res2: Int = 32
//10-1 循环输出
for(i<-0 to 9)println(10-i) //> 10
//| 9
//| 8
//| 7
//| 6
//| 5
//| 4
//| 3
//| 2
//| 1
//=========================================
//利用一个函数,n-1 遍历输出
//方式0
def f4(n:Int):Unit={
for(i<-0 to n-1)println(n-i)
} //> f4: (n: Int)Unit
f4(10) //> 10
//| 9
//| 8
//| 7
//| 6
//| 5
//| 4
//| 3
//| 2
//| 1
//方式1
for (i<-10 to 0 by -1) println(i) //> 10
//| 9
//| 8
//| 7
//| 6
//| 5
//| 4
//| 3
//| 2
//| 1
//| 0
//方式2
for( i<-0 to 10 reverse) println(i) //> 10
//| 9
//| 8
//| 7
//| 6
//| 5
//| 4
//| 3
//| 2
//| 1
//| 0
//===================================================
//扑克牌,确定抽出的一张是什么牌
//红桃A-K 1-13 黑桃A-K 14-26 梅花A-K 27-39 方块A-K 40-52 大王 53 小王 54
//生成一个数字---模拟,实际中只能确定剩余牌数
var a1=scala.util.Random.nextInt(100)
//> a1 : Int = 95
//模拟剩余和
var num=0 //> num : Int = 0
var i=1 //> i : Int = 1
while(i<55) {
num=num+i
i+=1
}
//实际中应该是是确定了这个总和,去求a1
println(num-a1) //> 1390
def f5(n:Int):Unit={
var k1=n/13
var k2=n%13
if(n==53) println("dawang")
if(n==54) println("xiaowang")
if(k1==1&&k2==0) println("red-K")
if(k1==0) println("red"+k2)
if(k1==2&&k2==0) println("black-K")
if(k1==1) println("black"+k2)
if(k1==3&&k2==0) println("mh-K")
if(k1==2) println("mh"+k2)
if(k1==4&&k2==0) println("fk-K")
if(k1==3) println("fk"+k2)
} //> f5: (n: Int)Unit
f5(a1)
///===========
//123456
//214365
//n为偶数
//将左右两个数替换 1 2 -----2 1
//方式1
var arr=Array(1,2,3,4,5,6,7,8,9,10) //> arr : Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val len=arr.length //> len : Int = 10
var ii=2 //> ii : Int = 2
var sum="" //> sum : String = ""
while(ii<=len){
sum+=(arr(ii-1).toString())+(arr(ii-2).toString())
ii+=2
}
println(sum) //> 21436587109
//方式2
var array=Array(1,2,3,4,5,6) //> array : Array[Int] = Array(1, 2, 3, 4, 5, 6)
def resv(arr:Array[Int])={
for(i<-0 until(arr.length-1, 2)){
val t=arr(i)
arr(i)=arr(i+1)
arr(i+1)=t
}
} //> resv: (arr: Array[Int])Unit
resv(array)
array //> res3: Array[Int] = Array(2, 1, 4, 3, 6, 5)
//编写函数计算x的n次方,其中n是整数,要考虑等n是0,正偶数,正奇数,负数这几种情况。
//比如当x=2时,此函数要算出2^4,2^3,2^0,2^(-1)对应的值
def mi(x:Double,n:Int):Double={
if(n==0) return 1
else if(n>0&&n%2==0){
mi(x,n/2)*mi(x,n/2)
}else if(n>0&&n%2==1){
mi(x,n-1)*x
}else{
1/mi(x,-n)
}
} //> mi: (x: Double, n: Int)Double
mi(2,3) //> res4: Double = 8.0
//
val m2=Map("book"->10,"gun"->100,"ipad"->1000)//> m2 : scala.collection.immutable.Map[String,Int] = Map(book -> 10, gun -> 1
//| 00, ipad -> 1000)
val a5=for((k,v)<-m2)yield{(k,v*0.9)}
//> a5 : scala.collection.immutable.Map[String,Double] = Map(book -> 9.0, gun
//| -> 90.0, ipad -> 900.0)
}