The mapping transformation creates a collection from the results of a function on the elements of another collection.
如上面引用的官方文档所言,map
函数的功能就是对于调用的Collection
的每个元素,应用一个Transformation
,然后返回一个新的Collection
。官方的示例用法如下:
val numbers = setOf(1, 2, 3)
println(numbers.map { it * 3 })
// return [3, 6, 9]
map
这个函数,被很多人翻译为“遍历”,我觉得不太恰当。诚然,该函数的确会对调用函数的Collection
每个元素进行遍历,但是其主要功能是对每个元素进行一个变换,然后返回变换后的新的Collection
。
我觉得更好的翻译应该是“映射”,即将原Collection
的每个元素映射为一个新的元素,并且构成一个新的Collection
。在实际应用中,这种映射可能存在以下几种情况:
// case 1
collection.map { it.property }
// case 2
collection.map { it * 3 }
// case ...
第一种情况,就是将原元素,映射为其属性。如此返回的新Collection
,实际上就是由每个元素对应的属性所构成的。
第二种情况,就是将原元素,映射为其调用times(3)
函数的返回值,由每个元素的如此的返回值,构成一个新的Collection
。
If you operate nested collections, you may find the standard library functions that provide flat access to nested collection elements useful.
根据上述官方的定义,flatten
函数的功能其实就是“展开”,即将嵌套的Collection
,展开为最底层的元素。官方示例如下:
val numberSets = listOf(setOf(1, 2, 3), setOf(4, 5, 6), setOf(1, 2))
println(numberSets.flatten())
// return [1, 2, 3, 4, 5, 6, 1, 2]
注意这个函数应该只能用于直接嵌套的情况,亦即由Collection
组成的Collection
。而对于间接嵌套的情况,例如一个由对象构成的Collection
,每个对象包含一个Collection
类型的属性,则需要用到下面的flatMap
函数。
flatMap
函数的词根是 map,而前缀才是 flat,因此是映射基础上的展开。实际上可以按照次序先后拆分为一个map
函数和一个flatten
函数。即先对调用的Collection
进行映射,生成一个新的Collection
,然后再对新生成的Collection
的每个(Collection
)元素进行展开。
例如我们现在有两个类,Player
是游戏的角色,Item
是装备。两个类定义如下:
data class Player(
val name: String, // 角色名
val items: List<Item> // 装备列表
)
data class Item(
val name: String, // 装备名
val damage: Int, // 伤害值
val defense: Int // 防御值
)
假设我们要获取每个角色的所有装备,即每个Player
的所有Item
,那么直接使用flatten
函数是不行的,必须要使用flatMap
函数。示例代码如下:
val itemList1 = listOf(Item("泰阿剑", 86, 0), Item("纯钧剑", 102, 0))
val itemList2 = listOf(Item("玄晶甲", 0, 48), Item("浸血甲", 0, 68))
val player1 = Player("剑侍", itemList1)
val player2 = Player("豪杰", itemList2)
val playerList = listOf(player1, player2)
println(playerList.flatMap { it.items })
// 等价于
// println(playerList.map { it.items }.flatten())
其中,playerList.flatMap { it.items }
与playerList.map { it.items }.flatten()
在效果上是等价的。