映射(Maps)
Map
将 键 关联到 值,并在给定键时查找值。
您可以通过向 mapOf()
提供键值对来创建 Map
。使用 to
,我们将每个键与其关联的值分开:
// Maps/Maps.kt
import atomictest.eq
fun main() {
val constants = mapOf(
"Pi" to 3.141,
"e" to 2.718,
"phi" to 1.618
)
constants eq
"{Pi=3.141, e=2.718, phi=1.618}"
// 从键查找值:
constants["e"] eq 2.718 // [1]
constants.keys eq setOf("Pi", "e", "phi")
constants.values eq "[3.141, 2.718, 1.618]"
var s = ""
// 遍历键值对:
for (entry in constants) { // [2]
s += "${entry.key}=${entry.value}, "
}
s eq "Pi=3.141, e=2.718, phi=1.618,"
s = ""
// 在迭代期间解包:
for ((key, value) in constants) // [3]
s += "$key=$value, "
s eq "Pi=3.141, e=2.718, phi=1.618,"
}
- [1] 通过
[]
运算符使用键来查找值。您可以使用keys
获取所有键,使用values
获取所有值。调用keys
会产生一个Set
,因为Map
中的所有键必须是唯一的,否则在查找时会产生歧义。 - [2] 遍历
Map
会产生键值对的映射条目。 - [3] 在迭代期间,您可以解包键和值。
普通的 Map
是只读的。下面是一个 MutableMap
:
// Maps/MutableMaps.kt
import atomictest.eq
fun main() {
val m =
mutableMapOf(5 to "five", 6 to "six")
m[5] eq "five"
m[5] = "5ive"
m[5] eq "5ive"
m += 4 to "four"
m eq mapOf(5 to "5ive",
4 to "four", 6 to "six")
}
map[key] = value
添加或更改与 key
关联的 value
。您还可以使用 map += key to value
显式地添加一对。
mapOf()
和 mutableMapOf()
保留了元素放入 Map
的顺序。对于其他类型的 Map
,不保证元素的顺序。
只读的 Map
不允许进行修改:
// Maps/ReadOnlyMaps.kt
import atomictest.eq
fun main() {
val m = mapOf(5 to "five", 6 to "six")
m[5] eq "five"
// m[5] = "5ive" // 报错
// m += (4 to "four") // 报错
m + (4 to "four") // 不改变 m
m eq mapOf(5 to "five", 6 to "six")
val m2 = m + (4 to "four")
m2 eq mapOf(
5 to "five", 6 to "six", 4 to "four")
}
定义 m
创建了一个将 Int
关联到 String
的 Map
。如果我们试图替换一个 String
,Kotlin 将会产生错误。
带有 +
的表达式创建一个新的 Map
,其中包含旧的元素和新的元素,但不影响原始 Map
。向只读的 Map
添加元素的唯一方法是创建一个新的 Map
。
如果 Map
中不存在给定键的条目,它将返回 null
。如果您需要一个不能为 null
的结果,可以使用 getValue()
,如果键丢失则捕获 NoSuchElementException
:
// Maps/GetValue.kt
import atomictest.*
fun main() {
val map = mapOf('a' to "attempt")
map['b'] eq null
capture {
map.getValue('b')
} eq "NoSuchElementException: " +
"Key b is missing in the map."
map.getOrDefault('a', "??") eq "attempt"
map.getOrDefault('b', "??") eq "??"
}
getOrDefault()
通常是 null
或异常的一个更好的替代。
您可以将类实例存储为 Map
中的值。下面是一个根据数字 String
检索 Contact
的映射:
// Maps/ContactMap.kt
package maps
import atomictest.eq
class Contact(
val name: String,
val phone: String
) {
override fun toString(): String {
return "Contact('$name', '$phone')"
}
}
fun main() {
val miffy = Contact("Miffy", "1-234-567890")
val cleo = Contact("Cleo", "098-765-4321")
val contacts = mapOf(
miffy.phone to miffy,
cleo.phone to cleo)
contacts["1-234-567890"] eq miffy
contacts["1-111-111111"] eq null
}
可以使用类实例作为 Map
中的键,但这更加复杂,因此我们将在本书的后面讨论它。
- -
Map
看起来像是简单的小型数据库。它们有时被称为 关联数组,因为它们将键与值关联起来。尽管与全功能数据库相比它们相当有限,但它们仍然非常有用(并且比数据库更高效)。
练习和答案可以在 www.AtomicKotlin.com 找到。