文章作者邮箱:[email protected] 地址:广东惠州
⚪ 掌握Scala的基础语法;
⚪ 掌握Scala的函数库;
语句 |
说明 |
示例 |
var |
用来声明一个变量, |
def main(args: Array[String]): Unit = { var var1=100 var var2:Int=100 //变量修改 var2=200; var3="world"; |
val |
用来声明一个常量,
|
//定义常量,但不允许修改常量 val vall = 100; //常量修改将报错 vall = 200; |
操作符 |
scala中操作符即方法,方法即操作符 所以 可以认为 scala中并没有传统意义上的操作符 所有的操作符都是方法 所有的方法也都可以像操作符一样去使用 |
1. 算术运算符 + - * / % 2. 关系运算符 == != > < >= <=== > < >= <= 3. 逻辑运算符 && || ! 4. 位运算符 ~ & | ^ << >> >>> 5. 赋值运算符 = += -= *= /= %= |
下表列出了Scala支持的算术运算符。
假定变量A为10,B为20:
运算符 | 描述 | 实例 |
+ | 加号 | A + B 运算结果为 30 |
- | 减号 | A - B 运算结果为 -10 |
* | 乘号 | A * B 运算结果为 200 |
/ | 除号 | A / B 运算结果为 2 |
% | 取余 | A % B 运算结果为 0 |
下表列出了Scala支持的关系运算符。
假定变量A为10,B为20:
运算符 | 描述 | 实例 |
== | 等于 | ( A == B ) 运算结果为 false |
!= | 不等于 | ( A != B ) 运算结果为 true |
> | 大于 | ( A > B ) 运算结果为 false |
< | 小于 | ( A < B ) 运算结果为 true |
>= | 大于等于 | ( A >= B ) 运算结果为 false |
<= | 小于等于 | ( A <= B ) 运算结果为 true |
下表列出了Scala支持的关系运算符。
假定变量A为1,B为0:
运算符 | 描述 | 实例 |
&& | 逻辑与 | ( A && B ) 运算结果为 false |
|| | 逻辑或 | ( A || B ) 运算结果为 true |
! | 逻辑非 | ! ( A && B ) 运算结果为 true |
位运算符用来对二进制位进行操作,~,&,|,^ 分别为取反,按位与与,按位与或,按位与异或运算,如下实例:
运算符 | 描述 | 实例 |
& | 按位与运算符 | (a & b) 输出结果12,二进制解释:0000 1100 |
| | 按位或运算符 | (a | b) 输出结果61,二进制解释:0011 1101 |
^ | 按位异或运算符 | (a ^ b) 输出结果49,二进制解释:0011 0001 |
~ | 按位取反运算符 | (~a) 输出结果-61,二进制解释:1100 0011, 在一个有符号二进制数的补码形式。 |
<< | 左移动运算符 | a<<2 输出结果240,二进制解释:1111 0000 |
>> | 右移动运算符 | a>>2 输出结果15,二进制解释:0000 1111 |
>>> | 无符号右移 | a>>>2 输出结果15,二进制解释:0000 1111 |
一下列出了Scala语言支持的赋值运算符:
运算符 | 描述 | 实例 |
= | 简单的赋值运算,指定右边的操作数赋值给左边的操作数。 | C = A + B 将 A + B 的运算结果赋值给 C |
+= | 相加后再赋值,将左右两边的操作数相加后再赋值给左边的操作数。 | C += A 相当于 C = C + A |
-= | 相减后再赋值,将左右两边的操作数相减后再赋值给左边的操作数。 | C -= A 相当于 C = C - A |
*= | 相乘后再赋值,将左右两边的操作数相乘后再赋值给左边的操作数。 | C *= A 相当于 C = C * A |
/= | 相除后再赋值,将左右两边的操作数相除后再赋值给左边的操作数。 | C /= A 相当于 C = C / A |
%= | 求余后再赋值,将左右两边的操作数求余后再赋值给左边的操作数。 | C %= A 相当于 C = C % A |
语句 |
说明 |
示例 |
if……else |
if……else 判断 if是具有返回值的,if判断后,将执行代码的最后一个表达式的值返回作为整个if执行后的结果。 |
//一个简单的示例 var var1=10; if(var1<100){ println("小了") }else{ println("大了") }
//根据scala函数式编程风格,建议做如下更改 //尽量使用常量 val val1=10; //if……else最后一行的值是返回值,可省略return val result= if(val1<100){ "小了"; }else{ "大了"; } print(result) //也可以简化成下面的形式 val val2=10; println(if(val2<100)"小了"else"大了"); |
while |
和java中用法相同 |
//一个简单的例子 val val1=List(1,2,3,4); var index=0; while(index println(val1(index)); index+=1; } |
for |
scala中的for要比java的for强大,使用很频繁,需要熟练掌握。
|
//生成一个1~100的区间,区间类型是range val val1=1 to 100;
//循环遍历并打印 for(num <-val1){ println(num) }
//支持条件过滤 for(num<-val1;if num>50){ println(num) }
//支持多条件过滤 for(num<-val1;if num>50;if num%2==0;if num<90) println(num) //也可以写成下面的形式 for(num<- 1 to 100;if num>50&&num<90&&num%2==0){ println(num) } |
try catch finally |
scala中继承了java的异常机制 |
import java.lang try { throw new RuntimeException("error"); }catch { case t: NullPointerException => t.printStackTrace();("空指针异常"); case t: Exception=>t.printStackTrace();println("其他异常"); }finally { println("资源释放") } |
match |
scala中的match类似于其他语言的switch |
//一个简单的例子 //match匹配到case后,执行case对应的内容,然后退出match,于java不同的是,不需要写break val val1="bbb"; val1 match { case "aaa" =>println("1"); case "bbb" =>println("2"); case _ =>println("3"); }
//此外,match可以带有返回值 val result=val1 match{ case "aaa" =>1 case "bbb" =>2 case _ =>3 } |
break continue |
scala中没有break和continue语句,需要通过另外的形式来实现 |
import util.control.Breaks._ object Demo12 { def main(args: Array[String]): Unit = {
//实现break breakable( for(i <- 1 to 10){ if(i==8){ break(); }else{ println(i); } } )
//实现continue for(i<-1 to 10){ breakable( if(i==8){ break; }else{ println(i); } ) }
} } |
scala 函数通过 def 关键字定义,def前面可以具有修饰符,可以通过private、protected来控制其访问权限。
注意:没有public,不写默认就是public的。 此外也可跟上override,final等关键字修饰。
1. 函数体中return关键字往往可以省略掉,一旦省略掉,函数将会返回整个函数体中最后一行表达式的值,这也要求整个函数体的最后一行必须是正确类型的值的表达式。
2. 大部分时候scala都可以通过 =符号 来自动推断出返回值的类型,所以通常返回值类型声明可以省略。
但是注意:如果因为省略了返回值类型造成歧义,则一定要写上返回值声明。
3. 如果函数体只有一行内容,则包裹函数体的大括号可以省略
4. 如果返回值类型是UNIT,则另一种写法是可以去掉返回值类型和等号,把方法体写在花括号内,而这时方法内无论返回什么,返回值都是 UNIT。
格式:[private/protected] def 函数名(参数列表):返回值声明 = {函数体}
示例:
//方法的返回值为空
def f1():Unit={
println("hello scala");
}
//等价于f1()方法,注意:如果函数没有=号,无论函数体里的返回值是什么,函数的返回值都是Unit
def f2(){
println("hello scala");
}
//定义方法参数类型,返回值类型,及返回值
def f3(a:Int,b:Int):Int={
a+b;
}
//scala可自行推断返回值类型,所以可省略返回值类型
def f4(a:Int,b:Int)={
a+b;
}
//如果函数体只一行内容,可以省了花括号
def f5(a:Int,b:Int)=a+b
//注意下面这种形式,因为没有=号,所以函数的返回值是Unit,即()
def f6(a:Int,b:Int){
a+b
}
代码示意:
object Demo21 {
def f1(a:String,b:String="[",c:String="]")={
b+a+c
}
def main(args: Array[String]): Unit = {
print(f1("hello"))//将打印:[hello]
}
}
1.成员函数
2.本地函数(内嵌在函数内的函数)
3.函数值(匿名函数)
4.高阶函数
成员函数: 函数被使用在类的内部,作为类的一份子,称为类的成员函数
示例:
object Demo15 {
def main(args: Array[String]): Unit = {
val p=new Student();
p.eat();
p.study();
}
// eat() 和study()属于 类Student的成员函数
class Student{
def eat(){
println("吃饭")
}
def study(){
println("学习")
}
}
}
本地函数:函数内嵌的函数称为本地函数,这样的函数外界无法访问
示例:
object Demo16 {
def main(args: Array[String]): Unit = {
val p=new Student();
p.eat("肉");
}
class Student{
def eat(food:String){
//cook函数内嵌在eat函数里,这样的函数称之为本地函数
def cook(food:String):String={
"做熟了的"+food;
}
println("吃"+cook(food));
}
}
}
函数值 - 匿名函数:
示例:
def f1(a:Int,b:Int):Int={a+b};
//等价于上式的函数
(a:Int,b:Int)=>{a+b};
//如果函数体只有一行代码,可以省去大括号
(a:Int,b:Int)=>a+b;
//如果函数参数列表只有一个参数,小括号有可以省略
a:Int=>a+1;
//如果函数的参数类型可以被推测,则可以省略类型值
//(a,b)=>a+b
def f1(a:Int,b:Int):Int={a+b};
//可以将f1()函数赋值给f2常量
val f2=f1(_,_);
//可以将f1()函数赋值给f3变量,f3可以更改此函数
var f3=f1(_,_);
f3=(a:Int,b:Int)=>a*b;
//也可以这样写
val f4=(c:Int,d:Int)=>{c+d}
//注意,下面的写法是将f1的函数值复制给f5,而不是函数赋值给f5
val f5=f1(2,3)
高阶函数(Higher-Order Function)就是操作其他函数的函数。
Scala 中允许使用高阶函数, 高阶函数可以使用其他函数作为参数,或者使用函数作为输出结果。
示例1:
object Demo01 {
//定义了compute函数,a,b和f函数 三个参数。其中f函数未做实现。
//我们的目的是对传入的a和b参数利用 f函数做运算,但是具体是什么运算需要由用户自己来指定。
def compute(a:Int,b:Int,f:(Int,Int)=>Int):Int={
f(a,b)
}
def main(args: Array[String]): Unit = {
val f1=(a:Int,b:Int)=>{a+b}
val f2=(a:Int,b:Int)=>{a*b}
val f3=(a:Int,b:Int)=>{a-b}
val f4=(a:Int,b:Int)=>{a/b}
//由下式可以看出,scala中,函数可以当做参数进行传递和调用
val result=compute(2,3,f1)
//下式等价于上式
//val result=compute(2,3,(a,b)=>{a+b})
}
}
示例2:
object Demo02 {
//定义了一个函数,作用是将用户处理后的字符串结果进行打印输出
def handleString(a:String,f:(String)=>String){
println("处理完后的字符串为:"+ f(a))
}
def main(args: Array[String]): Unit = {
val a="hello scala";
handleString(a,(a)=>{a});
handleString(a,(a)=>{a.substring(6)});
handleString(a,(a)=>{a.concat(" 1706")})
}
}
占位符:占位符指的是scala中的下划线_ ,可以用它当作一个或多个参数来使用。
使用_占位符的前提要求:每个参数在函数仅出现一次。
使用下划线时,如果类型可以自动推断出,则不用声明类型。如果无法自动推断类型,则在下划线后自己来显示声明类型即可。
示例1:
object Demo03 {
def compute(a:Int,b:Int,f:(Int,Int)=>Int):Int={
f(a,b)
}
def handleString(a:String,f:(String)=>String){
println("处理完后的字符串为:"+ f(a))
}
def main(args: Array[String]): Unit = {
val message="hello scala";
//这样用占位符会报错
//handleString(message,(_)=>{_.substring(6)})
//应改为下面的写法
handleString(message,{_.substring(6)})
//如果函数体只有一行代码,则还可以将大括号去掉
handleString(message,_.substring(6))
//compute的代码可简化如下
compute(2,3,_+_)
compute(2,3,_*_)
compute(2,3,_-_)
// 此外
// val f1=(a:Int,b:Int)=>{a+b}
// 等价于下式:
// val f1=(_:Int)+(_:Int)
// compute(2, 3, f1)
//再来看一个例子
val list=List(1,3,5,7,9)
list.foreach { x =>print(x) }
list.foreach { _ =>print(_) }
list.foreach { print(_) }
list.foreach { x => x*2 }
list.foreach { _*2 }
}
}
示例1:用递归方式实现斐波那契数列
//0 1 1 2 3 5 8 13
def f2(n:Int):Int={
if(n==0) return 0
if(n==1) return 1
else f2(n-1)+f2(n-2)
}
1.针对下列Java循环编写一个Scala版本:
for(int i=10;i>=0;i–)
System.out.println(i);
2.编写一个函数countdown(n:Int),打印从n到0的数字
3.编写函数计算x的n次方,其中n是整数,要考虑等n是0,正偶数,正奇数,负数这几种情况。
比如当x=2时,此函数要算出 2^4,2^3,2^0,2^(-1)对应的值
mi(x:Int,n:Int):Double={ }
mi(2,10)=1024
mi(2,-1)=0.5
4.编写一个循环,将整数数组中相邻的元素置换
Array(1,2,3,4,5,6)
得到的结果:214365
5.创建一个Map,包含一些你想要的一些装备,以及他们的价格。然后通过yield 构建另一个Map映射,采用同一组键,但是价格上打9折
比如定义一个Map:
var m1=Map("book"->10,"gun"->100,"ipad"->1000)
则输出的新map(m2)为:Map("book"->9,"gun"->90,"ipad"->900)