第4章 映射和元组

4.1 构造映射

可以这样构造一个映射:

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

这样构造出来的Map是不可变的,如果需要一个可变的映射,可以使用:

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

如果想构造一个空的映射,则需要指定参数类型:

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

事实上,"Alice" -> 10操作符等同于`("Alice", 10),但前者显然看起来更加直观,更加的Scala。


4.2 获取映射中的值

获取映射的时候,使用圆括号:

val bobScore = scores("Bob")

但有时候判断映射中是否有指定的键,使用contains方法:

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

其实,还有更Scala的写法:

val bobScore = scores.getOrElse("Bob", 0)

注意,映射的get方法返回的是Option对象,在14章中会详细介绍。


4.3 更新映射中的值

只有可变的映射可以进行值的更新。

scores("Bob") = 10

或者可以使用+=操作符来添加多个关系:

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

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

scores -= "Alice"

上述的+=-=操作符都是针对可变映射而言的,对于不可变的映射,可以新建一个映射:

val newScores = score + ("Bob" -> 10, "Fred" -> 7)

或者使用var来声明集合:

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

实际上,这样不停的创建新映射的效率并不会很低,老的映射与新的映射共享大部分结构。


4.4 迭代映射

可以通过for ((k, v) <- 映射)来遍历映射。

如果只需要访问键或值,可以使用scores.keySetscores.values

反转映射的快速方法:for ((k, v) <- 映射) yield (v, k)


4.5 已排序映射

Scala的映射实现方式有2种---哈希表与平衡树,默认是哈希表。Scala没有可变的树形映射,如果需要按一定顺序访问所有的键,可以使用SortedMap

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

如果你需要可变的树形映射,建议使用Java的TreeMap

如果想要按照插入顺序来访问所有键,使用LinkedHashMap

val scores = scala.collection.immutable.LinkedHashMap("January" -> 1, "February" -> 2, "March" -> 3, ...)


4.6 与Java的互操作

通过隐式转换,可以实现Java与Scala的映射转换。

Java转Scala映射:

import scala.collection.JavaConversions.mapAsScalaMap

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

Scala转Java映射:

import scala.collection.JavaConversions.mapAsJavaMap
import java.awt.font.TextAttribute._

val attrs = Map(FAMILY -> "Serif", SIZE -> 12)
val font = new Font(attrs)
4.7 元组

元组是不同类型集的聚集,如:

(1, 3.14, "Fred")是一个类型为Tuple3[Int, Double, java.lang.String]的元组。

通过_1_2_3访问元组的组元(注意组元从1开始索引,而不是0)。

可以使用模式匹配来获取元组的组员,如果有不需要的成员,用_来代替。

val (first, second, _) = t

元组可以用于函数需要返回值不止一个的情况。

4.8 拉链操作

元组可以把多个值绑在一起,通常可以用zip方法来完成,举例来说:

val symbols = Array("<", "-", ">")
val counts = Array(2, 10, 2)
val pairs = symbols.zip(counts)

返回的结果是Array(("<", 2), ("-", 10), (">", 2))

toMap方法可以将对偶(二元组)的集合转换成映射:keys.zip(values).toMap


书籍推荐