Scala基础语法
概述
Scala语言是一门基于JVM的编程语言,具有强大的功能,它即具有类似Java的面向对象的特性,而且也类似于C语言面向过程,函数也是一等公民,即不需要在隶属于哪一个类就可以执行。基于JVM的特性,使得scala和Java可以无缝互操作,scala可以任意操作Java的代码,两者的联系紧密。
数据类型
数据类型 | 描述 |
---|---|
Byte | 8位有符号补码整数。数值区间为 -128 到 127 |
Short | 16位有符号补码整数。数值区间为 -32768 到 32767 |
Int | 32位有符号补码整数。数值区间为 -2147483648 到 2147483647 |
Long | 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807 |
Float | 32 位, IEEE 754标准的单精度浮点数 |
Double | 64 位 IEEE 754标准的双精度浮点数 |
Char | 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF |
String | 字符序列 |
Boolean | true或false |
Unit | 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。 |
Null | null |
Nothing | Nothing类型在Scala的类层级的最低端;它是任何其他类型的子类型。 |
Any | Any是所有其他类的超类 |
AnyRef | AnyRef类是Scala里所有引用类(reference class)的基类 |
变量的定义
定义变量用var或者val关键字。
语法:
var 变量名称(:数据类型) = 变量值
val 变量名称(:数据类型) = 变量值
使用val修饰的变量,值不能被修改,相当于Java中的final修饰的变量。
定义变量时,可以指定数据类型,也可以不指定,不指定时编译器会自动推测变量的数据类型。
val name = "scala"
var age = 18
var nickname:String = "sl"
字符串的格式化输出
普通输出:
println("name=" + name + ",age=" + age)
'f’插值器:
在使用‘f’插值器时,所有变量引用都应该是printf样式格式说明符,如%d,%i,%f等。
println(f"$name%s,$age%d")
's’插值器:
‘s’允许在处理字符串时直接使用变量。
在println语句中将String变量($name)附加到普通字符串中。
println(s"my name is $name,age is $age")
条件表达式
表达式
if ( ){ }else if(){ }.....else{ }
块表达式 { }
#有默认返回值,有值得就是最后一行就是值
循环语句/yeild关键字
在scala中有for循环和while循环,用for循环比较多。
for循环语法结构:for(i <- 表达式/数组/集合)
// 定义个数组,元素为1到6
val array = Array(1, 2, 3, 4, 5, 6)
array: Array[Int] = Array(1, 2, 3, 4, 5, 6)
// 遍历打印数组中的每一个元素
for(ele <- array){ // 类似Java中的增强for循环
| println(ele)}
1
2
3
4
5
6
// 通过角标获取数组中的元素
// 定义一个0到5的角标范围
for(i <- 0 to 5){ // 0 to 5 =>会生成一个范围集合range(0, 1, 2, 3, 4, 5)
| println(array(i))}
1
2
3
4
5
6
for(i <- 0 until 6){ // 0 until 6 =>会生成一个范围集合range(0, 1, 2, 3, 4, 5)
| println(array(i))}
1
2
3
4
5
6
// to 和 until的区别就是to包含前后否为闭区间,until为前闭后开区间
// 打印数组中的偶数
for(e <- array if e % 2 ==0){ // for表达式中可以增加守卫
| println(e)}
2
4
6
scala> for(i <-1 to 3; j <- 1 to 3 if i != j){
| println((10 * i + j) + " ")}
12
13
21
23
31
32
break和continue
#break功能的实现
breakable{
for(i<-1 to 10) {
println(i)
//for表达式中需要退出循环的地方,添加break()方法调用
if(i>=5) break()
}
}
#continue功能的实现
for(i<- 1 to 10){
breakable{
if(i%3==0){break()}
println(i)
}
}
数据结构
数组
#定长数组
val a =new Array[Int](100)
Array("java","scala","python")
#变长数组
val a = ArrayBuffer[Int]()
val a = ArrayBuffer("hadoop", "storm", "spark")
#常用方法
sum, max, min, sorted , reverse反转
元组
val stu=(1,"zhangsan",20,"beijing")
val stu = "zhangsan"->20#或者箭头
#访问
stu._1 stu._2
#元组不可变不能重新赋值
列表
#有先后顺序
####不可变列表
//创建一个不可变列表,存放以下几个元素(1,2,3,4)
val a = List(1,2,3,4)
//使用Nil创建一个不可变的空列表
val a =Nil
//使用::方法创建列表,包含-2、-1两个元素
val a = -2 :: -1 :: Nil
####可变列表
val a = ListBuffer[Int]()
//创建一个可变列表,包含以下元素:1,2,3,4
val a = ListBuffer(1,2,3,4)
#常用方法
a.toList #转换为List
a.toArray#转换为Array
#常用操作
· 扁平化(flaten)***
· 判断列表是否为空(isEmpty)
· 拼接两个列表(++)
· 获取列表的首个元素(head)和剩余部分(tail)
· 反转列表(reverse)
· 获取前缀(take)、获取后缀(drop)
· 拉链(zip)和拉开(unzip)
· 转换字符串(toString)
· 生成字符串(mkString)
· 并集(union)
· 交集(intersect)
· 差集(diff)
集(Set)
#获取集的大小
a.size
#不可变集合
//定义一个空的不可变集
val a = Set[Int]()
//定义一个不可变集,保存以下元素:1,1,3,2,4,8
val a = Set(1,1,3,2,4,8)
#可变集合
//1.定义一个可变集,包含以下元素: 1,2,3, 4
import scala.collection.mutable.Set
val a = Set(1,2,3,4)
#常用方法
· 添加一个元素,生成一个Set(+)
· 拼接两个集,生成一个Set(++)
· 拼接集和列表,生成一个Set(++)
映射(类似HashMap)
#不可变映射
val a = Map("zhangsan"->30,"lisi"->40)
//2.获取zhangsan的年龄
a("zhangsan")
#可变映射
import scala.collection.mutable.Map
val a = Map("zhangsan"->30,"lisi"->40)
#基本操作
· 获取值(map(key))
· 获取所有key(map.keys)
· 获取所有value(map.values)
· 遍历map集合
· getOrElse判断在不在不在返回-1
a += "wangwu"->35
//2.使用while循环和迭代器,遍历打印该列表
val ite = a.iterator
while(ite.hasNext){println(ite.next)}
//3.使用for 表达式和迭代器,遍历打印该列表
val ite = a.iterator
for(i <- ite)println(i)
方法的定义与调用
方法的返回值类型可以不写,编译器可以自动推断出来,但是对于递归函数,必须制定返回值类型。
定义方法的格式为:
def methodName([list of parameters]) : [return type] = {}
def sum(a:Int, b:Int): Int = { a + b}
sum: (a: Int, b: Int)Int
val result = sum(1, 5)
println(result)
6
// 该方法没有任何参数,也没有返回值
def sayHello1 = println("Say BB1")
sayHello1: Unit
def sayHello2() = println("Say BB2")
sayHello2: ()Unit
sayHello1 // 如果方法没有(),则调用时也不能加()
Say BB1
sayHello2 // 如果方法有(),则调用时可以加(),也可以省略不加
Say BB2
函数的定义与调用
定义方式
val fun : (Int,Int)=>Int = (a:Int,b:Int) => {a+b}
作为参数传递
def TestFun(f:(Int,Int)=>Int,msg:String) : String={
msg+f(30,20)
}
println(TestFun(sub,"差:"))
println(TestFun((a:Int,b:Int)=>a+b,"和:"))
println(TestFun((a:Int,b:Int)=>a*b,"积:"))
println(TestFun((a:Int,b:Int)=>a/b,"商:"))
作为返回值
def TestFunc3(a:Int) : (Int,Int)=>Int = {
if (a%2 == 0){
(a:Int,b:Int)=>a + b
}else{
(a:Int,b:Int)=>a - b
}
}
println(TestFunc3(2)(30,20))
println(TestFunc3(3)(30,20))
隐式转换
隐式转换和隐式参数是Scala的两个重要功能,我们可以利用隐式转换来丰富现有类的功能,以及隐式对象可以自动呼出用于执行转换或其他任务;我们可以提供优雅的类库,对类库的使用者隐藏掉那些枯燥乏味的细节。
scala提供了implicit关键字
隐式参数
object Demo {
implicit val name:String = "zhangpeng"
def sayHello(implicit name:String) : Unit = {
println("hello," + name)
}
def main(args: Array[String]): Unit = {
sayHello
}
}
运行结果:
优先级:
传参 > 默认 > 隐式
隐式函数
隐式转换函数是以implicit关键字作用于带有单个参数的函数上。这种函数将会自动应用,将值从一种类型转换为另外一种类型。(相当于将一种类通过一种函数变为了另一种类)
例:编写隐式函数支持由Double=>Int的转换
隐式类
隐式类以implicit修饰,编译器会生成一个从类的构造方法参数到类本身的隐式转换。
object Implicit {
implicit def stringToInt(v:String) : Int = Integer.parseInt(v)
implicit def doubleToInt(value:Double):Int = value.toInt
implicit class NumOperation(demo:Demo){
def sum(a:Int,b:Int):Int = {
a+b
}
def sub(a:Int,b:Int):Int = {
a-b
}
def ji(a:Int,b:Int) : Int = {
a*b
}
def chu(a:Int,b:Int) : Double = {
a/b*1.0
}
}
class Demo{}
object Demo {
implicit val name:String = "zhangpeng"
def sayHello(implicit name:String) : Unit = {
println("hello," + name)
}
def main(args: Array[String]): Unit = {
val a:Int = "1"
sayHello
val demo = new Demo
println(demo.sum(30,20))
println(demo.sub(30,20))
println(demo.ji(30,20))
println(demo.chu(30,20))
}
}
效果图:
函数柯里化
柯里化(currying, 以逻辑学家Haskell Brooks Curry的名字命名)指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数作为参数的函数。 在Scala中方法和函数有细微的差别,通常编译器会自动完成方法到函数的转换。
def f1(a:Int,b:Int,c:Int):Int = a+b+c
def f2(a:Int,b:Int)(c:Int):Int = a+b+c
def f3(a:Int)(b:Int)(c:Int) : Int = a+b+c
println(f1(1,2,3))
println(f2(1,2)(3))
println(f3(1)(2)(3))
效果图: