Kotlin 集合
最后修改于 2024 年 1 月 29 日
在本文中,我们将展示如何在 Kotlin 中使用集合。 集合是元素的通用无序集合,不允许重复。
Kotlin 区分只读集合和可变集合。 只读集合使用 setOf
创建,可变集合使用 mutableSetOf
创建。
Kotlin setOf
setOf
方法在 Kotlin 中创建一个新的只读集合。
package com.zetcode fun main() { val words = setOf("pen", "cup", "dog", "spectacles") println("The set contains ${words.size} elements.") }
该示例使用 setOf
创建一个由单词组成的新集合。 集合的大小由 size
属性确定。
一个集合不能包含重复的元素。
package com.zetcode fun main() { val words2 = setOf("pen", "cup", "dog", "pen", "spectacles") words2.forEach { e -> println(e)} }
即使我们在 setOf
中添加了两个笔,也只会有一个笔的元素。
pen cup dog spectacles
Kotlin 集合基础知识
在下一个示例中,我们有一个简单的 Kotlin 集合示例。
package com.zetcode fun main() { val nums = setOf(11, 5, 3, 8, 1, 9, 6, 2) val len = nums.count() val max = nums.max() val min = nums.min() val sum = nums.sum() val avg = nums.average() val msg = """ max: $max, min: $min, count: $len, sum: $sum, average: $avg """ println(msg.trimIndent()) }
该示例创建一个数字集合并计算一些统计数据。
val nums = setOf(11, 5, 3, 8, 1, 9, 6, 2)
一个 Kotlin 只读集合是用 setOf
函数创建的。
val len = nums.count() val max = nums.max() val min = nums.min() val sum = nums.sum() val avg = nums.average()
我们计算值的数量、最大值、最小值、总和以及值的平均值。
max: 11, min: 1, count: 8, sum: 45, average: 5.625
Kotlin 集合索引
集合的每个元素都有一个索引。 Kotlin 集合索引从零开始。 最后一个元素的索引为 len-1
。
package com.zetcode fun main() { val words = setOf("pen", "cup", "dog", "person", "cement", "coal", "spectacles", "cup", "bread") val w1 = words.elementAt(0) println(w1) val i1 = words.indexOf("cup") println("The first index of cup is $i1") val i2 = words.lastIndexOf("cup") println("The last index of cup is $i2") }
该示例演示了 Kotlin 集合索引操作。
val w1 = words.elementAt(0)
一个元素使用 elementAt
方法检索。 该方法将要检索的元素的索引作为参数。
val i1 = words.indexOf("cup")
indexOf
返回单词在集合中第一次出现的索引。
val i2 = words.lastIndexOf("cup")
lastIndexOf
返回单词在集合中最后一次出现的索引。
pen The first index of cup is 1 The last index of cup is 1
Kotlin 集合计数
count
方法返回集合中元素的数量。
package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12) val len = nums.count() println("There are $len elements") val size = nums.size println("The size of the set is $size") val n1 = nums.count { e -> e < 0 } println("There are $n1 negative values") val n2 = nums.count { e -> e % 2 == 0 } println("There are $n2 even values") }
该示例返回集合中值的数量、负值的数量和偶数的数量。
val len = nums.count() println("There are $len elements") val size = nums.size println("The size of the set is $size")
我们可以使用 count
方法或 size
属性来确定集合中元素的数量。
val n1 = nums.count { e -> e < 0 }
count
可以将一个谓词函数作为参数。 在我们的例子中,它对小于 0 的值返回 true。
val n2 = nums.count { e -> e % 2 == 0 }
我们得到集合中偶数的数量。
There are 11 elements The size of the set is 11 There are 3 negative values There are 5 even values
Kotlin 集合的第一个和最后一个元素
我们有获取集合的第一个和最后一个元素的方法。
package com.zetcode fun main() { val words = setOf("pen", "cup", "dog", "person", "cement", "coal", "donkey", "spectacles") val w1 = words.first() println(w1) val w2 = words.last() println(w2) val w3 = words.findLast { w -> w.startsWith('d') } println(w3) val w4 = words.first { w -> w.startsWith('d') } println(w4) }
该示例创建一个单词集合。 我们获取集合的第一个和最后一个元素。
val w1 = words.first()
我们使用 first
获取第一个元素。
val w2 = words.last()
我们使用 last
获取最后一个元素。
val w3 = words.findLast { w -> w.startsWith('d') }
我们使用 findLast
检索以 'd' 开头的集合的最后一个元素。
val w4 = words.first { w -> w.startsWith('d') }
我们使用 first
检索以 'd' 开头的集合的第一个元素。
pen spectacles donkey dog
Kotlin 集合迭代
集合迭代或集合循环是逐个遍历集合元素的过程。
package com.zetcode fun main() { val words = setOf("pen", "cup", "dog", "person", "cement", "coal", "spectacles") words.forEach { e -> print("$e ") } println() for (word in words) { print("$word ") } println() for (i in 0 until words.size) { print("${words.elementAt(i)} ") } println() words.forEachIndexed({i, e -> println("$i - $e")}) val it: Iterator<String> = words.asIterable().iterator() while (it.hasNext()) { val e = it.next() print("$e ") } println() }
该示例展示了在 Kotlin 中循环遍历集合的五种方法。
words.forEach { e -> print("$e ") }
forEach
对每个集合元素执行给定的操作。 我们向它传递一个匿名函数,该函数打印当前元素。
for (word in words) { print("$word ") }
我们使用 for
循环集合。 for
循环逐个遍历集合元素; 在每个周期中,word
变量指向集合中的下一个元素。
for (i in 0 until words.size) { print("${words.elementAt(i)} ") }
一个备用的 for
循环利用集合的大小。 until
关键字创建一个集合索引的范围。
words.forEachIndexed({i, e -> println("$i - $e")})
使用 forEachIndexed
方法,我们循环遍历集合,在每次迭代中都有索引和值可用。
val it: Iterator<String> = words.asIterable().iterator() while (it.hasNext()) { val e = it.next() print("$e ") }
最后一种方法是使用 Iterator
和 while
循环。
pen cup dog person cement coal spectacles pen cup dog person cement coal spectacles pen cup dog person cement coal spectacles 0 - pen 1 - cup 2 - dog 3 - person 4 - cement 5 - coal 6 - spectacles pen cup dog person cement coal spectacles
Kotlin 集合排序
以下示例展示了如何在 Kotlin 中对集合值进行排序。 由于使用 setOf
创建的集合是只读的,因此这些方法不会更改集合,而是返回一个新的修改后的列表。
package com.zetcode data class Car(var name: String, var price: Int) fun main() { val nums = setOf(11, 5, 3, 8, 1, 9, 6, 2) val sortAsc = nums.sorted() println(sortAsc) val sortDesc = nums.sortedDescending() println(sortDesc) val revNums = nums.reversed() println(revNums) val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600)) val res = cars.sortedBy { car -> car.name } res.forEach { e -> println(e) } println("*************") val res2 = cars.sortedByDescending { car -> car.name } res2.forEach { e -> println(e) } }
该示例按升序和降序对集合值进行排序,反转集合元素,并按其名称对汽车对象进行排序。
val sortAsc = nums.sorted()
sorted
方法返回一个根据其自然排序顺序排序的所有元素的列表。
val sortDesc = nums.sortedDescending()
sortedDescending
方法返回一个根据其自然排序顺序降序排序的所有元素的列表。
val revNums = nums.reversed()
reversed
方法返回一个元素反转的列表。
val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600))
我们创建一个汽车对象集合。 这些对象可以按其名称或其价格进行排序。
val res = cars.sortedBy { car -> car.name }
使用 sortedBy
,我们按升序对汽车按其名称进行排序。
val res2 = cars.sortedByDescending { car -> car.name }
使用 sortedByDescending
,我们按降序对汽车按其名称进行排序。
[1, 2, 3, 5, 6, 8, 9, 11] [11, 9, 8, 6, 5, 3, 2, 1] [2, 6, 9, 1, 8, 3, 5, 11] Car(name=Mazda, price=6300) Car(name=Mercedes, price=18600) Car(name=Skoda, price=5670) Car(name=Toyota, price=12400) ************* Car(name=Toyota, price=12400) Car(name=Skoda, price=5670) Car(name=Mercedes, price=18600) Car(name=Mazda, price=6300)
Kotlin 集合包含
使用 contains
方法,我们可以检查集合是否包含指定的元素。
package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12) val r = nums.contains(4) if (r) println("The set contains 4") else println("The set does not contain 4") val r2 = nums.containsAll(setOf(1, -1)) if (r2) println("The set contains -1 and 1") else println("The set does not contain -1 and 1") }
可以检查集合是否包含一个或多个元素。
val r = nums.contains(4)
在这里,我们检查 nums
集合是否包含 4。该方法返回一个布尔值。
val r2 = nums.containsAll(setOf(1, -1))
这行代码检查集合是否包含两个值:1 和 -1。
The set contains 4 The set contains -1 and 1
Kotlin 可变集合
使用 mutableSetOf
,我们可以在 Kotlin 中创建可变集合。
package com.zetcode fun main() { val nums = mutableSetOf(3, 4, 5) nums.add(6) nums.add(7) nums.addAll(setOf(8, 9, 10)) println(nums) nums.remove(10) println(nums) nums.retainAll(setOf(12, 14, 16, 18)) println(nums) nums.clear() if (nums.isEmpty()) println("The set is empty") else println("The set is not epty") }
该示例创建了一个可变集合,并介绍了它的几种方法。
val nums = mutableSetOf(3, 4, 5)
我们创建一个由三个整数元素组成的可变集合。
nums.add(6) nums.add(7) nums.addAll(setOf(8, 9, 10))
add
在集合的末尾添加一个新元素。 addAll
在集合的末尾添加多个元素。
nums.clear()
clear
方法从集合中删除所有元素。
if (nums.isEmpty()) println("The set is empty") else println("The set is not epty")
使用 isEmpty
方法,我们检查集合是否为空。
[3, 4, 5, 6, 7, 8, 9, 10] [3, 4, 5, 6, 7, 8, 9] [] The set is empty
Kotlin 集合并集
并集操作返回一个包含来自两个集合的所有不同元素的集合。
package com.zetcode fun main() { val nums = setOf(1, 2, 3) val nums2 = setOf(3, 4, 5) val nums3 = nums.union(nums2) println(nums3) }
在该示例中,我们有两个整数集合。 我们使用 union
方法连接集合。
[1, 2, 3, 4, 5]
Kotlin 集合最大值
以下示例展示了如何找到集合的最大值。
package com.zetcode data class Car(var name: String, var price: Int) fun main() { val nums = setOf(11, 5, 23, 8, 1, 9, 6, 2) println(nums.max()) val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600)) val car = cars.maxBy { car -> car.price } println("The max price is ${car.price} of ${car.name}") }
该示例找到了一个整数集合和一个汽车对象集合的最大值。
val nums = setOf(11, 5, 23, 8, 1, 9, 6, 2) println(nums.max())
集合的整数的最大值很容易用 max
找到。
val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600)) val car = cars.maxBy { car -> car.price } println("The max price is ${car.price} of ${car.name}")
当我们处理对象时,我们需要指定我们查找最大值的属性。 maxBy
方法被赋予一个选择器函数,该函数选择汽车的 price
属性。
23 The max price is 18600 of Mercedes
Kotlin 集合过滤
过滤是一种操作,其中只有满足某些条件的元素才能通过。
package com.zetcode data class Car(var name: String, var price: Int) fun main() { val words = setOf("pen", "cup", "dog", "person", "cement", "coal", "spectacles") val words2 = words.filter { e -> e.length == 3 } words2.forEach { e -> print("$e ") } println() val words3 = words.filterNot { e -> e.length == 3 } words3.forEach { e -> print("$e ") } println() val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600)) val res = cars.filter { car -> car.price > 10000 } res.forEach { e -> println(e) } }
该示例演示了 Kotlin 集合上的过滤操作。
val words2 = words.filter { e -> e.length == 3 }
filter
方法将一个谓词函数作为参数。 谓词给出了元素必须满足的条件。 我们过滤掉长度等于 3 的单词。
val words3 = words.filterNot { e -> e.length == 3 }
filterNot
执行相反的操作:它允许通过不满足给定条件的元素。
val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600)) val res = cars.filter { car -> car.price > 10000 }
这些行过滤掉价格大于 10000 的汽车对象。
pen cup dog person cement coal spectacles Car(name=Toyota, price=12400) Car(name=Mercedes, price=18600)
Kotlin 集合映射
映射操作通过对集合的每个元素应用转换函数来返回一个修改后的列表。
package com.zetcode fun main() { val nums = setOf(1, 2, 3, 4, 5, 6) val nums2 = nums.map { e -> e * 2 } println(nums2) }
我们有一个整数集合。 使用 map
函数,我们将每个集合元素乘以 2。该函数返回一个新列表。
[2, 4, 6, 8, 10, 12]
Kotlin 集合规约
规约 是一种终端操作,它将集合值聚合为单个值。 reduce
方法对累加器和每个元素(从左到右)应用一个函数,将其规约为单个值。
package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, 1, 7, 6, 8, 9) val sum = nums.reduce { total, next -> total + next } println(sum) }
在该示例中,我们对一个整数集合使用规约操作。
val sum = nums.reduce { total, next -> total + next }
我们计算值的总和。total
是累加器,next
是列表中的下一个值。
45
Kotlin 集合折叠
折叠操作类似于规约。 折叠 是一种终端操作,它将集合值聚合为单个值。 区别在于折叠从一个初始值开始。
package com.zetcode fun main() { val expenses = setOf(20, 40, 80, 15, 25) val cash = 550 val res = expenses.fold(cash) {total, next -> total - next} println(res) }
我们有一个费用集合。 这些费用适用于可用的初始现金金额。
val res = expenses.fold(cash) {total, next -> total - next}
使用 fold
,我们从 cash
中推导出所有费用,并返回剩余值。
370
这是我们从可用金额中减去所有费用后拥有的金额。
Kotlin 集合分块
有时,我们在进行规约时需要处理集合的更多元素。 我们可以使用 chunked
方法将集合拆分成列表的列表。
package com.zetcode fun main() { val nums = setOf(1, 2, 3, 4, 5, 6) val res = nums.chunked(2).fold(0) { total, next -> total + next[0] * next[1] } println(res) }
在该示例中,我们有一个包含六个值的集合。 我们希望实现以下操作:1*2 + 3*4 + 5*6
。 为此,我们需要将列表拆分成两个值的块。
val res = nums.chunked(2).fold(0) { total, next -> total + next[0] * next[1] }
我们将集合拆分成两个元素的列表的列表,并对其应用折叠。 next
是一个列表,我们可以在其上使用索引操作。
44
Kotlin 集合分区
分区操作将原始集合拆分为列表对。 第一个列表包含指定谓词产生 true 的元素,而第二个列表包含谓词产生 false 的元素。
package com.zetcode fun main() { val nums = setOf(4, -5, 3, 2, -1, 7, -6, 8, 9) val (nums2, nums3) = nums.partition { e -> e < 0 } println(nums2) println(nums3) }
我们有一个整数集合。 使用 partition
方法,我们将集合拆分为两个子列表; 一个包含负值,另一个包含正值。
val (nums2, nums3) = nums.partition { e -> e < 0 }
使用解构声明,我们一次性将集合拆分为两部分。
[-5, -1, -6] [4, 3, 2, 7, 8, 9]
Kotlin 集合分组
groupBy
方法根据给定选择器函数返回的键对原始集合的元素进行分组,该选择器函数应用于每个元素。 它返回一个映射,其中每个组键都与一个对应的元素列表相关联。
package com.zetcode fun main() { val nums = setOf(1, 2, 3, 4, 5, 6, 7, 8) val res = nums.groupBy { if (it % 2 == 0) "even" else "odd" } println(res) val words = setOf("as", "pen", "cup", "doll", "my", "dog", "spectacles") val res2 = words.groupBy { it.length } println(res2) }
该示例展示了如何使用 groupBy
方法。
val nums = setOf(1, 2, 3, 4, 5, 6, 7, 8) val res = nums.groupBy { if (it % 2 == 0) "even" else "odd" } println(res)
这些行创建了一个映射,它有两个键:“even”和“odd”。 “even”指向一个偶数值列表,“odd”指向一个奇数值列表。
val words = setOf("as", "pen", "cup", "doll", "my", "dog", "spectacles") val res2 = words.groupBy { it.length }
在这里,我们创建一个带有整数键的映射。 每个键都对具有特定长度的单词进行分组。
{odd=[1, 3, 5, 7], even=[2, 4, 6, 8]} {2=[as, my], 3=[pen, cup, dog], 4=[doll], 10=[spectacles]}
Kotlin 集合任何
any
方法在至少一个元素与给定的谓词函数匹配时返回 true。
package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, -1, 7, 6, 8, 9) val r = nums.any { e -> e > 10 } if (r) println("There is a value greater than ten") else println("There is no value greater than ten") val r2 = nums.any { e -> e < 0 } if (r2) println("There is a negative value") else println("There is no negative value")
该示例展示了 any
的用法。
val r2 = nums.any { e -> e < 0 }
在这里,我们检查集合是否包含至少一个负值。 该方法返回一个布尔值。
Kotlin 集合全部
如果所有元素都满足给定的谓词函数,则 all
返回 true。
package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, -1, 7, 6, 8, 9) val nums2 = setOf(-3, -4, -2, -5, -7, -8) // testing for positive only values val r = nums.all { e -> e > 0 } if (r) println("nums set contains only positive values") else println("nums set does not contain only positive values") // testing for negative only values val r2 = nums2.all { e -> e < 0 } if (r2) println("nums2 set contains only negative values") else println("nums2 set does not contain only negative values") }
该示例展示了 all
的用法。
// testing for positive only values val r = nums.all { e -> e > 0 }
在这里,我们测试 nums
集合是否仅包含正值。
Kotlin 集合删除
使用 drop 操作,我们从集合中排除一些元素。
package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12) val nums2 = nums.drop(3) println(nums2) val nums3 = nums.sorted().dropWhile { e -> e < 0 } println(nums3) val nums4 = nums.sorted().dropLastWhile { e -> e > 0 } println(nums4) }
该示例展示了不同删除操作的用法。
val nums2 = nums.drop(3)
使用 drop
方法,我们排除前三个元素。
val nums3 = nums.sorted().dropWhile { e -> e < 0 }
使用 dropWhile
方法,我们排除满足给定谓词函数的前 n 个元素。
val nums4 = nums.sorted().dropLastWhile { e -> e > 0 }
使用 dropLastWhile
方法,我们排除满足给定谓词函数的最后 n 个元素。
[2, 1, -1, 7, 6, -8, 9, -12] [1, 2, 3, 4, 5, 6, 7, 9] [-12, -8, -1]
Kotlin 列表提取
提取操作是对 drop 操作的补充。 提取方法通过选择集合的某些元素来形成一个新列表。
package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12) val nums2 = nums.take(3) println(nums2) val nums3 = nums.sorted().take(3) println(nums3) val nums4 = nums.takeWhile { e -> e > 0 } println(nums4) val nums5 = nums.sortedDescending().takeWhile { e -> e > 0 } println(nums5) val nums6 = nums.takeIf { e -> e.contains(6) } println(nums6) }
该示例展示了各种提取方法的用法。
val nums2 = nums.take(3)
take
方法创建一个包含原始集合的前三个元素的新列表。
val nums4 = nums.takeWhile { e -> e > 0 }
takeWhile
提取满足谓词函数的前 n 个元素。
val nums6 = nums.takeIf { e -> e.contains(6) }
如果满足谓词函数中的条件,takeIf
方法将提取集合的所有元素。
[4, 5, 3] [-12, -8, -1] [4, 5, 3, 2, 1] [9, 7, 6, 5, 4, 3, 2, 1] [4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12]
来源
在本文中,我们介绍了 Kotlin 集合。
作者
列出 所有 Kotlin 教程。