1. 上一章:第 8 章
  2. 下一章:第 10 章
Kotlin 图解指南 • 第 9 章

集合:映射

章节封面图片

简介

在上一章中,我们看到了集合(如列表和集合)如何用于完成单独 individual 变量无法轻松完成的事情。在本章中,我们将介绍另一种集合——映射。

合适的工具做合适的工作

”你必须使用正确的工具来完成工作。”这是 Andrews 先生教他年幼的儿子 Jim 的,Jim 刚开始学习如何像他父亲一样成为一个杂务工。”当你要钉钉子时,你需要使用锤子,而不是螺丝刀。”

为了帮助 Jim 挑选正确的工具,他画了一张桌子,上面列出了他工具箱里不同的五金工具和工具。

一个两列的工具表格——左列是五金件,右列是工具。 Hammer Wrench Wrench Slotted Screwdriver Phillips Screwdriver Tool to Use Nail Hex Nut Hex Bolt Slotted Screw Phillips Screw Hardware

”现在,有了这张表,你就可以轻松查找所需的工具。只需扫描左列中你需要使用的五金工具,然后扫过右列查看要使用的正确工具即可。”

如何扫描表格。(简单的东西!) Hammer Wrench Wrench Slotted Screwdriver Phillips Screwdriver Tool to Use Nail Hex Nut Hex Bolt Slotted Screw Phillips Screw Hardware Which tool should be used with a slotted screw? A Slotted Screwdriver!

这样的表格表明事物之间存在关联——钉子与锤子关联,六角螺母与扳手关联,以此类推。在本章中,我们将构建 Kotlin 中类似的表格,但在此之前,让我们先创建一个单一的关联。

关联数据

关联两个值的一种简单方法是使用名为 Pair 的类。这个类的构造方法有两个参数。你可以调用它的构造方法,传入任意两个对象,无论它们的类型如何。在我们的例子中,让我们关联两个 String 对象——一个代表钉子,一个代表锤子。

val association = Pair("Nail", "Hammer")

Pair 是一个非常简单的类,有两个属性 firstsecond,你可以用它们来获取里面的值。下面是一个显示 Pair 类的 UML 图。firstsecond 的类型取决于调用构造方法时传入参数的类型,所以在该图中,我们只使用 AB 作为实际类型的占位符

显示 Pair 类及其两个属性的 UML 图。 Pair<A,B> + first: A + second: B

first 属性就是你调用构造方法时的第一个参数,而 second 就是第二个参数。

println(association.first)  // Nail
println(association.second) // Hammer

简单,对吧?

现在,有时使用名为 to() 的函数会更自然,它会为你调用 Pair 构造方法,而不是直接调用 Pair 类的构造方法。这个函数可以针对任何对象调用。让我们更新代码,使用 to() 函数。

val association = "Nail".to("Hammer")

阅读这段代码时,你可能会说:”当我有一根钉子时,我应该to一把锤子。”清单 9.1清单 9.3 做的是相同的事情——它们都创建一个 Pair,其中左边的值赋给名为 first 的属性,右边的值赋给名为 second 的属性。

to() 函数也有一个特殊的特性,让你可以在不使用标点符号的情况下使用它!所以,你也可以像这样创建同样的 Pair

val association = "Nail" to "Hammer"

注意,这和上面的清单 9.3是一样的,只是 .() 都省略了。当一个函数允许你以这种方式调用时,它被称为中缀函数。我们不会经常看到中缀函数,但了解它们的存在很重要,这样当看到这样的代码时就不会感到困惑。

到目前为止,我们使用了类型推断,这样就不必写出 association 变量的类型了。和上一章中的 ListSet 一样,Pair 变量的类型取决于它所包含的事物的类型。由于 “Nail” 和 “Hammer” 都是 String 类型,因此 association 变量的类型是 Pair<String, String>

如何构造 Pair 变量的类型。 Pair<String, String> Type of the first thing Type of the second thing

当然,我们也可以像这样显式指定类型:

val association: Pair<String, String> = "Nail" to "Hammer"

既然我们已经成功创建了一个单一的关联,我们就可以对其余的工具做同样的事情……然后将它们全部放入一个映射中!

映射基础

让我们再看看 Andrews 先生的表格。

再次显示表格。 Hammer Wrench Wrench Slotted Screwdriver Phillips Screwdriver Tool to Use Nail Hex Nut Hex Bolt Slotted Screw Phillips Screw Hardware

在 Kotlin 中,这样的表格称为映射(map)。你可能熟悉街道地图和藏宝图等地图,但我们这里说的不是这些。这个术语来自数学领域,映射定义了集合元素之间的对应关系。类似地,Kotlin 映射定义了左列中的每个条目与右列中相应条目之间的关联。

在我们创建第一个映射之前,先来了解几个重要的术语:

  • 表格左列中的项目称为(keys)。
  • 右列中的项目称为(values)。
  • 映射中键和值的关联称为映射条目(entry)。
表格中的键和值。 Hammer Wrench Wrench Slotted Screwdriver Phillips Screwdriver Tool to Use Nail Hex Nut Hex Bolt Slotted Screw Phillips Screw Hardware Keys Values 表格中的条目。 Hammer Wrench Wrench Slotted Screwdriver Phillips Screwdriver Tool to Use Nail Hex Nut Hex Bolt Slotted Screw Phillips Screw Hardware Entries

有一条重要规则需要记住——映射中的每个键都是唯一的。然而,值可以重复。换句话说,左列中不能有重复的条目,但右列中可以。你可以在下表中看到这一点,左列的条目是唯一的,但扳手在右列中出现了两次。

工具表格,显示左列不允许重复,但右列允许。 Hammer Wrench Wrench Slotted Screwdriver Phillips Screwdriver Tool to Use Nail Hex Nut Hex Bolt Slotted Screw Phillips Screw Hardware No duplicates in this column Duplicates allowed in this column Duplicated value!

使用 mapOf() 创建映射

既然我们已经理解了主要概念,是时候创建我们的第一个映射了!为此,我们将使用 mapOf() 函数,传入一个我们想要在映射中的每个关联的 Pair

val toolbox = mapOf(
    "Nail" to "Hammer",
    "Hex Nut" to "Wrench",
    "Hex Bolt" to "Wrench",
    "Slotted Screw" to "Slotted Screwdriver",
    "Phillips Screw" to "Phillips Screwdriver",
)

如果你读过上一章,你会发现这看起来类似于 listOf()setOf(),只是这里的所有元素都有两部分——,它们在 Pair 中连接在一起。

当你把 Kotlin 映射和 Andrews 先生的表格并排放在一起时,你可以看到它们之间的相似之处:

创建映射的 Kotlin 代码与手绘表格之间的相似之处。 Hammer Wrench Wrench Slotted Screwdriver Phillips Screwdriver Tool to Use Nail Hex Nut Hex Bolt Slotted Screw Phillips Screw Hardware val toolbox = mapOf ( "Nail" to "Hammer" , "Hex Nut" to "Wrench" , "Hex Bolt" to "Wrench" , "Slotted Screw" to "Slotted Screwdriver" , "Phillips Screw" to "Phillips Screwdriver" , )

就像列表、集合和其他变量一样,你可以使用 println() 来打印映射的内容。

println(toolbox)

当你打印时,映射的条目会出现在花括号之间。键在等号的左边,值在右边。

{Nail=Hammer, Hex Nut=Wrench, Hex Bolt=Wrench, Slotted Screw=Slotted Screwdriver, Phillips Screw=Phillips Screwdriver}

就像 Pair 一样,Map 变量的类型取决于键的类型和值的类型。

如何构造 Map 变量的类型。 Map<String, String> Type of the key Type of the value

因此,我们可以像这样显式地写出类型:

val toolbox: Map<String, String> = mapOf(
    "Nail" to "Hammer",
    "Hex Nut" to "Wrench",
    "Hex Bolt" to "Wrench",
    "Slotted Screw" to "Slotted Screwdriver",
    "Phillips Screw" to "Phillips Screwdriver",
)

查找值

使用映射时最常见的事情是查找值。例如,当 Jim 有一颗钉子时,他需要查找该使用哪种工具。就像 Jim 会在左列中找到钉子,然后在旁边找到相应的工具一样,Kotlin 可以在你提供键时给你对应的值。你可以使用 get() 函数来完成这项工作。

val tool = toolbox.get("Nail")
println(tool) // Hammer

与列表类似,你也可以使用映射的下标访问操作符来获取值。

val tool = toolbox["Nail"]
println(tool) // Hammer

如果你用不存在的键调用 get()(或使用下标访问操作符),它会返回 null。这意味着 get() 函数返回一个可空类型而不是非空类型!在清单 9.9 和 9.10 中,它返回 String? 而不是 String

你可以使用在第 6 章中学到的空安全工具(如空合并操作符)将其恢复为非空类型。或者,你可以调用 getValue() 而不是 get()getValue() 将返回非空类型,但要注意——如果你给它一个不存在的键,你会看到错误信息,你的代码将停止运行。

val tool = toolbox.getValue("Nail")
println(tool) // Hammer

val anotherTool = toolbox.getValue("Wing Nut") // Error at runtime

你也可以使用 getOrDefault() 在键不存在时提供默认值。如果 Andrews 先生没有某种五金件对应的工具,他就只能用手拧紧它了!

val tool = toolbox.getOrDefault("Hanger Bolt", "Hand")

修改映射

与其他集合类型一样,映射有两种可变性格式——MutableMap 和不可变的 Map。可变类型允许你更改其内容,而不可变映射则要求你创建一个新的映射实例,可以将其分配给新的或现有的变量。

让我们先看看如何更改 MutableMap。首先,我们需要使用 mutableMapOf() 来创建映射,而不是像在清单 9.6中那样只是用 mapOf()

val toolbox = mutableMapOf(
    "Nail" to "Hammer",
    "Hex Nut" to "Wrench",
    "Hex Bolt" to "Wrench",
    "Slotted Screw" to "Slotted Screwdriver",
    "Phillips Screw" to "Phillips Screwdriver",
)

要添加新条目,可以使用 put() 函数,其中第一个参数是键,第二个参数是值。

toolbox.put("Lumber", "Saw")

不过,就像 get() 函数一样,Kotlin 开发者通常使用下标访问操作符而不是直接调用 put() 函数。下面的代码实现与清单 9.14相同的功能。

toolbox["Lumber"] = "Saw"

你也可以用完全相同的方式更改现有值。只需提供一个已存在的键。

toolbox["Hex Bolt"] = "Nut Driver"

最后,你可以使用 remove() 函数删除条目。

toolbox.remove("Lumber")

请注意,虽然你可以更改值,但不能更改键。相反,你可以删除一个键并插入一个新条目。

toolbox.remove("Phillips Screw")
toolbox["Cross Recess Screw"] = "Phillips Screwdriver"

不可变映射

与不可变列表和集合一样,你可以在不可变映射上使用加法和减法操作符。请记住,这样做会创建新的映射实例,你通常会将其分配给一个变量。下面的代码演示了与上面相同的操作,但是在不可变映射上。请注意,我们在这里使用 var 关键字,这样我们就可以将每个结果重新分配给同一个 toolbox 变量!

var toolbox = mapOf(
    "Nail" to "Hammer",
    "Hex Nut" to "Wrench",
    "Hex Bolt" to "Wrench",
    "Slotted Screw" to "Slotted Screwdriver",
    "Phillips Screw" to "Phillips Screwdriver",
)

// Add an entry
toolbox = toolbox + Pair("Lumber", "Saw")

// Update an entry
toolbox = toolbox + Pair("Hex Bolt", "Nut Driver")

// Remove an entry
toolbox = toolbox - "Lumber"

// Simulate changing a key
toolbox = toolbox - "Phillips Screw"
toolbox = toolbox + Pair("Cross Recess Screw", "Phillips Screwdriver")

映射操作

ListSet 一样,Map 对象也有可以对其执行的操作,其中一些看起来非常熟悉。让我们从 forEach() 函数开始。

forEach()

forEach() 函数与 ListSet 对象上的函数几乎相同。它接受一个 lambda,你可以用它对映射中的每个条目做些什么。由于映射存储的是条目,lambda 的参数将是 Map.Entry 类型。

Map.Entry 与本章前面介绍的 Pair 类非常相似——它有两个属性,但不是叫 firstsecond,而是叫 keyvalue

Map.Entry 类的 UML 类图。 Map.Entry<K,V> + key: K + value: V

以下是你如何在 Map 上使用 forEach() 函数的方法。

toolbox.forEach { entry -> 
    println("Use a ${entry.value} on a ${entry.key}") 
}

当你运行这段代码时,你会看到以下输出。

Use a Hammer on a Nail
Use a Wrench on a Hex Nut
Use a Wrench on a Hex Bolt
Use a Slotted Screwdriver on a Slotted Screw
Use a Phillips Screwdriver on a Phillips Screw

因为它与你上一章看到的 forEach() 非常相似,你应该能够识别主要部分。它们是:

forEach() 函数的分解。 Lambda 参数 运行的代码 为每个条目 toolbox. forEach { entry -> println ( " ${ entry . key } and ${ entry . value } " ) } Map 变量

过滤

与列表和集合类似,你可以对映射进行 filter 过滤。请记住,就像我们之前在列表中看到的那样,这个函数不会修改现有映射——它会创建一个新的映射实例,所以你需要将结果分配给一个变量。

让我们把工具箱过滤到只剩下螺丝刀。

val screwdrivers = toolbox.filter { entry -> 
    entry.value.contains("Screwdriver")
}

结果是一个只包含螺丝刀的新 Map

在映射上使用 `filter()` 的效果。 Slotted Screwdriver Phillips Screwdriver Tool to Use Slotted Screw Phillips Screw Hardware Hammer Wrench Wrench Slotted Screwdriver Phillips Screwdriver Tool to Use Nail Hex Nut Hex Bolt Slotted Screw Phillips Screw Hardware

在这个例子中,我们根据 value 进行筛选,但你也可以根据键来筛选。

val screwdrivers = toolbox.filter { entry ->
    entry.key.contains("Screw")
}

映射转换

是的,你可以对 Map 进行映射转换!只需使用 mapKeys()mapValues() 函数来转换其键或值。就像我们在上一章看到的集合操作一样,你可以创建一个操作链。让我们在一个链中同时对键值进行映射转换。

val newToolbox = toolbox
    .mapKeys { entry -> entry.key.replace("Hex", "Flange") }
    .mapValues { entry -> entry.value.replace("Wrench", "Ratchet") }
使用 `mapKeys()` 和 `mapValues()` 函数的效果。 Hammer Ratchet Ratchet Slotted Screwdriver Phillips Screwdriver Tool to Use Nail Flange Nut Flange Bolt Slotted Screw Phillips Screw Hardware Hammer Wrench Wrench Slotted Screwdriver Phillips Screwdriver Tool to Use Nail Hex Nut Hex Bolt Slotted Screw Phillips Screw Hardware

Map 对象还有许多其他操作,你可以在 Kotlin 的API 文档中探索。不过,在继续之前,我们还要再研究一个操作——withDefault()

设置默认值

正如我们之前看到的,你可以使用 getOrDefault() 来优雅地处理键不存在的情况。然而,如果你每次都使用相同的默认值,这很快就会失控……

val tool = toolbox.getOrDefault("Hanger Bolt", "Hand")
val anotherTool = toolbox.getOrDefault("Dowel Screw", "Hand")
val oneMoreTool = toolbox.getOrDefault("Eye Bolt", "Hand")

相反,你可以使用一个名为 withDefault() 的操作,它将基于原始映射返回一个新映射。在这个新映射中,每当你使用一个不存在的键调用 getValue() 时,它会调用一个 lambda 并返回结果。就是这样:

toolbox = toolbox.withDefault { key -> "Hand" }

现在,你不需要在每次尝试获取值时都提供默认值(如上面示例 9.24所示),你可以正常调用 getValue()。这很好,因为如果你想更改默认值,只需要在一个地方修改,而不是很多地方!

val tool = toolbox.getValue("Hanger Bolt")
val anotherTool = toolbox.getValue("Dowel Screw")
val oneMoreTool = toolbox.getValue("Eye Bolt")

请记住,这适用于 getValue()适用于 get() 或索引访问运算符,如果找不到键,它们将继续返回 null

现在你知道如何创建和修改映射、如何从中获取值,以及如何使用集合操作。但当你开始将映射与其他集合结合使用时,事情会变得非常有趣!接下来让我们看看这一点。

从列表创建映射

我们使用 mapOf() 函数手动创建映射。也可以基于现有的列表或集合创建映射。通过一些重要的函数,你可以用许多不同的方式来处理你的数据!为了做到这一点,我们当然需要一个列表作为起点。

让我们创建一个来表示 Andrews 先生工具箱中的工具,而不是使用简单的 String,这样它可以保存工具的名称、以盎司为单位的重量以及它所对应的五金件。

class Tool(
    val name: String, 
    val weightInOunces: Int,
    val correspondingHardware: String,
)

现在,让我们创建一个 Tool 对象列表,包含 Andrews 先生工具箱中的工具。

val tools = listOf(
    Tool("Hammer", 14, "Nail"),
    Tool("Wrench", 8, "Hex Nut"),
    Tool("Wrench", 8, "Hex Bolt"),
    Tool("Slotted Screwdriver", 5, "Slotted Screw"),
    Tool("Phillips Screwdriver", 5, "Phillips Screw"),
)

现在我们有了列表,准备好从中创建一些映射了!

从对象列表中关联属性

你可以使用 associate() 函数从对象列表创建映射。首先,让我们使用 associate() 创建一个类似于示例 9.6中的映射:

val toolbox = tools.associate { tool ->
    tool.correspondingHardware to tool.name
}

希望你现在对集合操作感到越来越自在了。对于列表中的每个元素,associate() 函数会调用传递给它的 lambda。该 lambda 返回一个键值 Pair,其中包含你希望在结果映射中存在的键和值。

调用 associate() 函数的效果。 Map<String,String> Hammer Nail Wrench Hex Nut Wrench Hex Bolt Slotted Screwdriver Slotted Screw Phillips Screwdriver Phillips Screw Key Value Phillips Screwdriver 5 Phillips Screw correspondingHardware weightInOunces name Slotted Screwdriver 5 Slotted Screw correspondingHardware weightInOunces name Wrench 8 Hex Bolt correspondingHardware weightInOunces name Wrench 8 Hex Nut correspondingHardware weightInOunces name Hammer 14 Nail correspondingHardware weightInOunces name List<Tool>

下面是 associate() 函数的详细解析。

描述使用 associate() 函数时代码的不同部分。 Lambda parameter Pair to insert as an entry in the new map. val toolbox = tools . associate { tool -> tool . correspondingHardware to tool . name } Original list variable New map variable

通常,结果映射中的元素数量与原始列表中的元素数量相同。在某些情况下,它可能会更少。因为映射中的键都是唯一的,如果你尝试添加一个已存在的键,它将覆盖现有值。例如,让我们在 示例 9.29 的 lambda 中交换键和值的位置,使工具名称成为键,五金件成为值。

val toolbox = tools.associate { tool ->
    tool.name to tool.correspondingHardware
}

原始列表有两个 nameWrenchTool 对象,所以当 associate() 遇到第一个时,它被添加到映射中,但当它遇到第二个时,它会替换第一个值。因此,结果映射只包含 Hex Bolt 而不是 Hex Nut,因为两者中 Hex Bolt 是最后出现的。

当存在重复键时调用 associate() 函数的效果。 Map<String,String> Hammer Wrench Slotted Screwdriver Phillips Screwdriver Nail Hex Bolt Slotted Screw Phillips Screw Key Value Phillips Screwdriver 5 Phillips Screw correspondingHardware weightInOunces name Slotted Screwdriver 5 Slotted Screw correspondingHardware weightInOunces name Wrench 8 Hex Bolt correspondingHardware weightInOunces name Wrench 8 Hex Nut correspondingHardware weightInOunces name Hammer 14 Nail correspondingHardware weightInOunces name List<Tool>

所以在这种情况下,映射中的条目比原始列表中的元素少。也就是说,映射中只有 4 个条目,而列表中有 5 个元素。

其他关联函数

还有几个其他版本的 associate() 函数值得了解。如果你希望原始列表元素成为结果映射中的,这些会特别有帮助。

例如,如果你想创建一个键为工具名称、值为 Tool 对象的映射,可以使用 associateBy()。这个函数的 lambda 只返回。原始列表元素本身将是值。

val toolsByName = tools.associateBy { tool -> tool.name }
调用 associateBy() 函数的效果。 Key Value Map<String,Tool> Hammer Wrench Slotted Screwdriver Phillips Screwdriver Phillips Screwdriver 5 Phillips Screw correspondingHardware weightInOunces name Slotted Screwdriver 5 Slotted Screw correspondingHardware weightInOunces name Wrench 8 Hex Bolt correspondingHardware weightInOunces name Hammer 14 Nail correspondingHardware weightInOunces name Phillips Screwdriver 5 Phillips Screw correspondingHardware weightInOunces name Slotted Screwdriver 5 Slotted Screw correspondingHardware weightInOunces name Wrench 8 Hex Bolt correspondingHardware weightInOunces name Wrench 8 Hex Nut correspondingHardware weightInOunces name Hammer 14 Nail correspondingHardware weightInOunces name List<Tool>

使用这个映射,你可以通过名称轻松获取工具!

val hammer = toolsByName["Hammer"]

反过来,如果你想创建一个键为 Tool 对象、值在 lambda 中指定的映射,可以使用 associateWith() 函数。这个函数的 lambda 返回,原始列表元素将成为键。

val toolWeightInPounds = tools.associateWith { tool ->
    tool.weightInOunces * 0.0625
}
调用 associateWith() 函数的效果。 Key Value Map<Tool,Double> 0.3125 0.3125 0.5 0.5 0.875 Phillips Screwdriver 5 Phillips Screw correspondingHardware weightInOunces name Slotted Screwdriver 5 Slotted Screw correspondingHardware weightInOunces name Wrench 8 Hex Bolt correspondingHardware weightInOunces name Wrench 8 Hex Nut correspondingHardware weightInOunces name Hammer 14 Nail correspondingHardware weightInOunces name Phillips Screwdriver 5 Phillips Screw correspondingHardware weightInOunces name Slotted Screwdriver 5 Slotted Screw correspondingHardware weightInOunces name Wrench 8 Hex Bolt correspondingHardware weightInOunces name Wrench 8 Hex Nut correspondingHardware weightInOunces name Hammer 14 Nail correspondingHardware weightInOunces name List<Tool>

要获取锤子的重量,你需要已经有一个锤子对象。

val hammerWeightInPounds = toolWeightInPounds[hammer]

将列表元素分组到映射列表中

有时候,当你有一个列表时,你想根据某些特征将其拆分为多个较小的列表。例如,我们可以获取 tools 列表并按重量对其进行分组。

按重量(盎司)分组的工具。 14 oz each 8 oz each 5 oz each

为此,我们可以使用 groupBy() 函数。这个函数会为列表中的每个元素运行提供的 lambda。lambda 返回相同结果的元素将被组装成一个列表,并插入到映射中。

val toolsByWeight = tools.groupBy { tool ->
    tool.weightInOunces
}

结果是一个 Map,包含一个重量为 14 盎司的工具列表、另一个重量为 8 盎司的工具列表和第三个重量为 5 盎司的工具列表。映射的是重量(盎司),映射的是具有该重量的工具列表。

调用 groupBy() 函数的效果。 Key Value Map<Int,List<Tool 5 8 14 Phillips Screwdriver 5 Phillips Screw correspondingHardware weightInOunces name Slotted Screwdriver 5 Slotted Screw correspondingHardware weightInOunces name List<Tool> Wrench 8 Hex Bolt correspondingHardware weightInOunces name Wrench 8 Hex Nut correspondingHardware weightInOunces name List<Tool> Hammer 14 Nail correspondingHardware weightInOunces name List<Tool> Phillips Screwdriver 5 Phillips Screw correspondingHardware weightInOunces name Slotted Screwdriver 5 Slotted Screw correspondingHardware weightInOunces name Wrench 8 Hex Bolt correspondingHardware weightInOunces name Wrench 8 Hex Nut correspondingHardware weightInOunces name Hammer 14 Nail correspondingHardware weightInOunces name List<Tool>

下面是 groupBy() 函数的详细解析:

groupBy() 函数的分解。 Lambda parameter Elements that return the same thing here will be grouped together val toolsByWeight = tools . groupBy { tool -> tool . weightInOunces } Original list variable New map variable

如果你希望在结果列表中获得原始列表元素以外的东西,你也可以使用第二个参数调用此函数。为此,你需要传递一个 lambda,返回你希望在结果列表中需要的任何内容。例如,如果你只想要这些列表中工具的名称,你可以这样做:

val toolNamesByWeight = tools.groupBy(
    { tool -> tool.weightInOunces }, 
    { tool -> tool.name }
)
使用两个参数调用 groupBy() 函数的效果。 Key Value Map<Int,List<String 5 8 14 List<String> Phillips Screwdriver Slotted Screwdriver List<String> Wrench Wrench List<String> Hammer Phillips Screwdriver 5 Phillips Screw correspondingHardware weightInOunces name Slotted Screwdriver 5 Slotted Screw correspondingHardware weightInOunces name Wrench 8 Hex Bolt correspondingHardware weightInOunces name Wrench 8 Hex Nut correspondingHardware weightInOunces name Hammer 14 Nail correspondingHardware weightInOunces name List<Tool>

总结

Jim 在成长为像他父亲一样出色的杂务工的道路上走得很好。通过你在过去九章中获得的知识,你在成长为一名出色的 Kotlin 开发者的道路上也走得很好!以下是您在本章中学到的内容:

现在你已经学习了集合(如列表、集合和映射),你在代码中开启了许多可能性。在下一章中,我们将学习接收者和扩展。