一、什么是scala
Scala 是一种多范式的编程语言,其设计初衷是要集成面向对象编程和函数式编程的各种特性。Scala运行于Java平台(Java虚拟机),并兼容现有的Java程序。
二、为什么要学习scala
1、优雅
2、速度快
3、能融合到hadoop生态圈
4、Spark底层源码是scala语言编写的
函数编程范式更适合用于Map/Reduce和大数据模型,它摒弃了数据与状态的计算模型,着眼于函数本身,而非执行的过程的数据和状态的处理。函数范式逻辑清晰、简单,非常适合用于处理基于不变数据的批量处理工作,这些工作基本都是通过map和reduce操作转换数据后,生成新的数据副本,然后再进行处理。像Spark,Flink,kafka等都是采用Scala开发的,所以学习好大数据,掌握scala是必要的。
三、Scala基础语法知识
1、语言特点
1、面向对象,函数式编程
2、兼容Java,类库可以互相调用
3、语法简洁,代码行短,类型自动推断,抽象控制
2、Scala解释器
Scala解释器读到一个表达式,对它进行求值,将它打印出来,接着再继续读下一个表达式。这个过程被称做读取read–求值eval–打印print–循环loop,即:REPL。实际发生的是,你输入的内容被快速地编译成字节码,然后这段字节码交由Java虚拟机执行。
3、变量定义
var/val 变量名[:变量类型]=变量值
中括号内的内容可以省略,因为scala语言可以自动推断数据类型。
1、Var:修饰的变量,引用可以改变
2、Val:修饰的变量,引用不可以改变
4、数据类型
在java当中,顶级父类是object,在scala当中,顶级父类是Any。
1、Any下面有两个子类,一个是AnyVal,一个是AnyRef
(1)AnyVal:值类型,指的是整型,浮点型,字符型,布尔类型
(2)AnyRef:引用类型,指的是scala的集合,scala的类,java的类
AnyRef有一个子类,是null
AnyVal和AnyRef共有的子类是Nothing
5、操作符说明
1、Scala调用一些方法或者函数的时候,如果方法或者函数是空参的,可以省略掉()。
2、在Scala中一行表示的结尾不像Java需要使用";",Scala可以省略。
6、流程控制
1、分支语句
var x = -4
//分支语句
val res = {
if (x > 0) {
println(x)
} else {
"ff"
}
}
println(res)//ff
2、块表达式
//块表达式 scala 的返回值可以省略return关键字,表达式的最后一句,作为表达式的返回值返回
//return 关键字通常使用在函数中进行逻辑的终止,比如循环
var res01={
1+2
3+4
5>9
}
println(res01)//false
3、while循环
//while循环 ++ --等自增运算符scala不支持,因为已经被scala集合的对应函数所占据
var n=1
var res = while(n<=10){
n+=1
println(n)
}
println(res)//输出:()
//注:while语句没有输出值,但是在Scala中,认为每个表达式都有值,这个问题的解决方案是引入一个Unit类,写作(),叫做无用占位符
4、do While循环
var sum = 0
var s =1
do{
sum += s
s+=1
println(s"${s}---${sum}")
}while(s<=10)
5、for循环
var sum =0
//to遍历 1 to 5:[1,2,3...5],左右均为闭合区间,包含左侧元素,也包含右侧元素。
for (i<- 1 to 5){
sum+=i
println(s"${sum}---${i}")
}
for(i<- 1.to(8)){
println(i)
}
//until遍历 1 until(5):[1,2,3...5),左闭右开区间,包含左侧元素,不包含右侧元素
for(i <- 1 until(5)){
println(i)//1 2 3 4
}
//range遍历 左闭右开区间,包含左侧元素,不包含右侧元素,三个参数分别为开始、结束和增量值
for(i<-Range(1,6,2)){
println(i)//1 3 5
}
//倒序输出
for(i<-(1.to(5)).reverse){
println(i)
}
for(i<- Range(3,0,-1)){
println(i)
}
//scala守卫模式
for(i<- 1 to 10 if i%2==0){
println("---"+i)
}
//引入变量
for(i<-1 to 5; j=5-i){
println(s"$i---$j")
}
//九九乘法表
for(i <- 1 to 9;j <- 1 to i){
print(s"$i*$j=${i*j}\t")
if(i==j){
println()
}
}
6、循环终止
//1.使用return
for(j<- 1 to 6){
if(j==3){
return
}
println(j)
}
//2.使用循环条件来控制
var i =0;
do{
i+=1;
println(i)
}while(i<5)
//3.使用breakable函数体来控制
//相当于continue
for(i<- 1 to 20){
breakable{
if(i==12){
break()
}
println(i)
}
}
//相当于break
breakable{
for(i <- 1 to 5){
if(i==3){
break()
}
println(i)
}
}
8、懒加载(lazy)
被lazy所修饰的变量,只有当第一次被使用的时候才会进行初始化,没有使用之前只是记录了存在,检查语法结构是否正确。可以节省一定的资源空间。
7、方法定义
//方法的最后一句就是该方法的返回值,函数也一样,return可以省略,如果有return,就一定要加上返回值类型
//def 方法名 (参数名:参数类型,参数名:参数类型)={方法体}
def hello(name:String,age:Int)={
name+age
}
val res=hello("hhh",22)
println(res) //hhh22
//def 方法名(参数名:参数类型,参数名:参数类型):返回值类型={方法体}
def hello2(name:String,age:Int):String={
name
}
val res2=hello2("fff",22)
println(res2)
//单行方法
def hello3(age:Int)={
age
}
val res3=hello3(22)
println(res3)
//空参方法
//定义方法时有小括号,调用的时候可带可不带小括号
//定义的时候没有小括号,调用的时候不能加小括号
def hello4={
println("errr")
}
hello4
//指定参数的方法,带名参数调用方法
def hello5(name:String,age:Int) ={
age+name
}
val rrr=hello5(age=44,name="xiaowena")
println(rrr)
//带默认值的方法
def hello6(name:String="hhh",age:Int=19)={
name+age
}
val eee=hello6("jjj")
println(eee)//jjj19
val eee1=hello6("jjj",33)
println(eee1)//jjj33
val eee2=hello6()
println(eee2)//hhh19
//多个参数
def hello7(x:String,y:Int*)={
var sum = 0
for(i<-y){
sum+=1
}
sum
}
val hh=hello7("mulity",3,4,5,6,7)
println(hh)//5
//可变参数
var arr=Array(1,2,3,4,5)
def hello8(name:String,age:Int*)={
var sum=0
for(i<-age){
sum+=i
}
sum
}
//传递数组类型的要以这样arr: _*的方式
val res4=hello8("tom",arr: _*)
println(res4)
//递归方法
def factory(i:Int):Int={
if(i==0){
1
}else{
i*factory(i-1)
}
}
val jj=factory(5)
println(jj)
8、函数定义
//创建函数 俗称匿名函数
//val 函数名=(参数名:参数类型,参数名:参数类型)=>{函数体}
val fun=(name:String,age:Int)=>{
name+age
}
val ff=fun("hello",22)
println(ff)
//val 函数名:(参数类型,参数类型)=>返回值类型={函数体}
val fun2:(String,Int)=>String={
(name,age)=>{
println("jjjj")
println(age)
name
}
}
val ff2=fun2("haoop",12)
println(ff2)
//原始的创建函数的真实过程
val fun3 = new Function3[String,Int,Int,String] {
override def apply(v1: String, v2: Int, v3: Int):String = {
v1+v2+v3
}
}
val ff3:String=fun3("xiaom",3,4)
println(ff3)
//函数作为参数传递到方法中
def hello(f:(Int,Int)=>Int)={
f(2,3)
}
val fun5:(Int,Int)=>Int={
(x,y)=>{
x-y
}
}
val ff4=hello(fun5)
println(ff4)//-1
//创建函数
val function = new Function2[String, Int, String] {
override def apply(v1: String, v2: Int): String = {
v1 + v2
}
}
val fun6:String=function("hhh",77)
//调用函数并赋值
println(fun6)//hhh77
9、方法和函数的区别
(1)方法和函数定义形式不同
(2)方法也是函数,函数也是对象
(3)函数可以作为参数传递到方法中去
(4)方法名+空格+下划线(_),就可以把方法变成函数