Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

映射(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 关联到 StringMap。如果我们试图替换一个 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 找到。