码迷,mamicode.com
首页 > 编程语言 > 详细

Scala详解---------数组、元组、映射

时间:2015-07-26 11:12:58      阅读:1522      评论:0      收藏:0      [点我收藏+]

标签:

一、数组

1、定长数组

声明数组的两种形式:

声明指定长度的数组 val 数组名= new Array[类型](数组长度)

  技术分享

提供数组初始值的数组,无需new关键字

  技术分享

Scala声明数组时,需要带有Array类名,且使用 () 来指明长度或提供初始值序列。

在JVM中,Scala的Array以Java数组的方式实现。如arr在JVM中的类型对应java.lang.String[],charArr对应char[]。

2、变长数组

  技术分享

ArrayBuffer,全称scala.collection.mutable.ArrayBuffer,类似于Java中的ArrayList和C++中的vector,是长度可变数组类型的结构,称为数组缓冲。

通过:val 名 = ArrayBuffer[类型]() 来声明,声明ArrayBuffer时需要指明类型。

通过 += 操作符来添加元素或序列,++= 操作符来拼接数组。

【在ArrayBuffer的尾端添加或删除元素是一个高效的操作。】 ArrayBuffer还支持在指定位置插入、删除元素。

ArrayBuffer到数组的转换: toArray方法

  技术分享

3、数组遍历

通过for循环来遍历数组

  技术分享

指定遍历数组的步长——通过until(上界, 步长)

  技术分享

  技术分享

通过reverse函数逆序遍历数组:

  技术分享

4、可以通过 for循环+yield 来获得新的数组或ArrayBuffer

  技术分享

  技术分享

通过for+yield操作数组或ArrayBuffer之后将得到新的数组或ArrayBuffer。

5、操作数组/数组缓冲常用函数

  技术分享

求和、求最大最小值、数组排序。通过sorted函数对数组或ArrayBuffer排序时,返回的是一个新的数组或ArrayBuffer,原有的不变。

可以直接对数组调用排序算法,但是不能对ArrayBuffer排序。

  技术分享

quickSort是直接修改原数组,而sorted方法是返回新数组

6、多维数组

Scala中的多维数组同Java中一样,多维数组都是数组的数组。

通过 Array.ofDim[类型](维度1, 维度2, 维度3,....)来声明多维数组,如声明二维数组;

  技术分享

  从二维数组的初始化中,我们可以看到,多维数组在Scala中也是数组的数组。

通过 Array[ Array[Int]](维度1) 来声明数组,可以声明不规则数组;

  技术分享

  多维数组是数组的数组,按照这种性质来声明多维数组,如例子中的二维数组,声明时,需要指定最外围的数组大小。

【注:可以通过scala.collection.JavaConversions包中隐式转换方法来实现Scala容器类与Java中类的转换。】

二、映射

1、映射构造

对偶,即名值对。可以通过 -> 操作符来定义对偶, 名->值 运算的结果是( 名, 值 ); 

  技术分享

也可以声明对偶形式的变量

  技术分享

映射是由对偶构成的,映射是对偶的集合。

声明不可变映射,直接使用Map来声明时,默认是不可变映射类型。

  技术分享

  【注: 不可变映射维持元素插入顺序。】

声明可变映射(scala.collection.mutable.Map)

  技术分享

  【注:放入可变映射中的值并未按照放入顺序来排序的。】

  通过for循环来修改可变Map中的值;

  技术分享

  【注:映射可变、不可变指的是整个映射是否可变,包括元素值、映射中元素个数、元素次序等。】

声明空映射

  直接通过 new Map[类型1, 类型2]() 来定义映射会报错,因为Map是抽象的,无法实例化。

  定义空映射时,需要指定映射的实现类,通过new来定义;

  技术分享

  分别定义不可变映射与可变映射。注,直接使用 new HashMap定义时会报错。

2、映射常用操作

判断映射中是否含有某个键: map.contains(键值)

  技术分享

使用 += 向可变映射中添加元素或拼接映射

  技术分享

使用 -= 移除可变映射中的键及对应元素

  技术分享

不可变映射可通过 + 操作符返回一个新的不可变映射;不可变映射可通过 - 操作符返回一个新的不可变映射;

  技术分享

映射遍历

  技术分享

获取映射的键集合keySet和值集合

  技术分享

  通过映射的 keySet 方法可以获得映射的由键值构成的集合;通过 values 方法可以获得映射的值集合的Interable对象,应用于循环中。

  Scala的keySet / values 方法类似于Java中的映射方法。

3、Scala中映射的底层实现要么基于哈希表,要么基于平衡树,其中基于平衡树的映射内部是有序的。

  技术分享

  Scala目前基于平衡树的映射只提供了不可变版本。

  【注:构建可变有序映射可借助Java的TreeMap。】

4、可变映射中,若穴ky"http://www.it165.net/qq/" target="_blank" class="keylink">qq5ub2ozqyz1tSqy9iy5cjry7PQ8rXE07PJ5L/Jzai5/UxpbmtlZEhhc2hNYXChozwvcD4KPHA+NaGizai5/XNjYWxhLmNvbGxlY3Rpb24uSmF2YUNvbnZlcnNpb25zLm1hcEFzU2NhbGFNYXC/yb2rSmF2YbXETWFw16q7u86qU2NhbGHA4NDNtcRNYXCju82ouf1zY2FsYS5jb2xsZWN0aW9uLkphdmFDb252ZXJzaW9ucy5tYXBBc0phdmFNYXC/yb2rU2NhbGG1xNOzyeTXqru7zqpKYXZhwODQzbXE07PJ5KGjPC9wPgo8cD42oaJ0b01hcLe9t6g8L3A+CjxwPqGhoaHKudPDdG9NYXC3vbeov8m9q7bUxbzX6bPJtcS8r7rP16q7r86q07PJ5KGjPC9wPgo8cD6hoaGhPGltZyBzcmM9"http://www.it165.net/uploadfile/files/2014/0920/20140920190600125.png" alt="\" />

三、元组

1、元组是不同类型的值的聚集;对偶是最简单的元组。

2、元组表示

  通过将不同的值用小括号括起来,即表示元组。

  技术分享

  上例中元组的类型就是 (Int, Double, Char, String) ;元组中可以存放不同类型的值。

3、元组访问

元组中的元素称为组元。可以通过 _1、 _2 、_3 的形式来访问对应下标的组元。

  技术分享

  【注:元组中组元下标从1开始。】

通过模式匹配来访问元组中的值

  技术分享

  忽略不需穴ky"http://www.it165.net/qq/" target="_blank" class="keylink">qq1xNa1PC9zdHJvbmc+oaPU2sSjyr3GpcXkyrGjrM2ouf0gXyCjqM3yxNzGpcXkt/ujqcC0zqqyu9Do0qq78cih1rW1xNfp1KrVvM67o6zDv7j2IF8gvfa/ydLUzqrSu7j21+nUqtW8zruhozwvcD4KPHA+oaGhoTxpbWcgc3JjPQ=="http://www.it165.net/uploadfile/files/2014/0920/20140920190600129.png" alt="\" />

4、元组可用于函数返回多个值的情形

  技术分享

  上例中,函数定义返回值类型为元组 (Int, String);


以下是对集合的简述:

Scala有一组丰富的集合库。集合是对事物的容器。这些容器可被测序,线性集像List, Tuple, Option, Map等集合的项目可具有元素的任意数量或有界到零个或一个元素(例如,Option)。

集合可能是严格或懒惰。懒集合有可能不消耗内存,直到他们被访问,就像范围元素。此外,集合可以是可变的(引用的内容可以更改)或不变(一个引用的东西指从未改变)。需要注意的是不可变的集合可能包含可变项。

对于一些问题,可变集合更好地工作,并为不可变集合更好地工作。如果有疑问,最好是先从一个不变的集合,如果需要可变进行更改。

本章给出最常用的集合类型对这些集合的信息和使用最频繁的操作。

SN 集合使用说明
1 Scala Lists
Scala的List[T]是T类型的链表
2 Scala Sets
集是相同类型的配对的不同元素的集合。
3 Scala Maps
映射是键/值对的集合。任何值可以根据它的键进行检索。
4 Scala Tuples
不像数组或列表,元组可以容纳不同类型的对象。
5 Scala Options
Option[T] 提供了一种容器,用于给定类型的零个或一个元素。
6 Scala Iterators
迭代不是集合,而是一种由一个访问的集合之一的元素。

示例:下面的代码片段是一个简单的例子来定义所有上述集合类型:

// Define List of integers.
val x = List(1,2,3,4)

// Define a set.
var x = Set(1,3,5,7)

// Define a map.
val x = Map("one" -> 1, "two" -> 2, "three" -> 3)

// Create a tuple of two elements.
val x = (10, "Scala")

// Define an option
val x:Option[Int] = Some(5)


映射和元组

摘要:

一个经典的程序员名言是:"如果只能有一种数据结构,那就用哈希表吧"。哈希表或者更笼统地说映射,是最灵活多变的数据结构之一。映射键/值对偶的集合。Scala有一个通用的叫法:元组,即n个对象的聚集,并不一定要相同类型的。对偶不过是一个 n=2的元组,元组对于那种需要将两个或更多值聚集在一起时特别有用。本篇的要点包括:

01. Scala有十分易用的语法来创建、查询和遍历映射。

02. 你需要从可变的和不可变的映射中做出选择。

03. 默认情况下,你得到的是一个哈希映射,不过你也可以指明要树形映射。

04. 你可以很容易地在Scala映射和Java映射之间来回切换。

05. 元组可以用来聚集值。

构造映射

不可变映射

我们可以这样构造一个映射:

val scores = Map ("Alice"-> 10, "Bob"->3, "Cindy"->8)

上述代码构造出一个不可变的Map[String,Int],其值不能被改变

可变映射

如果你想要一个可变映射,则用

val scores = scala.collection.mutable.Map("Alice"-> 10, "Bob"->3, "Cindy"->8)

如果想从—个空的映射开始,你需要选定一个映射实现并给出类型参数

val scores = new scala.collection.mutable.HashMap [String, Int]

在Scala中,映射是对偶的集合。对偶简单地说就是两个值构成的组,这两个值并不一定是同一个类型的,比如("Alice",10)

操作符创建对偶

操作符用来创建对偶:

"Alice"->10

上述代码产出的值是:

("Alice", 10)

完全也可以用下面这种方式来定义映射:

val scores=Map ( ("Alice", 10), ("Bob", 3), ("Cindy", 8) )

只不过->操作符看上去比圆括号更易读那么一点,也更加符合大家对映射的直观感觉:映射这种数据结构是一种将映射到函数。区别在于通常的函数计算值,而映射只是做查询

获取映射中的值

在Scala中,函数映射之间的相似性尤为明显,因为你将使用()表示法来查找某个键对应的值

val bobsScore = scores ("Bob") //类似于Java中的scores.get ("Bob")

如果映射并不包含请求中使用的键,则会抛出异常。要检查映射中是否有某个指定的键,可以用contains方法:

val bobsScore = if (scores.contains ("Bob")) scores("Bob") else 0

由于这样的组合调用十分普遍,以下是一个快捷写法:

val bobsScore = scores.getOrElse("Bob", 0) // 如果映射包含键"Bob",返回对应的值;否则,返回0

最后,映射.get(键)这样的调用返回一个Option对象,要么是Some(键对应的值),要么是None

更新键值

更新可变映射

在可变映射中,你可以更新某个映射的值,或者添加一个新的映射关系,做法是在=号的左侧使用()

scores ("Bob") = 10 // 更新键"Bob"对应的值

scores ("Fred")=7 // 增加新的键/值对偶到scores

或者,你也可以用+=操作来添加多个关系

scores+= ("Bob"-> 10, "Fred"->7)

移除某个键和对应的值,使用-=操作符

scores -= "Alice"

不可变映射

虽然不能更新一个不可变的映射,但你可以做一些同样有用的操作,即获取一个包含所需要的更新的新映射:

val newScores = scores+ ("Bob"->10,"Fred"->7) // 更新过的新映射

newScores映射包含了与scores相同的映射关系,此外"Bob"被更新,"Fred"被添加了进来

除了把结果作为新值保存外,你也可以更新Var变量:

var scores = …

scores = scores+ ("Bob"->10, "Fred"->7)

同理,要从不可变映射中移除某个键,你可以用一操作符来获取一个新的去掉该键的映射:

scores = scores - "Alice"

你可能会觉得这样不停地创建新映射效率很低,不过事实并非如此。老的和新的映射共享大部分结构。这样做之所以可行,是因为它们是不可变的。

迭代映射

如下这段超简单的循环即可遍历映射中所有的键/值对偶:

for ((k,v) <- 映射) 处理k和v

这里的"魔法"是你可以在Scala的for循环中使用模式匹配。这样一来,不需要冗杂的方法调用,你就可以得到每一个对偶的键和值

如果出于某种原因,你只需要访问键或值,像Java一样,则可以用keySetvalues方法。values方法返回—个Iterable,你可以在for循环当中使用这个Iterable

scores.keySet // 一个类似Set("Bob","Cindy","Fred","Alice")这样的集合

for ( v <- scores.values) printlnI(v) // 将打印10 8 7 10或其他排列组合

要反转一个映射,即交换键和值的位置,可以用:

for ( (k,v) <- 映射) yield (v.k)

已排序映射

在操作映射时,你需要选定一个实现:一个哈希表或者一个平衡树。默认情况下,Scala给的是哈希表。由于对使用的键没有很好的哈希函数,或者需要顺序地访问所有的键,因此,你可能会想要一个树形映射。

要得到一个不可变的树形映射而不是哈希映射的话,可以用:

val scores = scala.collections.immutable.SortedMap("Alice"->10,"Fred"->7, "Bob"->3,"Cindy"->8)

很可惜,Scala( 2.9)并没有可变的树形映射。如果那是你要的,最接近的选择是使用Java的TreeMap。需要注意的是:如果要按插入顺序访问所有键,使用LinkedHashMap,例如:

val months = scala.collection.mutable.LinkedHashMap("January" -> 1,"February" -> 2, "March" -> 3, …)

与Java互操作

Java到Scala

如果你通过Java方法调用得到了一个Java映射,你可能想要把它转换成一个Scala映射,以便使用更便捷的Scala映射API。这对于需要操作Scala,并未提供的可变树形映射的情况也很有用。只需要增加如下引入语句:

import scala.collection.JavaConversions .mapAsScalaMap

然后通过指定Scala映射类型来触发转换

val scores:scala.collection.mutable.Map[String, Int]=new java.util.TreeMap[String, Int]

除此之外,你还可以得到从java.util.PropertiesMap[String,String]的转换:

import scala.collection.JavaConversions.propertiesAsScalaMap

val props:Scala.collection.Map[String, String] = System.getProperties()

Scala到Java

反过来讲,要把Scala映射传递给预期Java映射的方法,提供相反的隐式转换即可

例如:

import scala.collection.JavaConversions.mapAsjavaMap

import java.awt.font.TextAttribute. _ // 引入下面的映射会用到的键

val attrs = Map ( FAMILY -> "Serif", SIZE -> 12 ) // Scala映射

val font=new java.awt.Font (attrs) // 该方法预期一个Java映射

元组

元组定义

映射是键/值对偶的集合。对偶足元组( tuple)的最简单形态,元组是不同类型的值的聚集元组的值是通过将单个的值包含在圆括号中构成的。例如:

(1, 3.14, "Fred")

是一个元组,类型为:

Tuple3 [Int, Double, java.lang.String]

类型定义也可以写为:

(Int, Double, java,lang.String)

如果你有一个元组,比如:

val t = (1,3.14, "Fred")

你就可以用方法_1、_2、_3访问其组元,比如:

val second = t._2 // 将second设为3.14

需要注意的是:和数组或字符串中的位置不同,元组的各组元从1开始,而不是0。你可以把t._2写为t _2,即用空格而不是句点,但不能写成t_2

获取元组

通常,使用模式匹配来获取元组的组元,例如:

val (first,second,third)=t //将first设为1,second设为3.14.third设为"Fred"

如果并不是所有的部件都需要,那么可以在不需要的部件位置上使用_

val (first, second, _ ) = t

元组可以用于函数需要返回不止一个值的情况。举例来说,StringOps的partition方法返回的是一对字符串,分别包含了满足某个条件和不满足该条件的字符:

"New York".partition ( _.isUpper) //输出对偶( "NY","ew ork")

拉链操作

使用元组的原因之一是把多个值绑在一起,以便它们能够被一起处理,这通常可以用zip方法来完成。举例来说,下面的代码:

val symbols = Array ("<","-",">")

val counts = Array (2, 10, 2)

val pairs = symbols.zip(counts)

输出对偶的数组:

Array ( ("<",2),("-",10), (">",2) )

然后这些对偶就可以被一起处理:

for ( (s,n) <- pairs ) Console.print(s*n) // 会打印<<---------->>

需要注意的是:用toMap方法可以将对偶的集合转换成映射。如果你有一个键的集合,以及一个与之平行对应的值的集合,那么你就可以用拉链操作将它们组合成一个映射:keys.zip(values) .toMap




以上内容借鉴
http://www.it165.net/pro/html/201409/22442.html
http://www.yiibai.com/scala/scala_collections.html
http://www.cnblogs.com/sunddenly/p/4420893.html
       

版权声明:欢迎转载,希望在你转载的同时,添加原文地址,谢谢配合

Scala详解---------数组、元组、映射

标签:

原文地址:http://blog.csdn.net/u011225629/article/details/47065581

(1)
(1)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!