Scala 函数式语言
Scala于Java的对比
Scala里面的一切操作皆方法
Scala基本语法和约定
- 区分大小写 - Scala是区分大小写的,比如标识符Hello和hello在Scala中表示不同的含义(对象)。
- 类名称 - 对于所有类名,第一个字母应为大写。如果使用多个单词来形成类的名称,则每个内部单词的第一个字母应该是大写。示例 - class MyFirstScalaClass,class Employee*类等。
- 方法名称 - 所有方法名称应以小写字母开头。如果使用多个单词形成方法的名称,则每个内部单词的第一个字母应为大写。示例 - def myMethodName(),def getName()等。
- 程序文件名 - 程序文件的名称应与对象名称完全匹配。保存文件时,您应该使用对象名称保存它(记住Scala是区分大小写的),并将.scala附加到文件名称的末尾。 (如果文件名和对象名不匹配,则程序将不会编译)。示例:假设HelloWorld是对象名称。那么文件应该保存为HelloWorld.scala
- def main(args:Array [String]) - Scala程序从main()方法开始,这是每个Scala程序的强制性部分。
申明变量
- val:声明不可变的变量,一旦初始化就不能再被赋值
- var:声明可变的变量,可以在它的生命周期中被多次赋值
- 推荐使用val,如下:
val content: String = "hello world“
val content2: String = new String(“hello world”)
- 另外一种定义方式:
val x, y = 100
变量声明时可以不指定类型,编译器可以自动推断出来 - 多个赋值
如果代码块或方法返回一个元组(Tuple - 保持不同类型的对象的集合),则可以将元组分配给一个val变量。(后面讲解元组)val (myVar1: Int, myVar2: String) = Pair(40, “Foo”)
运算符
- 在Scala语言中,运算符是一个符号,告诉编译器执行特定的数学或逻辑函数。Scala语言提供丰富的内置运算符,包括算术运算符、关系运算符、逻辑运算符、按位运算符、赋值运算符、其它运算符。基本和java一样。
- ::运算符(两个冒号)表示普通元素与List的连接操作val a = 1 val b = List(3, 4) val c = 1 :: b
- :::运算符(三个冒号)表示List的连接操作,例如val a = List(1, 2) val b = List(3, 4) val c = a ::: b
- <- 运算符,也叫做generator。主要用于for循环中,用于遍历集合对象。在每次遍历的过程中,生成一个新的对象,这个对象是val,而不是var,然后对循环体中对对象进行处理。 不需要显式的指定对象的类型,因为Scala使用自动推导的方式根据B的元素类型得出A的类型
=> 含义比较多,用法最复杂1、val triple = (x: Int) => 3 * x—定义函数2、switch的模式匹配.
基本方法
在Scala中一切操作皆是方法:操作符可以被当成方法来调用,方法也可以被当成操作符使用。注意:Scala中没有提供++和—操作符,用+=和-=代替。
a 方法 b 等价于a.方法(b)例如
a.+(b) 等价于a + b
val result5 = msg1.+(msg2)
val result6 = msg1.+(msg1)
println(result5+” “+result6)
块表达式与赋值
在scala中,{}块包含一系列表达式,其结果也是一个表达式,块中最后一个表达式的值就是其值。
var y1 = {val a=1;val b=9;a+b;}//输出结果为y1=10;
在scala中,赋值语句本身的值是Unit类型的。因此如下语句的值为“()”:
var y2 = {val a=1;val b=9;i=a+b;}//输出结果为y2=()
正是由于上述原因,scala中不能多重赋值,而java和c++却可以多重赋值。因此,在scala中,如下语句会抛出语法错误:var x :Int =1;var y:Int =1;x = y = 1
程序控制
- if语句
val x = 1
val y = if (x > 0) 1 else -1 //判断x的值,将结果赋给y
println(y) //打印y的值支持混合类型表达式
val z = if (x > 1) 1 else "error"
println(z) //打印z的值
//如果缺失else,相当于if (x > 2) 1 else ()
val m = if (x > 2) 1
//在scala中每个表达式都有值,scala中有个Unit类,写做(),相当于Java中的void val n = if (x > 2) 1 else ()
println(n)
//if和else
if val k = if (x < 0)
else if (x >= 1) 1 else -1
println(k)
- Scala拥有与Java相同的while和do循环,while、do-while结果类型是Unit。不同的是for循环。
scala中没有类似于for(; ; )的for循环,你可以使用如下形式的for循环语句: for(i <- 表达式)
该for表达式语法对于数组和所有集合类均有效。
具体如下:
var m=1;
var loop = new Breaks;
loop.breakable(
while(true){
m+=1;
if(m==20){
loop.break();
}
print(m+"\t")
}
)
- 枚举:for(i <- 1 to 10),其中“i <- 表达式”语法称之为发生器,该语句是让变量i(注意此处循环变量i是val的(但无需你指定),该变量的类型是集合的元素类型)遍历表达式中的所有值。1 to 10产生的Range包含上边界,如果不想包含上边界,可以使用until。
for(i <- 1 to 10){
print(i+"\t");
}
- 过滤:也叫守卫,在for表达式的发生器中使用过滤器可以通过添加if子句实现,如:
for(i <- 1 to 10 if i!=5)
如果要添加多个过滤器,即多个if子句的话,要用分号隔开,如:
for(i <- 1 to 10 if i!=5; if i!=6) println(i)
- 嵌套枚举:如果使用多个“<-”子句,就得到了嵌套的“循环”,如:
for(i <- 1 to 3; j <- 1 to 3) println(i*10+j)
过滤和嵌套一起使用时,如:
for(i <- 1 to 3; j <- 1 to 3 if i!=j) println(i*10+j)
- 匹配(match)表达式
Scala中的match表达式类似于Java中的switch语句,它可以提供给你在多个备选项中做选择 .
在每个case语句最后,不需要break,break是隐含的;
match表达式也能产生值;
val ss = "apple"
val fruit= ss match {
case "banana" =>"pepper"
case "apple" =>"pen"
case "pear" =>"ink"
}
println(fruit);//结果为pen
字符串
在Scala中的字符串和Java中的一样,字符串是一个不可变的对象,也就是一个不能修改的对象。可以修改的对象,如数组,称为可变对象。
创建字符串实例如下:
var greeting = “Hello World!”;或var greeting = new String(“Hello World!”);或var greeting:String = "Hello World!";
如果需要创建一个可以修改的字符串,可以使用 String Builder 类或者StringBuffer类,语法为
var sb:StringBuffer = new StringBuffer(“dd”);
字符串方法:基本和java一样
使用 length() 方法来获取字符串长度
使用 concat() 方法来连接两个字符串
数组
- 要在程序中使用数组,必须先声明一个变量来引用数组,并且必须指定变量可引用的数组类型。以下是声明数组变量的语法。
var z:Array[String] = new Array[String](3)
或者 var z = new Array[String](3)
或者var z = Array("Maxsu", "Nancy", "Alen")
- scala虽然用val定义的数组,但是数组内的元素是可变的。变量z被声明为可以容纳三个元素的字符串数组。可以将值分配给单个元素或访问每个元素,访问元素通过使用如下命令来完成:
z(0) = "Zara";
z(1) = "Nuha";
z(4/2) = "Ayan“
数组的遍历
var myList = Array(1.9, 2.9, 3.4, 3.5)
for ( x <- myList ) {
println( x )
}
或者var total = 0.0;
for ( i <- 0 to (myList.length - 1){
total += myList(i);
println("Total is " + total);
多维数组
- 在许多情况下,需要定义和使用多维数组(即数组的数组)。 例如,矩阵和表是可以被实现为二维数组结构的例子。构造多维数组可以使用ofDim方法或者直接使用for循环来new。示例如下:
- ofDim方法创建多维数组
val matrix = Array.ofDim[Double](3,3)//这是一个具有三个元素的数组,每个元素都是一个具有三个元素的整数数组matrix(1)(2) = 12.36
for循环方式创建多维数组
val mutliarr = new Array[Array[Int]](10)
for(i <- 0 until mutliarr.length){
mutliarr(i) = new Array[Int](5)
}
变长数组
Java中有ArrayList,Scala中等效的数据结构就是ArrayBuffer,也叫做变长数组。以下是声明变长数组的方式:
val a = ArrayBuffer[Int]()
或val a = ArrayBuffer[Int](1,2,3)
或val a = new ArrayBuffer[Int]
数组数据的操作
a += 1 //在尾端添加元素
a += (1,2,3) //追加多个元素
a ++= ArrayBuffer(7,8,9) //追加集合
a.trimEnd(2) //移除最后两个元素
a.insert(2, 6, 7) //在下标2之前插入6,7
a.remove(2, 2) //从下标2开始移除2个元素
固定长度的数组与变长数组之间可以互相转换,比如有时你需要构建一个Array但是不知道最终需要多少元素,就可以先构建数组缓冲然后调用.toArray,反过来.toBuffer可以将数组转换成一个数组缓冲.
数组常用方法
- sum求和(数组必须是数值型数据)
println(array.sum) - min max 输出数组中最小和最大元素
println(array.min)
println(array.max) - 使用sorted方法对数组或数组缓冲进行升序排序,这个过程不会修改原始数组
val sortArr = array.sorted
for(elem <- sortArr)
print(elem + “, “) - 使用比较函数sortWith进行排序
val sortArr = ab.sortWith(>) - 数组显示
println(sortArr.mkString(“|”))
println(sortArr.mkString(“startFlag”,”|”,”endFlag”))
println("****************变长数组*********************")
val arr=ArrayBuffer[Int]();
arr+=(1,2,3,4);
for(i<- 0 to arr.length-1){
print(arr(i)+"\t");
}
arr+=(48,0,56,92)
println()
println(arr.sum)
println(arr.min)
println(arr.max)
println(arr.mkString("|"))
结果:
使用concat()方法连接两个数组
var myList1 = Array(1.9, 2.9, 3.4, 3.5)
var myList2 = Array(8.9, 7.9, 0.4, 1.5)
var myList3 = concat( myList1, myList2)
使用range()方法来生成包含给定范围内增加整数序列的数组
“`
var myList1 = range(10, 20, 2)//创建一个数组,其元素介于10和20之间,范围步差为2
var myList2 = range(10,20) //创建一个数组,其元素介于10和20之间,范围步差为1
“`
def iterate[T]( start: T, len: Int )( f: (T) => T ): Array[T]
返回指定长度数组,每个数组元素为指定函数的返回值。
以上实例数组初始值为 0,长度为 3,计算函数为a=>a+1:Array.iterate(0,3)(a=>a+1)
def copy( src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int ): Unit 复制一个数组到另一个数组上
def empty[T]: Array[T] 返回长度为 0 的数组
def fill[T]( n: Int )(elem: => T): Array[T]
返回数组,长度为第一个参数指定,同时每个元素使用第二个参数进行填充。