集合
编程时,将数据分组到结构中以便后续处理非常有用。Kotlin 正是为了这个目的提供了集合。
Kotlin 提供了以下集合类型用于分组项:
集合类型 | 描述 |
---|---|
列表 | 有序的项集合 |
集 | 无序的唯一项集合 |
映射 | 键值对的集合,其中键是唯一的且只映射到一个值 |
每种集合类型都可以是可变的或只读的。
列表
列表按照项添加的顺序存储项,并允许重复项。
要创建一个只读列表 (List
),请使用 listOf()
函数。
要创建一个可变列表 (MutableList
), 请使用 mutableListOf()
函数。
创建列表时,Kotlin 可以推断存储的项的类型。要显式声明类型,请在列表声明后添加带尖括号 <>
的类型:
fun main() {
// Read only list
val readOnlyShapes = listOf("triangle", "square", "circle")
println(readOnlyShapes)
// [triangle, square, circle]
// Mutable list with explicit type declaration
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
println(shapes)
// [triangle, square, circle]
}
TIP
为防止意外修改,你可以通过将可变列表赋值给 List
来创建其只读视图:
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
val shapesLocked: List<String> = shapes
这也称为 类型转换。
列表是有序的,因此要访问列表中的项,请使用索引访问操作符 []
:
fun main() {
val readOnlyShapes = listOf("triangle", "square", "circle")
println("The first item in the list is: ${readOnlyShapes[0]}")
// The first item in the list is: triangle
}
要获取列表中的第一个或最后一个项,请分别使用 .first()
和 .last()
函数:
fun main() {
val readOnlyShapes = listOf("triangle", "square", "circle")
println("The first item in the list is: ${readOnlyShapes.first()}")
// The first item in the list is: triangle
}
要获取列表中的项数,请使用 .count()
函数:
fun main() {
val readOnlyShapes = listOf("triangle", "square", "circle")
println("This list has ${readOnlyShapes.count()} items")
// This list has 3 items
}
要检查某个项是否在列表中,请使用in
操作符:
fun main() {
val readOnlyShapes = listOf("triangle", "square", "circle")
println("circle" in readOnlyShapes)
// true
}
要从可变列表中添加或删除项,请分别使用 .add()
和 .remove()
函数:
fun main() {
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
// Add "pentagon" to the list
shapes.add("pentagon")
println(shapes)
// [triangle, square, circle, pentagon]
// Remove the first "pentagon" from the list
shapes.remove("pentagon")
println(shapes)
// [triangle, square, circle]
}
集
列表是有序的且允许重复项,而集是无序的且只存储唯一项。
要创建一个只读集 (Set
),请使用 setOf()
函数。
要创建一个可变集 (MutableSet
), 请使用 mutableSetOf()
函数。
创建集时,Kotlin 可以推断存储的项的类型。要显式声明类型,请在集声明后添加带尖括号 <>
的类型:
fun main() {
// Read-only set
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
// Mutable set with explicit type declaration
val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
println(readOnlyFruit)
// [apple, banana, cherry]
}
你可以在前面的示例中看到,由于集只包含唯一元素,重复的 "cherry"
项被丢弃了。
TIP
为防止意外修改,你可以通过将可变集赋值给 Set
来创建其只读视图:
val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
val fruitLocked: Set<String> = fruit
NOTE
由于集是无序的,你无法通过特定索引访问项。
要获取集中的项数,请使用 .count()
函数:
fun main() {
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("This set has ${readOnlyFruit.count()} items")
// This set has 3 items
}
要检查某个项是否在集中,请使用in
操作符:
fun main() {
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("banana" in readOnlyFruit)
// true
}
要从可变集中添加或删除项,请分别使用 .add()
和 .remove()
函数:
fun main() {
val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
fruit.add("dragonfruit") // Add "dragonfruit" to the set
println(fruit) // [apple, banana, cherry, dragonfruit]
fruit.remove("dragonfruit") // Remove "dragonfruit" from the set
println(fruit) // [apple, banana, cherry]
}
映射
映射将项存储为键值对。你可以通过引用键来访问值。你可以将映射想象成一份食物菜单。通过查找你想吃的食物(键),你可以找到价格(值)。如果你想在不使用像列表那样编号索引的情况下查找值,映射会很有用。
NOTE
映射中的每个键都必须是唯一的,这样 Kotlin 才能理解你想要获取哪个值。
映射中可以有重复的值。
要创建一个只读映射 (Map
),请使用 mapOf()
函数。
要创建一个可变映射 (MutableMap
), 请使用 mutableMapOf()
函数。
创建映射时,Kotlin 可以推断存储的项的类型。要显式声明类型,请在映射声明后添加带尖括号 <>
的键和值类型。例如:MutableMap<String, Int>
。键的类型为 String
,值的类型为 Int
。
创建映射最简单的方法是在每个键及其相关值之间使用 to
:
fun main() {
// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu)
// {apple=100, kiwi=190, orange=100}
// Mutable map with explicit type declaration
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(juiceMenu)
// {apple=100, kiwi=190, orange=100}
}
TIP
为防止意外修改,你可以通过将可变映射赋值给 Map
来创建其只读视图:
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
val juiceMenuLocked: Map<String, Int> = juiceMenu
要访问映射中的值,请使用带其键的索引访问操作符 []
:
fun main() {
// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("The value of apple juice is: ${readOnlyJuiceMenu["apple"]}")
// The value of apple juice is: 100
}
NOTE
如果你尝试使用映射中不存在的键来访问键值对,你会看到 null
值:
fun main() {
// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("The value of pineapple juice is: ${readOnlyJuiceMenu["pineapple"]}")
// The value of pineapple juice is: null
}
本教程稍后会在空安全章节中解释 null
值。
你也可以使用索引访问操作符 []
向可变映射中添加项:
fun main() {
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
juiceMenu["coconut"] = 150 // Add key "coconut" with value 150 to the map
println(juiceMenu)
// {apple=100, kiwi=190, orange=100, coconut=150}
}
要从可变映射中删除项,请使用 .remove()
函数:
fun main() {
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
juiceMenu.remove("orange") // Remove key "orange" from the map
println(juiceMenu)
// {apple=100, kiwi=190}
}
要获取映射中的项数,请使用 .count()
函数:
fun main() {
// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("This map has ${readOnlyJuiceMenu.count()} key-value pairs")
// This map has 3 key-value pairs
}
要检查映射中是否已包含特定键,请使用 .containsKey()
函数:
fun main() {
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.containsKey("kiwi"))
// true
}
要获取映射的键或值的集合,请分别使用 keys
和 values
属性:
fun main() {
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.keys)
// [apple, kiwi, orange]
println(readOnlyJuiceMenu.values)
// [100, 190, 100]
}
要检查键或值是否在映射中,请使用in
操作符:
fun main() {
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("orange" in readOnlyJuiceMenu.keys)
// true
// Alternatively, you don't need to use the keys property
println("orange" in readOnlyJuiceMenu)
// true
println(200 in readOnlyJuiceMenu.values)
// false
}
有关集合可以执行的操作的更多信息,请参阅集合。
既然你已经了解了基本类型以及如何管理集合,现在是时候探索可以在程序中使用的控制流了。
练习
练习 1
你有一组“绿色”数字和一组“红色”数字。补全代码以打印总共有多少个数字。
|---|---|
fun main() {
val greenNumbers = listOf(1, 4, 23)
val redNumbers = listOf(17, 2)
// Write your code here
}
|---|---|
fun main() {
val greenNumbers = listOf(1, 4, 23)
val redNumbers = listOf(17, 2)
val totalCount = greenNumbers.count() + redNumbers.count()
println(totalCount)
}
练习 2
你的服务器支持一组协议。用户请求使用特定协议。补全程序以检查请求的协议是否受支持(isSupported
必须是一个布尔值)。
|---|---|
fun main() {
val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
val requested = "smtp"
val isSupported = // Write your code here
println("Support for $requested: $isSupported")
}
|---|---|
fun main() {
val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
val requested = "smtp"
val isSupported = requested.uppercase() in SUPPORTED
println("Support for $requested: $isSupported")
}
练习 3
定义一个将整数 1 到 3 关联到其对应拼写的映射。使用此映射来拼写给定的数字。
|---|---|
fun main() {
val number2word = // Write your code here
val n = 2
println("$n is spelt as '${<Write your code here >}'")
}
|---|---|
fun main() {
val number2word = mapOf(1 to "one", 2 to "two", 3 to "three")
val n = 2
println("$n is spelt as '${number2word[n]}'")
}