Scala编程实例:使用List和Tuple

本文节选自Martin Odersky,Lex Spoon和Bill Venners所著,Regular翻译的《Programming in Scala》的第三章。Scala是一种针对 JVM 将函数和面向对象技术组合在一起的编程语言。

本节接着上一节的内容,继续介绍Scala编程中一些更先进的特征:List(数组)和Tuple(元组)。

Scala中使用List

方法不应该有副作用是函数风格编程的一个很重要的理念。方法唯一的效果应该是计算并返回值。用这种方式工作的好处就是方法之间很少纠缠在一起,因此就更加可靠和可重用。另一个好处(静态类型语言里)是传入传出方法的所有东西都被类型检查器检查,因此逻辑错误会更有可能把自己表现为类型错误。把这个函数式编程的哲学应用到对象世界里意味着使对象不可变。

如你所见,Scala数组是一个所有对象都共享相同类型的可变序列。比方说Array[String]仅包含String。尽管实例化之后你无法改变Array的长度,它的元素值却是可变的。因此,Array是可变的对象。

说到共享相同类型的不可变对象序列,Scala的List类才是。和数组一样,List[String]包含的仅仅是String。Scala的List,scala.List,不同于Java的java.util.List,总是不可变的(而Java的List可变)。更通常的说法,Scala的List是设计给函数式风格的编程用的。

创建一个List很简单。代码3.3做了展示:

  1. val oneTwoThree = List(1, 2, 3)

代码 3.3 创造和初始化列表

代码3.3中的代码完成了一个新的叫做oneTwoThree的val,并已经用带有整数元素值1,2和3的新List[Int]初始化。 因为List是不可变的,他们表现得有些像Java的String:当你在一个List上调用方法时,似乎这个名字指代的List看上去被改变了,而实际上它只是用新的值创建了一个List并返回。比方说,List有个叫“:::”的方法实现叠加功能。你可以这么用:

  1. val oneTwo = List(1, 2)
  2. val threeFour = List(3, 4)
  3. val oneTwooneTwoThreeFour = oneTwo ::: threeFour
  4. println(oneTwo + " and " + threeFour + " were not mutated.")
  5. println("Thus, " + oneTwoThreeFour + " is a new List.")

如果你执行这个脚本,你会看到:

  1. List(1, 2) and List(3, 4) were not mutated.
  2. Thus, List(1, 2, 3, 4) is a new List.

或许List最常用的操作符是发音为“cons”的‘::’。Cons把一个新元素组合到已有List的最前端,然后返回结果List。例如,若执行这个脚本:

  1. val twoThree = list(2, 3)
  2. val oneTwoThree = 1 :: twoThree
  3. println(oneTwoThree)

你会看到:

  1. List(1, 2, 3)

注意

表达式“1 :: twoThree”中,::是它右操作数,列表twoThree,的方法。你或许会疑惑::方法的关联性上有什么东西搞错了,不过这只是一个简单的需记住的规则:如果一个方法被用作操作符标注,如a * b,那么方法被左操作数调用,就像a.*(b)——除非方法名以冒号结尾。这种情况下,方法被右操作数调用。因此,1 :: twoThree里,::方法被twoThree调用,传入1,像这样:twoThree.::(1)。

5.8节中将描述更多操作符关联性的细节。

由于定义空类的捷径是Nil,所以一种初始化新List的方法是把所有元素用cons操作符串起来,Nil作为最后一个元素。

比方说,下面的脚本将产生与之前那个同样的输出

  1. “List(1, 2, 3)”:
  2. val oneTwoThree = 1 :: 2 :: 3 :: Nil
  3. println(oneTwoThree)

Scala的List包装了很多有用的方法,表格3.1罗列了其中的一些。列表的全部实力将在第十六章释放。

为什么列表不支持append?

类List没有提供append操作,因为随着列表变长append的耗时将呈线性增长,而使用::做前缀则仅花费常量时间。如果你想通过添加元素来构造列表,你的选择是把它们前缀进去,当你完成之后再调用reverse;或使用ListBuffer,一种提供append操作的可变列表,当你完成之后调用toList。ListBuffer将在22.2节中描述。

Scala中使用Tuple

另一种有用的容器对象是元组:tuple。与列表一样,元组也是不可变的,但与列表不同,元组可以包含不同类型的元素。而列表应该是List[Int]或List[String]的样子,元组可以同时拥有Int和String。元组很有用,比方说,如果你需要在方法里返回多个对象。Java里你将经常创建一个JavaBean样子的类去装多个返回值,Scala里你可以简单地返回一个元组。而且这么做的确简单:实例化一个装有一些对象的新元组,只要把这些对象放在括号里,并用逗号分隔即可。一旦你已经实例化了一个元组,你可以用点号,下划线和一个基于1的元素索引访问它。代码3.4展示了一个例子:

  1. val pair = (99, "Luftballons")
  2. println(pair._1)
  3. println(pair._2)

代码 3.4 创造和使用元组

代码3.4的第一行,你创建了元组,它的第一个元素是以99为值的Int,第二个是"luftballons"为值的String。Scala推断元组类型为Tuple2[Int, String],并把它赋给变量pair。第二行,你访问_1字段,从而输出第一个元素,99。第二行的这个“.”与你用来访问字段或调用方法的点没有区别。本例中你正用来访问名叫_1的字段。如果执行这个脚本,你能看到:

  1. 99
  2. Luftballons

元组的实际类型取决于它含有的元素数量和这些元素的类型。因此,(99, "Luftballons")的类型是Tuple2[Int, String]。(‘u‘, ‘r‘, ‘the‘, 1, 4, "me")是Tuple6[Char, Char, String, Int, Int, String]。

访问元组的元素

你或许想知道为什么你不能像访问List里的元素那样访问元组的,就像pair(0)。那是因为List的apply方法始终返回同样的类型,但是元组里的或许类型不同。_1可以有一个结果类型,_2是另外一个,诸如此类。这些_N数字是基于1的,而不是基于0的,因为对于拥有静态类型元组的其他语言,如Haskell和ML,从1开始是传统的设定。

本文节选自《Programming in Scala》

【相关阅读】

  1. Scala编程实例:带类型的参数化数组
  2. 初探Scala编程:编写脚本,循环与枚举
  3. 初探Scala编程:解释器,变量及函数定义
  4. 影响Scala语言设计的因素列表
  5. 喜欢Scala编程的四个理由

转自:http://developer.51cto.com/art/200907/134954.htm

时间: 2024-11-07 21:11:09

Scala编程实例:使用List和Tuple的相关文章

SCALA编程实例

SCALA与JAVA很相似,包括类.函数.集合等等的使用.如果你是一个JAVA程序员,你应该会很快上手. 需要注意的是SCALA特有的一些奇葩标志,比如->,比如=>,遇到要注意下. 使用SCALA IDE,自行下载: 主要程序内容:main函数编写,函数调用,Map使用.数组和循环遍历. object WordCount { def main(args: Array[String]):Unit={ var ar = Array("#","$",&quo

【Scala编程】函数式风格编写排序算法

有关Scala编程实例 在刚开始学习一门编程语言的时候,总是想去写一些比较大的程序和项目,但是由于基础不扎实,往往欲速则不达.所以,只能一步一步来,通过一些经典的小例子来实践和锻炼,最终不断加深编程的技能,坚持下来,相信慢慢就能够变得熟练. 冒泡排序.选择排序.插入排序的一般写法 这三种排序方法没有太多要说的东西,这里的编程方式和指定式方式没什么差别. 这里之所以使用Array数据,因为Array数组是可变的对象序列,其元素值可以改变,而List类对象的元素是不可变的. 这里的写法不是函数式风格

Scala编程进阶

跳出循环语句的3种方法... 1 多维数组... 2 Java数组与Scala数组缓冲的隐式转换... 2 Java Map与Scala Map的隐式转换... 3 Tuple拉链操作... 3 内部类的作用域:外部类对象... 3 扩大内部类作用域:伴生对象... 4 扩大内部类作用域:类型投影... 4 内部类获取外部类的引用... 4 package定义... 5 package特性... 5 import. 8     跳出循环语句的3种方法 方法一:使用boolean控制变量 whil

(升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课程会涵盖Scala编程详解.Spark核心编程.Spark SQL和Spark Streaming.Spark内核以及源码剖析.性能调优.企业级案例实战等部分.完全从零起步,让学员可以一站式精通Spark企业级大数据开发,提升自己的职场竞争力,实现更好的升职或者跳槽,或者从j2ee等传统软件开发工程

Scala编程基础

Scala与Java的关系... 1 安装Scala. 1 Scala解释器的使用... 2 声明变量... 2 数据类型与操作符... 2 函数调用与apply()函数... 3 if表达式... 3 语句终结符.块表达式... 4 输入和输出... 4 循环... 4 高级for循环... 5 函数的定义与调用... 5 在代码块中定义包含多行语句的函数体... 5 递归函数与返回类型... 6 默认参数... 6 函数调用时带名参数... 6 变长参数... 6 序列作为变长参数... 6

下载20小时玩转Scala编程(Spark必备)

20课下载地址:http://pan.baidu.com/s/1nuV8NnN现200转让了,联系QQ:380539674本课程紧抓重点.言简意赅.深入浅出的讲解Scala编程,旨在学员能快速上手并灵活掌握. 课程以实操为主,提供完整详细的源码,供学员学习或应用到项目中.课程的课件也很详细, 在学员不方便看视频的时候直接看课件并结合源码,同样可以达到很好的学习效果,并能大幅节省学习时间.第一讲.Scala环境和IDE使用,数据类型第二讲.控制语句,if.while.for.foreach使用第三

20小时玩转Scala编程(Spark必备)

网盘地址:https://pan.baidu.com/s/1NdFAD5K3XkoWAzo0uWDqtQ 提取码: 7k7j 本课程紧抓重点.言简意赅.深入浅出的讲解Scala编程,旨在学员能快速上手并灵活掌握. 课程以实操为主,提供完整详细的源码,供学员学习或应用到项目中.课程的课件也很详细,在学员不方便看视频的时候直接看课件并结合源码,同样可以达到很好的学习效果,并能大幅节省学习时间. 课程大纲: 第一讲.Scala环境和IDE使用,数据类型第二讲.控制语句,if.while.for.for

HBase编程实例

摘要:在前文中安装了Hbase,通过Hbase shell可以进行一些操作,但是和实际的编程实例联系起来不方便,因此本文介绍有关Hbase编程的实例. 一.使用Eclipse开发HBase应用程序 1,在Eclipse中新建一个Java Project,命名为HBaseTest,然后右键Properties中选择Java Build Path,选择Add External Jars,将HBase/lib目录下的jar包导入进来. 2,在工程根目录下创建Conf文件夹,将HBase/Conf下的h

c编程实例:809*??=800*??+9*???+1

程序代码: #include<stdio.h>#include<stdio.h>void main(){ int c; int i,j,k; printf("start computing!!!"); for(i=10;i<100;i++){ for(j=100;j<1000;j++){ c=i*809-1-9*j; k=c%800; if(k==0){ k=c/800; if(k>10&&k<100) printf(&q