Scala 集合:Map API

栏目: Scala · 发布时间: 5年前

内容简介:Map 定义了键值对的特质类型,区分可变与不可变,间接继承了偏函数 PartialFunction 特质,所以一个 Map 本质上也是一个偏函数,其定义如下:其伴生对象提供了构造 Map 对象的简单方式,示例:可变 Map 与不可变 Map 的相互转换:

Map 定义了键值对的特质类型,区分可变与不可变,间接继承了偏函数 PartialFunction 特质,所以一个 Map 本质上也是一个偏函数,其定义如下:

trait Map[K, +V] extends Iterable[(K, V)] with GenMap[K, V] with MapLike[K, V, Map[K, V]]

其伴生对象提供了构造 Map 对象的简单方式,示例:

val map1 = Map("name" -> "zhenchao", "age" -> 28)
val map2 = Map(("name", "zhenchao"), ("age", 28))

可变 Map 与不可变 Map 的相互转换:

  • 可变 -> 不可变

将可变 Map 转换成不可变 Map 的最简单方式就是调用 toMap 函数,但是如果希望转换成特定类型的不可变 Map 类型,则需要借助 ++ 函数,示例:

val mmap = mutable.Map("name" -> "zhenchao", "age" -> 28)
val map = mmap.toMap
map // 输出:Map(age -> 28, name -> zhenchao)
val tmap = mutable.TreeMap.empty[String, AnyVal] ++ mmap
tmap // 输出:TreeMap(age -> 28, name -> zhenchao)
  • 不可变 -> 可变

不可变 Map 转换成可变 Map 也需要借助 ++ 函数实现,示例:

val map = Map("name" -> "zhenchao", "age" -> 28)
val mmap = mutable.Map.empty[String, AnyVal] ++ map
mmap // 输出:Map(name -> zhenchao, age -> 28)

一. 查询操作

1.1 get & getOrElse & apply

函数 get、getOrElse 和 apply 均用于从 Map 对象中获取元素,区别在于 get 操作返回 Option 类型,getOrElse 允许在对应 key 不命中时返回默认的 value,而 apply 同样是返回指定的 key 对应的 value,但是在 key 不命中时默认抛出 NoSuchElementException 异常。示例:

val map = Map("name" -> "zhenchao", "age" -> 28)
map.get("name") // 输出:zhenchao
map.getOrElse("school", "WHU") // 输出:WHU
map.apply("age") // 输出:28
map("age") // 输出:28

函数 apply 同样可以使用 () 表达式简写。

1.2 withDefault & withDefaultValue

上面在使用 apply 函数时,在 key 不命中的情况下默认会抛出 NoSuchElementException,如果希望改变这种行为,我们可以使用 withDefault 或 withDefaultValue 函数自定义默认行为,其中 withDefault 接收一个函数(入参是 key),而 withDefaultValue 则接收一个默认值。示例:

val map = Map("name" -> "zhenchao", "age" -> 28)
val map1 = map.withDefault(key => "invalid key: " + key)
val map2 = map.withDefaultValue("unknown")
map1("school") // 输出:invalid key: school
map2("school") // 输出:unknown

1.3 getOrElseUpdate

对于可变集合来说,可以使用 getOrElseUpdate 函数(定义如下),该函数允许提供一个 op 操作,如果对应的 key 存在则返回对应的 value,否则会计算 op 得到一个 value,并更新 Map 对象,同时返回该 value。

def getOrElseUpdate(key: K, op: => V): V

示例:

val mmap = mutable.Map("name" -> "zhenchao", "age" -> 28)
mmap.getOrElseUpdate("school", "WHU") // 输出:WHU

二. 插入操作

插入操作允许 value 为 null,但不允许 key 为 null,此外对于已经存在的 key,插入操作相当于更新操作。

2.1 +

函数 + 用于往 Map 对象中添加一个或多个键值对,函数定义如下:

def + [V1 >: V](kv: (K, V1)): Map[K, V1]
def + [V1 >: V] (elem1: (K, V1), elem2: (K, V1), elems: (K, V1) *): immutable.Map[K, V1]

示例:

val map = Map("name" -> "zhenchao", "age" -> 28)
map + ("school" -> "WHU") // 输出:Map(name -> zhenchao, age -> 28, school -> WHU)
map + ("school" -> "CMU", "gender" -> "M") // 输出:Map(name -> zhenchao, age -> 28, school -> CMU, gender -> M)

2.2 ++ & ++:

函数 ++ 接收一个 GenTraversableOnce 类型的参数,只要是继承 GenTraversableOnce 的集合都可以作为参数,函数会将参数中所包含的元素添加到原 Map 对象中,并创建一个新的 Map 返回。示例:

val map = Map("name" -> "zhenchao", "age" -> 28)
map ++ Seq("school" -> "CMU", "gender" -> "M") // 输出:Map(name -> zhenchao, age -> 28, school -> CMU, gender -> M)
map ++: Seq("school" -> "CMU", "gender" -> "M") // 输出:List((name,zhenchao), (age,28), (school,CMU), (gender,M))

函数 ++:++ 的右结合版本。

2.3 += & ++= & put

对于可变集合而言,可以实现原地插入,函数 += 对标 + ,函数 ++= 对标 ++ ,函数 put 用于插入单个键值对,并返回一个 Option 类型,表示插入操作之前对应的 value。示例:

val mmap = mutable.Map("name" -> "zhenchao", "age" -> 28)
mmap += ("school" -> "WHU")
mmap += ("school" -> "CMU", "gender" -> "M")
mmap // 输出:Map(school -> CMU, age -> 28, name -> zhenchao, gender -> M)
mmap ++= Seq("age" -> 29, "gender" -> "M")
mmap // 输出:Map(school -> CMU, age -> 29, name -> zhenchao, gender -> M)
mmap.put("country", "China")
mmap // 输出:Map(school -> CMU, country -> China, age -> 29, name -> zhenchao, gender -> M)

三. 更新操作

3.1 updated

函数 updated 用于更新 Map 对象中指定的 key 和 value,如果不存在则添加,示例:

val map = Map("name" -> "zhenchao", "age" -> 28)
map.updated("age", 29) // 输出:Map(name -> zhenchao, age -> 29)
map.updated("school", "WHU") // 输出:Map(name -> zhenchao, age -> 28, school -> WHU)

3.2 update & put

对于可变集合而言,可以实现原地更新操作,函数 update 用于更新一个可变 Map 中的 key 和 value,如果不存在则会添加,效果上等价于 put,示例:

val mmap = mutable.Map("name" -> "zhenchao", "age" -> 28)
mmap.update("age", 29)
mmap.update("school", "WHU")
mmap("school") = "CMU"
mmap // 输出:Map(school -> CMU, age -> 29, name -> zhenchao)

函数 update 同样可以简写为 () 表达式。

四. 删除操作

4.1 - & --

函数 - 用于删除指定的一个或多个 key,而函数 -- 则接收一个 GenTraversableOnce 类型参数,用于批量删除给定集合中包含的所有 key,示例:

val map = Map("name" -> "zhenchao", "age" -> 28)
map - "name" // 输出:Map(age -> 28)
map -- Set("age", "school") // 输出:Map(name -> zhenchao)

4.2 -= & --= & remove & clear

对于可变集合而言,可以实现原地删除,函数 -= 对标 - ,函数 --= 对标 -- ,示例:

val mmap = mutable.Map("name" -> "zhenchao", "age" -> 28)
mmap -= "name"
mmap --= Set("age", "school")
mmap // 输出:Map()

函数 remove 用于从可变 Map 对象中删除给定的 key,并返回 key 对应的 value,Option 类型。函数 clear 用于清空整个 Map 对象。

五. 包含检查

5.1 contains & isDefinedAt

函数 contains 和 isDefinedAt 均用于检查 Map 对象中是否包含指定的 key,示例:

val map = Map("name" -> "zhenchao", "age" -> 28)
map.contains("name") // 输出:true
map.isDefinedAt("school") // 输出:false

其中 isDefinedAt 继承自偏函数。

六. 获取键或值的集合

6.1 keys & keySet & keysIterator

函数 keys、keySet 和 keysIterator 均用于获取 Map 对象键的集合,区别在于函数 keys 返回的是 Iterable[K] 类型对象;函数 keySet 返回的是 Set[K] 类型对象;而函数 keysIterator 返回一个 Iterator[K] 类型对象。

6.2 values & valuesIterator

函数 values 和 valuesIterator 均用于获取 Map 对象值的集合,区别在于函数 values 返回的是 Iterable[V] 类型,而函数 valuesIterator 返回的是 Iterator[V] 类型。

七. 转换操作

Map 对象考虑其特性,增加了 filterKeys、mapValues 和 transform 函数。

7.1 filterKeys

函数 filterKeys 对 Map 对象中的 key 进行筛选,并保留满足条件的元素,示例:

val map = Map(1 -> "zhangsan", 2 -> "lisi", 3 -> "wanger")
map.filterKeys(_ % 2 == 0) // 输出:Map(2 -> lisi)

7.2 mapValues & transform

函数 mapValues 和 transform 均用于对 Map 对象的值进行转换,区别在于函数 mapValues 的入参只有 value,而 transform 的入参除了 value,还包含 key,示例:

val map = Map(1 -> "zhangsan", 2 -> "lisi", 3 -> "wanger")
map.mapValues(_.reverse) // 输出:Map(1 -> nasgnahz, 2 -> isil, 3 -> regnaw)
map.transform((k, v) => v + k) // 输出:Map(1 -> zhangsan1, 2 -> lisi2, 3 -> wanger3)

对于可变 Map 而言,因为是原地转换,所以要求 transform 操作输出的 value 类型与输入的类型相同。

八. 反转操作

对于给定的 Map 集合,我们可以使用 map 函数很容易将 key 和 value 反转,但是如果 value 存在重复,那么这个时候我们可能希望反转之后的 value 是一个集合类型,这种需求该如何实现?

// value 不重复
val map = Map(1 -> "zhangsan", 2 -> "lisi", 3 -> "wanger")
map.map(t => (t._2, t._1)) // 输出:Map(zhangsan -> 1, lisi -> 2, wanger -> 3)
map.map { case (x, y) => (y, x) } // 输出:Map(zhangsan -> 1, lisi -> 2, wanger -> 3)

// value 重复
val map2 = Map("a" -> 1, "b" -> 2, "c" -> 2, "d" -> 3, "e" -> 1)
map2.groupBy(_._2).mapValues(_.keys.toList) // 输出:Map(2 -> List(b, c), 1 -> List(e, a), 3 -> List(d))

上述示例中重复 value 的反转执行流程如下:

Map(2 -> Map(b -> 2, c -> 2), 1 -> Map(e -> 1, a -> 1), 3 -> Map(d -> 3))

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

凸优化

凸优化

Stephen Boyd、Lieven Vandenberghe / 王书宁、许鋆、黄晓霖 / 清华大学出版社 / 2013-1 / 99.00元

《信息技术和电气工程学科国际知名教材中译本系列:凸优化》内容非常丰富。理论部分由4章构成,不仅涵盖了凸优化的所有基本概念和主要结果,还详细介绍了几类基本的凸优化问题以及将特殊的优化问题表述为凸优化问题的变换方法,这些内容对灵活运用凸优化知识解决实际问题非常有用。应用部分由3章构成,分别介绍凸优化在解决逼近与拟合、统计估计和几何关系分析这三类实际问题中的应用。算法部分也由3章构成,依次介绍求解无约束......一起来看看 《凸优化》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具