Scala语言基础 2

简介: Scala语言基础

8.3 Scala函数定义和参数传递

1、默认参数。

 Scala 可以为函数参数指定默认参数值。如果在调用函数的过程中可以不传递参数,这时函数就会调用它的默认参数值;如果传递了参数,则传递值会取代默认值。

 在paste模式下,键入以下内容:


1.  def addInt( a:Int=5, b:Int=7 ) : Int = {
2.        var sum:Int = 0
3.        sum = a + b
4.        sum
5.     }
6.     println( "返回值 : " + addInt() );

按下Ctrl+D,执行以上代码。输出结果如下:

返回值 : 12

2、命名参数。

 通常情况下,调用函数时,参数传入和函数定义时参数列表一一对应。

 在paste模式下,键入以下内容:

1.  def  speed(distance: Float, time:Float) :Float = distance/time
2.  speed(100,10)

按下Ctrl+D,执行以上代码。输出结果如下:

Float = 10.0

而使用命名参数则允许我们使用任意顺序传入参数。在paste模式下,键入以下内容:


1.  speed(time=10,distance=100)
2.  speed(distance=100,time=10)

按下Ctrl+D,执行以上代码。输出结果如下:

Float = 10.0

3、变长参数。

 Scala在定义函数时允许指定最后一个参数可以重复(变长参数),从而允许函数调用者使用变长参数列表来调用该函数,Scala中使用”*”来指明该参数为重复参数。

 在paste模式下,键入以下内容:

1.  def echo (args: String *) = for (arg <- args) println(arg)
2.  echo ("One")
3.  echo ("Hello","World")

按下Ctrl+D,执行以上代码。输出结果如下:

One
Hello
World

8.4 Scala常用集合

1、数组。

 定长数组,就是长度不变的数组,在Scala中使用Array进行声明。

 在paste模式下,键入以下内容:

1.  var arr = Array(1, 3, 2, 4)
2.       
3.  //求和
4.  println(arr.sum) 
5.       
6.  //最大值
7.  println(arr.max) 
8.       
9.  //最小值
10. println(arr.min) 
11.      
12. //转化成字符串
13. println(arr.mkString("|")) 
14.      
15. //按大小排序
16. println(arr.sorted.toBuffer)
17.      
18. //数组倒序
19. println(arr.reverse.toBuffer)
20.      
21. // 将数组(元素是元组类型)转换为Map
22. println(Array(("cn", "china"), ("fr", "french")).toMap)

按下Ctrl+D,执行以上代码。输出结果如下:


10
4
1
1|3|2|4
ArrayBuffer(1, 2, 3, 4)
ArrayBuffer(4, 2, 3, 1)
Map(cn -> china, fr -> french)

不定长数组,就是长度可变的数组,在Scala中使用ArrayBuffer进行声明。

 在paste模式下,键入以下内容:

1.  import scala.collection.mutable.ArrayBuffer
2.       
3.  var arrbuffer = ArrayBuffer(1, 5, 3, 7)
4.       
5.  //求和
6.  println(arrbuffer.sum) 
7.       
8.  //最大值
9.  println(arrbuffer.max) 
10.      
11. //最小值
12. println(arrbuffer.min) 
13.      
14. //转化成字符串
15. println(arrbuffer.mkString("|")) 
16.      
17. //按大小排序(由小到大)
18. println(arrbuffer.sorted.toBuffer)
19.      
20. //按大小排序(由大到小)
21. println(arrbuffer.sorted.reverse.toBuffer)
22.      
23. //数组倒序
24. println(arrbuffer.reverse.toBuffer)
25.      
26. // 将数组(元素是元组类型)转换为Map
27. println(Array(("cn", "china"), ("fr", "french")).toMap)
28.      
29. // 增加一个元素
30. arrbuffer += 20
31. println(arrbuffer) 
32.      
33. // 增加一个数组集合
34. arrbuffer ++= Array(50, 60)     
35. println(arrbuffer)
36.      
37. // 删除最后 3 个元素 
38. arrbuffer.trimEnd(3) 
39. println(arrbuffer)
40.      
41. // 在索引2处插入两个元素
42. arrbuffer.insert(2, 28, 29) 
43. println(arrbuffer)
44.      
45. // 在索引2处删除三个元素
46. arrbuffer.remove(2, 3)
47. println(arrbuffer)
48.      
49. // 清空数组
50. arrbuffer.clear()
51. println(arrbuffer)

按下Ctrl+D,执行以上代码。输出结果如下:

16
7
1
1|5|3|7
ArrayBuffer(1, 3, 5, 7)
ArrayBuffer(7, 3, 5, 1)
Map(cn -> china, fr -> french)
ArrayBuffer(1, 5, 3, 7, 20)
ArrayBuffer(1, 5, 3, 7, 20, 50, 60)
ArrayBuffer(1, 5, 3, 7)
ArrayBuffer(1, 5, 28, 29, 3, 7)
ArrayBuffer(1, 5, 7)
ArrayBuffer()

数组遍历。

 在paste模式下,键入以下内容:

1.  val intValueArr2 = Array(0,1,2);
2.  //遍历
3.  for(i <- intValueArr2) println(i);

;按下Ctrl+D,执行以上代码。输出结果如下:

0
1
2

2、列表。

 在Scala中,列表分为不可变的和可变的。不可变列表的实现类为List,可变数组的实现类为ListBuffer。

 在paste模式下,键入以下代码:

1.  val intList = List(1,2,3)
2.  val intListOther = 0::intList

按下Ctrl+D,执行以上代码。输出结果如下:

intList: List[Int] = List(1, 2, 3)
intListOther: List[Int] = List(0, 1, 2, 3)

注意,上面操作执行后,intList不会发生变化,依然是List(1,2,3),intListOther是一个新的列表List(0,1,2,3)

 列表有头部和尾部的概念,可以使用intList.head来获取上面定义的列表的头部,值是1,使用intList.tail来获取上面定义的列表的尾部,值是List(2,3),可以看出,头部是一个元素,而尾部则仍然是一个列表。

 由于列表的头部是一个元素,所以,我们可以使用::操作,在列表的头部增加新的元素,得到一个新的列表。::操作符是右结合的,因此,如果要构建一个列表List(1,2,3),实际上也可以采用下面的方式:

1.  val intList = 3::2::1::Nil

执行结果如下:

intList: List[Int] = List(3, 2, 1)

上面代码中,Nil表示空列表。

 我们也可以使用:::操作符对不同的列表进行连接得到新的列表。例如,在paste模式下,键入以下内容:

1.  val intList1 = List(1,2)
2.  val intList2 = List(3,4)
3.  val intList3 = intList1:::intList2

按下Ctrl+D,执行以上代码。输出结果如下:


intList1: List[Int] = List(1, 2)
intList2: List[Int] = List(3, 4)
intList3: List[Int] = List(1, 2, 3, 4)

注意,执行上面操作后,intList1和intList2依然存在,intList3是一个全新的列表。

 实际上,Scala还为列表提供了一些常用的方法,比如,如果要实现求和,可以直接调用sum方法,如下:

1.  intList.sum

如果要遍历列表,可以使用for循环。例如,在paste模式下,键入以下代码:


1.  val intList = List(1,2,3)
2.       
3.  //遍历
4.  for(i <- intList) println(i);

按下Ctrl+D,执行以上代码。输出结果如下:

1
2
3

3、元组。

 元组是不同类型的值的聚集。元组和列表不同,列表中各个元素必须是相同类型,而元组可以包含不同类型的元素。

 下面我们声明一个名称为tuple的元组。在paste模式下,键入以下代码:


1.  val tuple = ("西普",666,666,666);
2.       
3.  println("我是"+tuple._1);
4.  println("我还是"+tuple._2);
5.  println(tuple._1+tuple._3);

按下Ctrl+D,执行以上代码。输出结果如下:


我是西普
我还是666
西普666

从上述代码的执行效果可以看出,我们声明一个元组是很简单的,只需要用圆括号把多个元组的元素包围起来就可以了。

 当需要访问元组中的某个元素的值时,可以通过类似tuple._1、tuple._2、tuple._3这种方式就可以实现。

 4、映射。

 在Scala中,映射(Map)是一系列键值对的集合,也就是,建立了键和值之间的对应关系。在映射中,所有的值,都可以通过键来获取。

 映射包括可变和不可变两种,默认情况下创建的是不可变映射,如果需要创建可变映射,需要引入scala.collection.mutable.Map包。

 下面我们创建一个不可变映射:

1.  val university = Map("xipu" -> "xi pu jiao yu", "THU" -> "Tsinghua University","PKU"->"Peking University")

执行以上代码。输出结果如下:

university: scala.collection.immutable.Map[String,String] = Map(XMU -> Xiamen University, THU -> Tsinghua University, PKU -> Peking University)

如果要获取映射中的值,可以通过键来获取。代码如下:

1.  println(university("xipu"))

执行以上代码。输出结果如下:


xi pu jiao yu

上面代码通过”xipu”这个键,可以获得值”xi pu jiao yu”。

 如果要检查映射中是否包含某个值,可以使用contains方法。例如,在paste模式下,键入以下代码:

1.  val xmu = if (university.contains("xipu")) university("xipu") else 0
2.  println(xmu)

按下Ctrl+D,执行以上代码。输出结果如下:

xi pu jiao yu
xmu: Any = xi pu jiao yu

上面我们定义的是不可变映射,是无法更新映射中的元素的,也无法增加新的元素。如果要更新映射的元素,就需要定义一个可变的映射。

 在paste模式下,键入以下代码:

1.  import scala.collection.mutable.Map
2.  val university2 = Map("XMU" -> "xi pu jiao yu", "THU" -> "Tsinghua University","PKU"->"Peking University")
3.  university2("XMU") = "西普教育"         //更新已有元素的值
4.  university2("ZZU") = "Zhengzhou University"     //添加新元素

按下Ctrl+D,执行以上代码。输出结果如下:

import scala.collection.mutable.Map
university2: scala.collection.mutable.Map[String,String] = Map(XMU -> xi pu jiao yu, THU -> Tsinghua University, ZZU -> Zhengzhou University, PKU -> Peking University)

如果要遍历映射,可以使用for循环语句。基本格式是:for ((k,v) <- 映射) 语句块

 在paste模式下,键入以下代码:

1.  val university = Map("XMU" -> "xi pu jiao yu", "THU" -> "Tsinghua University","PKU"->"Peking University")
2.  for ((k,v) <- university) printf("代码: %s,名称: %s
3.  ",k,v)

按下Ctrl+D,执行以上代码。输出结果如下:

代码: XMU,名称: xi pu jiao yu
代码: THU,名称: Tsinghua University
代码: PKU,名称: Peking University

或者,也可以只遍历映射中的k或者v。比如说,我们只想把所有键打印出来:

1.  for (k<-university.keys) println(k)

输出结果如下:

XMU
THU
PKU

再比如说,我们只想把所有值打印出来:


1.  for (v<-university.values) println(v)

输出结果如下:

xi pu jiao yu
Tsinghua University
Peking University

8.5 Scala异常处理

1、抛出异常。

 Scala 抛出异常的方法和 Java一样,使用 throw 方法,例如,抛出一个新的参数异常:

1.  throw new IllegalArgumentException

2、捕获异常。

 异常捕捉的机制与其他语言中一样,如果有异常发生,catch字句是按次序捕捉的。因此,在catch字句中,越具体的异常越要靠前,越普遍的异常越靠后。 如果抛出的异常不在catch字句中,该异常则无法处理,会被升级到调用者处。

 捕捉异常的catch子句,语法与其他语言中不太一样。在Scala里,借用了模式匹配的思想来做异常的匹配,因此,在catch的代码里,是一系列case字句。

 在paste模式下,键入以下代码:

1.  import java.io.FileReader
2.  import java.io.FileNotFoundException
3.  import java.io.IOException
4.       
5.  try {
6.      val f = new FileReader("input.txt")
7.  } catch {
8.      case ex: FileNotFoundException =>{
9.           println("Missing file exception")
10.     }
11.     case ex: IOException => {
12.          println("IO Exception")
13.     }
14. }

按下Ctrl+D,执行以上代码。输出结果如下:

Missing file exception

catch字句里的内容跟match里的case是完全一样的。由于异常捕捉是按次序,如果最普遍的异常,Throwable,写在最前面,则在它后面的case都捕捉不到,因此需要将它写在最后面。

 3、finally 语句。

 finally 语句用于执行不管是正常处理还是有异常发生时都需要执行的步骤。

 在paste模式下,键入以下代码:

1.  import java.io.FileReader
2.  import java.io.FileNotFoundException
3.  import java.io.IOException
4.       
5.  try {
6.      val f = new FileReader("input.txt")
7.  } catch {
8.      case ex: FileNotFoundException =>{
9.           println("Missing file exception")
10.     }
11.     case ex: IOException => {
12.          println("IO Exception")
13.     }
14. }finally {
15.     println("Exiting finally...")
16. }

按下Ctrl+D,执行以上代码。输出结果如下:

Missing file exception
Exiting finally…

9. 实验结果及分析:

实验结果运行准确,无误


10. 实验结论:

经过本节实验的学习,通过使用Shell的方式,学习了使用Scala基本语法,包含变量、表达式、流程控制,使用Scala定义函数定义和传递参数,包括位置参数、默认参数、名称参数,使用Scala常用集合数据结构,包括数组、列表、元组、Map,使用Scala进行异常处理,进一步巩固了我们的scala基础。


11. 总结及心得体会:

关于Scala中函数的定义和使用,总结如下:

 scala使用def关键字定义函数。


def test() {

println(“Hello World!”);

}

 因为是静态类型语言, 定义含参数和返回值的函数需要指定类型, 语法略有不同:

def add(x:Int, y:Int): Int = {

return x + y;

}

 scala支持默认参数:

def add(x:Int = 0, y:Int = 0):Int = {

 return x + y;

}

 可以指定最后一个参数为可变参数, 从而接受数目不定的同类型实参:

def echo (args: String *) { for (arg <- args) println(arg) }

echo(“Hello”, “World”)

 String *类型的参数args实际上是一个Array[String]实例, 但是不能将一个Array作为参数传给args.

 若需传递Array作为实参,需要使用arr :_*传递实参:

val arr= Array(“Hello” , “World”)

echo(arr: _*)

 命名参数允许以任意顺序传入参数:

def speed(dist:Double, time:Double):Double = {return dist / time}

speed(time=2.0, dist=12.2)


7b5d2031f901482a8cec2d73513c9bf7.png20001fe7349f410fa089b8b7d1e48e03.png

–end–


相关文章
|
存储 Ubuntu Java
|
SQL 消息中间件 分布式计算
如何查看spark与hadoop、kafka、Scala、flume、hive等兼容版本【适用于任何版本】
如何查看spark与hadoop、kafka、Scala、flume、hive等兼容版本【适用于任何版本】
786 0
如何查看spark与hadoop、kafka、Scala、flume、hive等兼容版本【适用于任何版本】
|
8天前
|
分布式计算 资源调度 Java
Scala+Spark+Hadoop+IDEA实现WordCount单词计数,上传并执行任务(简单实例-下)
Scala+Spark+Hadoop+IDEA实现WordCount单词计数,上传并执行任务(简单实例-下)
14 0
|
8天前
|
分布式计算 Hadoop Scala
Scala +Spark+Hadoop+Zookeeper+IDEA实现WordCount单词计数(简单实例-上)
Scala +Spark+Hadoop+Zookeeper+IDEA实现WordCount单词计数(简单实例-上)
9 0
|
1月前
|
SQL 存储 分布式计算
在scala中使用spark
在scala中使用spark
29 0
|
1月前
|
分布式计算 Java Scala
spark 与 scala 的对应版本查看、在idea中maven版本不要选择17,弄了好久,换成11就可以啦
spark 与 scala 的对应版本查看、.在idea中maven版本不要选择17,弄了好久,换成11就可以啦
159 2
|
1月前
|
分布式计算 Java Scala
Spark编程语言选择:Scala、Java和Python
Spark编程语言选择:Scala、Java和Python
Spark编程语言选择:Scala、Java和Python
|
1月前
|
分布式计算 数据处理 Scala
Spark 集群和 Scala 编程语言的关系
Spark 集群和 Scala 编程语言的关系