集合
十一、取集合的一部分
-
Slice
slice()
返回具有给定索引的集合元素列表。
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.slice(1..3)) // [two, three, four]
println(numbers.slice(0..4 step 2)) // [one, three, five]
println(numbers.slice(listOf(3, 5, 0))) // [four, six, one]
-
Take 与 Drop
take()
从头获取指定数量的元素,takeLast()
从尾开始获取。
drop()
从头去除指定数量的元素,dropLast()
从尾开始去除。
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.take(3)) // [one, two, three]
println(numbers.takeLast(3)) // [four, five, six]
println(numbers.drop(4)) // [five, six]
println(numbers.dropLast(5)) // [one]
takeWhile()
:不停获取元素直到排除与谓词匹配的首个元素。
takeLastWhile()
:从集合末尾获取与谓词匹配的元素区间。
dropWhile()
:返回从首个与谓词不匹配的元素到末尾元素。
dropLastWhile()
:返回从开头到最后一个与谓词不匹配的元素。
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.takeWhile { !it.startsWith('f') })
// [one, two, three]
println(numbers.takeLastWhile { it != "three" })
// [four, five, six]
println(numbers.dropWhile { it.length == 3 })
// [three, four, five, six]
println(numbers.dropLastWhile { it.contains('i') })
// [one, two, three, four]
-
Chunked
chunked()
:将集合分解为给定大小的块。参数:块的大小;返回值:一个List
其中包含给定大小的List
。
val numbers = (0..13).toList()
println(numbers.chunked(3))
// [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13]]
println(numbers.chunked(3) { it.sum() })
// [3, 12, 21, 30, 25]
-
Windowed
windowed()
:检索给定大小的集合元素中所有可能区间。
可选参数:
— step
两个相邻窗口的第一个元素之间的距离,默认为1。
— partialWindows
是否包含小于给定大小的窗口,默认为false。
val numbers = (1..10).toList()
println(numbers.windowed(3, step = 2, partialWindows = true))
// [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]]
println(numbers.windowed(3, step = 2))
// [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9]]
println(numbers.windowed(3, step = 2) { it.sum() })
// [6, 12, 18, 24]
构建两个元素的窗口:zipWithNext()
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.zipWithNext())
// [(one, two), (two, three), (three, four), (four, five)]
println(numbers.zipWithNext { s1, s2 -> s1.length > s2.length})
// [false, false, true, false]
十二、取单个元素
-
按位置取
elementAt()
用一个整数作为参数。
val numbers = linkedSetOf("one", "two", "three", "four", "five")
println(numbers.elementAt(3)) // four
val numbersSortedSet = sortedSetOf("one", "two", "three", "four")
println(numbersSortedSet.elementAt(0)) // four
List
可以使用get()
和[]
。
检索第一个和最后一个元素:first()
和last()
。
避免越界,使用elementAt()
的安全变体:
— elementAtOrNull()
:指定位置超出集合范围时,返回null
。
— elementAtOrElse()
:接受一个lambda表达式。使用一个越界位置调用时,返回对给定值调用lambda表达式的结果。
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.elementAtOrNull(5)) // null
println(numbers.elementAtOrElse(5) { i -> "numbers[$i] is undefined"}) // numbers[5] is undefined
-
按条件取
带有谓词的first()
:得到使调用谓词为true
的第一个元素。
带有谓词的last()
:得到使调用谓词为true
的最后一个元素。
安全调用:firstOrNull()
和lastOrNull()
。
find()
可以代替firstOrNull()
,findLast()
可以代替lastOrNull()
。
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.first { it.length > 3 }) // three
println(numbers.last { it.startsWith("f") }) // five
println(numbers.firstOrNull { it.length > 5 }) // null
println(numbers.lastOrNull { it.length < 4 }) // six
println(numbers.find { it.length > 5 }) // null
println(numbers.findLast { it.length < 4 }) // six
-
随机取
val numbers = listOf(1, 2, 3, 4)
println(numbers.random())
-
检测存在与否
检测某个元素:contains()
和in
。
检测多个元素:containsAll()
。
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.contains("four")) // true
println("zero" in numbers) // false
println(numbers.containsAll(listOf("four", "two"))) // true
println(numbers.containsAll(listOf("one", "zero"))) // false
检查集合是否为空或非空:isEmpty()
和isNotEmpty()
。
十三、排序
大多数内置类型可比较:
— 数值类型:使用传统的数值顺序。
— Char
和String
:使用字典顺序。
如果需要为自定义类型定义一个自然顺序,可以继承Comparable
并实现compareTo()
函数。
compareTo()
必须将另一个具有相同类型的对象作为参数并返回一个整数值:
— 正值表明接收者对象更大;
— 负值说明参数更大;
— 0 说明对象相等。
如果需要为类型自定义顺序,可以创建一个Comparator
,Comparator
包含compare()
函数。
val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length }
println(listOf("aaa", "bb", "c").sortedWith(lengthComparator))
// [c, bb, aaa]
可以使用compareBy()
函数定义一个Comparator
,它接受一个lambda表达式。
println(listOf("aaa", "bb", "c").sortedWith(compareBy { it.length }))
// [c, bb, aaa]
-
自然顺序
sorted()
:升序。
sortedDescending()
:降序。
val numbers = listOf("one", "two", "three", "four")
println(numbers.sorted()) // [four, one, three, two]
println(numbers.sortedDescending()) // [two, three, one, four]
-
自定义顺序
sortedBy()
:升序。
sortedByDescending()
:降序。
val numbers = listOf("one", "two", "three", "four")
println(numbers.sortedBy { it.length }) // [one, two, four, three]
println(numbers.sortedByDescending { it.last() }) // [four, two, one, three]
-
倒序
reversed()
返回带有元素副本的新集合。
val numbers = listOf("one", "two", "three", "four")
println(numbers.reversed()) // [four, three, two, one]
println(numbers) // [one, two, three, four]
asReversed()
返回相同集合实例的一个反向视图。
如果原始列表是可变的,所有对原始列表的更改都会反映在反向视图中,同样对于反向视图的更改也会反映在原始列表中。
val numbers = mutableListOf("two", "three")
val reversedNumbers = numbers.asReversed()
println(numbers) // [two, three]
println(reversedNumbers) // [three, two]
numbers.add("four")
println(numbers) // [two, three, four]
println(reversedNumbers) // [four, three, two]
reversedNumbers.add("one")
println(numbers) // [one, two, three, four]
println(reversedNumbers) // [four, three, two, one]
-
随机顺序
shuffled()
函数返回以随机顺序排序的新List
。
val numbers = listOf("one", "two", "three", "four")
println(numbers.shuffled())
十四、聚合
-
常用聚合操作
— min()
和 max()
:最小元素和最大元素。
— average()
:所有元素的平均值。
— sum()
:所有元素的总和。
— count()
:元素的数量。
通过选择器函数或自定义Comparator
检索最大和最小元素:
— maxBy()
/ minBy()
:接受一个选择器函数。
— maxWith()
/ minWith()
:接受一个Comparator
对象。
val numbers = listOf(5, 42, 10, 4)
val min3Remainder = numbers.minBy { it % 3 }
println(min3Remainder) // 42
val strings = listOf("one", "two", "three", "four")
val longestString = strings.maxWith(compareBy { it.length })
println(longestString) // three
-
高级求和函数
— sumBy()
— sumByDouble()
val numbers = listOf(5, 42, 10, 4)
println(numbers.sumBy { it * 2 }) // 122
println(numbers.sumByDouble { it.toDouble() / 2 }) // 30.5
-
Fold 与 reduce
依次将所提供的操作应用于集合元素并返回累积的结果。
fold()
:接受一个初始值并用作第一步的累积值。
reduce()
:将第一个和第二个元素作为第一步的操作参数。
第一个参数为累积值,第二个参数为元素。
val numbers = listOf(5, 2, 10, 4)
val sum = numbers.reduce { sum, element -> sum + element }
println(sum) // 21
val sumDoubled = numbers.fold(0) { sum, element -> sum + element * 2 }
println(sumDoubled) // 42
val sumDoubledReduce = numbers.reduce { sum, element -> sum + element * 2 } //第一个元素在结果中没有加倍
println(sumDoubledReduce) // 37 = 5 + 4 + 20 + 8
foldRight()
与redeceRight()
:从右至左将函数应用于元素。第一个参数为元素,第二个参数为累积值。
val numbers = listOf(5, 2, 10, 4)
val sumDoubledRight = numbers.foldRight(0) { element, sum -> sum + element * 2 }
println(sumDoubledRight) // 42
将元素索引作为参数:foldIndexed()
和reduceIndexed()
。
从右至左:foldRightIndexed
和reduceRightIndexed()
。
val numbers = listOf(5, 2, 10, 4)
val sumEven = numbers.foldIndexed(0) { idx, sum, element -> if (idx % 2 == 0) sum + element else sum }
println(sumEven) // 15 = 5 + 10
val sumEvenRight = numbers.foldRightIndexed(0) { idx, element, sum -> if (idx % 2 == 0) sum + element else sum }
println(sumEvenRight) // 15 = 10 + 5
十五、集合写操作
-
添加元素
添加单个元素:使用add()
函数。
一个参数:要添加的元素。
两个参数:第一参数表示添加的位置,第二参数表示要添加的元素。
添加参数集合的每个元素:使用addAll()
函数。
单个参数:要添加的集合。
两个参数:第一参数表示添加的位置,第二参数表示要添加的集合。
val numbers = mutableListOf(2, 5)
numbers.add(6)
numbers.add(0, 1)
println(numbers) // [1, 2, 5, 6]
numbers.addAll(arrayOf(7, 8))
numbers.addAll(2, setOf(3, 4))
println(numbers) // [1, 2, 3, 4, 5, 6, 7, 8]
plusAssign(+=)
运算符:
val numbers = mutableListOf("one", "two")
numbers += "three"
println(numbers) // [one, two, three]
numbers += listOf("four", "five")
println(numbers) // [one, two, three, four, five]
-
删除元素
移除一个元素:remove()
函数。
val numbers = mutableListOf(1, 2, 3, 4, 3)
numbers.remove(3) // [1, 2, 4, 3] 删除第一个匹配的元素
println(numbers)
numbers.remove(5) // 没有删除任何元素
println(numbers)
移除多个元素:
removeAll()
:移除参数集合中存在的所有元素。可以用谓词调用。
retainAll()
:移除出参数集合中的元素之外的所有元素。可以用谓词调用。
clear()
:移除所有元素并将集合置空。
val numbers = mutableListOf(1, 2, 3, 4)
numbers.retainAll { it >= 3 }
println(numbers) // [3, 4]
numbers.clear()
println(numbers) // []
val numbersSet = mutableSetOf("one", "two", "three", "four")
numbersSet.removeAll(setOf("one", "two", "five"))
println(numbersSet) // [three, four]
minusAssign(-=)
运算符:
右边是单个元素时,-=
会移除它的第一个匹配项。 如果它是一个集合,那么它的所有元素的每次出现都会删除。 第二个操作数可以包含集合中不存在的元素。
val numbers = mutableListOf("one", "two", "three", "four", "three", "five", "five")
numbers -= "three"
println(numbers) // [one, two, four, three, five, five]
numbers -= listOf("four", "five", "six")
println(numbers) // [one, two, three]
十六、List相关操作
-
按索引取元素
get()
函数或简写语法[index]
。
getOrElse()
:提供用于计算默认值的函数,如果集合中不存在索引则返回默认值。
getOrNull()
:返回null
作为默认值。
val numbers = listOf(1, 2, 3, 4)
println(numbers.get(0)) // 1
println(numbers[0]) // 1
// println(numbers.get(5)) // Exception
println(numbers.getOrNull(5)) // null
println(numbers.getOrElse(5) { it }) // 5
-
取列表的一部分
subList()
:左闭右开。
val numbers = (0..10).toList()
println(numbers.subList(3, 6)) // [3, 4, 5]
-
查找元素位置
- 线性查找
indexOf()
和lastIndexOf()
val numbers = listOf(1, 2, 3, 4, 2, 5)
println(numbers.indexOf(2)) // 1
println(numbers.indexOf(6)) // -1
println(numbers.lastIndexOf(2)) // 4
println(numbers.lastIndexOf(6)) //-1
接受谓词的函数:indexOfFirst()
和indexOfLast()
val numbers = listOf(1, 2, 3, 4)
println(numbers.indexOfFirst { it > 2 }) // 2
println(numbers.indexOfFirst { it == 5 }) // -1
println(numbers.indexOfLast { it % 2 == 1 }) // 2
println(numbers.indexOfLast { it > 5}) // -1
- 二分查找
搜索一排宿列表中的元素,并将该值作为参数传递。如果存在则返回索引;否则返回-insertionPoint - 1
,其中insertPoint
为应插入此元素的索引。
还可以指定搜索区间:左闭右开。
val numbers = listOf(0, 2, 3, 4)
println(numbers.binarySearch(2)) // 1
println(numbers.binarySearch(1)) // -2
println(numbers.binarySearch(2, 0, 2)) // 1
println(numbers.binarySearch(1, 0, 2)) // -3
如果列表不是COmparable
,应提供一个Comparator
,该列表必须根据此Comparator
以升序排序。
data class Product(val name: String, val price: Double)
fun main() {
val productList = listOf(
Product("WebStorm", 49.0),
Product("AppCode", 99.0),
Product("DotTrace", 129.0),
Product("ReSharper", 149.0))
println(productList.binarySearch(Product("AppCode", 99.0),
compareBy { it.price }.thenBy { it.name }))
// 1
}
使用比较函数无需提供明确的搜索值。它需要使用一个比较函数将元素映射到Int
值,并搜索函数返回0的元素。该列表必须根据提供的函数以升序排序。
import kotlin.math.sign
data class Product(val name: String, val price: Double)
fun priceComparison(product: Product, price: Double) = sign(product.price - price).toInt()
fun main() {
val productList = listOf(
Product("WebStorm", 49.0),
Product("AppCode", 99.0),
Product("DotTrace", 129.0),
Product("ReSharper", 149.0))
println(productList.binarySearch { priceComparison(it, 99.0) })
// 1
}
-
写操作
- 添加:
val numbers = mutableListOf("one")
numbers.add("four")
println(numbers) // [one, four]
numbers.addAll(listOf("five", "seven" ))
println(numbers) // [one, four, five, seven]
numbers.add(3, "six")
println(numbers) // [one, four, five, six, seven]
numbers.addAll(1, listOf("two", "three"))
println(numbers) // [one, two, three, four, five, six, seven]
- 更新:
set()
和[index]
:在指定位置替换元素。
val numbers = mutableListOf("one", "five", "four")
numbers[1] = "two"
numbers.set(2, "three")
println(numbers)
fill()
:将所有集合元素替换为指定值。
val numbers = mutableListOf(1, 2, 3, 4)
numbers.fill(5)
println(numbers)
- 删除:
removeAt()
:删除指定位置的元素。
val numbers = mutableListOf(1, 2, 3, 4)
numbers.removeAt(3)
println(numbers) // [1, 2, 3]
- 排序:
asReversed()
在可变列表上调用会返回另一个可变列表,该列表是原始列表的反向视图。在该视图中的更改将反映在原始列表中。
val numbers = mutableListOf("one", "two", "three", "four")
numbers.sort()
println("Sort into ascending: $numbers")
// [four, one, three, two]
numbers.sortDescending()
println("Sort into descending: $numbers")
// [two, three, one, four]
numbers.sortBy { it.length }
println("Sort into ascending by length: $numbers")
// [two, one, four, three]
numbers.sortByDescending { it.last() }
println("Sort into descending by the last letter: $numbers")
// [four, two, one, three]
numbers.sortWith(compareBy { it.length }.thenBy { it })
println("Sort by Comparator: $numbers")
// [one, two, four, three]
numbers.shuffle()
println("Shuffle: $numbers")
// [one, four, two, three] (随机)
numbers.reverse()
println("Reverse: $numbers")
// [three, two, four, one]
val reversedNumbers = numbers.asReversed()
println("ReversedNumbers: $reversedNumbers")
// [one, four, two, three]
reversedNumbers.add("five")
println("ReversedNumbers: $reversedNumbers")
// [one, four, two, three, five]
println("numbers: $numbers")
// [five, three, two, four, one]
十七、Set相关操作
union()
:并集
intersect()
:交集
subtract()
:差集
val numbers = setOf("one", "two", "three")
println(numbers union setOf("four", "five")) // [one, two, three, four, five]
println(setOf("four", "five") union numbers) // [four, five, one, two, three]
println(numbers intersect setOf("two", "one")) // [one, two]
println(setOf("two", "one") intersect numbers) // [two, one]
println(numbers subtract setOf("three", "four")) // [one, two]
println(numbers subtract setOf("three")) // [one, two]
List
也支持Set
操作,但是结果仍然是Set
,因此删除所有重复的元素。
val numbers = listOf("one", "two", "three", "three")
println(numbers union setOf("four", "five")) // [one, two, three, four, five]
println(setOf("four", "five") union numbers) // [four, five, one, two, three]
println(numbers intersect setOf("two", "one")) // [one, two]
println(setOf("two", "one") intersect numbers) // [two, one]
println(numbers subtract setOf("three", "four")) // [one, two]
println(numbers subtract setOf("three")) // [one, two]
十八、Map相关操作
-
取键与值
get()
:采用键作为参数。简写为[key]
语法。找不到指定的键返回null
。
getValue()
:找不到指定的键则抛出异常。
getOrElse()
:找不到指定的键返回lambda表达式的值。
getOrDefault()
:找不到指定的键返回指定的默认值。
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap.get("one")) // 1
println(numbersMap["one"]) // 1
println(numbersMap.getOrElse("four", defaultValue = { 4 })) // 4
println(numbersMap.getOrDefault("four", 4)) // 4
println(numbersMap.get("four")) // null
println(numbersMap["four"]) // null
println(numbersMap.getValue("four")) // Exception
获取所有键和所有值:keys
和values
属性。
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap.keys) // [one, two, three]
println(numbersMap.values) // [1, 2, 3]
-
过滤
filter()
:参数为Pair()
对象。
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key11" to 11)
val filteredMap = numbersMap.filter { (key, value) -> key.endsWith("1") && value > 10}
println(filteredMap) // {key11=11}
filterKeys()
:按键过滤。
filterValues()
:按值过滤。
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key11" to 11)
val filteredKeysMap = numbersMap.filterKeys { it.endsWith("1") }
val filteredValuesMap = numbersMap.filterValues { it < 10 }
println(filteredKeysMap) // {key1=1, key11=11}
println(filteredValuesMap) // {key1=1, key2=2}
-
加减操作
plus
:当右操作数中有左操作Map
中已存在的键时,使用右侧的值。
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap + Pair("four", 4))
println(numbersMap + Pair("one", 10))
println(numbersMap + mapOf("five" to 5, "one" to 11))
minus
:右操作数可以是单个键或键的集合。
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap - "one") // {two=2, three=3}
println(numbersMap - listOf("two", "four")) // {one=1, three=3}
-
写操作
- 添加与更新条目
put()
:第一参数为键,第二参数为值。简写为[key]
语法。
putAll()
:参数可以是Map
或一组Pair
:Iterable
、Sequence
、Array
。
如果给定键已存在,则旧值被覆盖。
val numbersMap = mutableMapOf("one" to 1)
numbersMap.put("two", 22)
numbersMap["three"] = 33
numbersMap.putAll(setOf("four" to 44, "five" to 55))
println(numbersMap) // {one=1, two=22, three=33, four=44, five=55}
numbersMap.put("two", 2)
numbersMap["three"] = 3
numbersMap.putAll(setOf("four" to 4, "five" to 5))
println(numbersMap) // {one=1, two=2, three=3, four=4, five=5}
+=
操作符:
val numbersMap = mutableMapOf("one" to 1, "two" to 2)
numbersMap += mapOf("three" to 3, "four" to 4)
println(numbersMap) // {one=1, two=2, three=3, four=4}
- 删除条目
remove()
:参数可以是键或整个键值对,如果同时制定键和值,仅当键值都匹配时,才会删除。
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3)
numbersMap.remove("one")
numbersMap.remove("two", 2)
numbersMap.remove("three", 4)
println(numbersMap)
通过键或值删除条目:在Map
的.keys
或.value
中调用remove()
。在.values
中调用时, remove()
仅删除给定值匹配到的的第一个条目。
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3, "threeAgain" to 3)
numbersMap.keys.remove("one")
println(numbersMap) // {two=2, three=3, threeAgain=3}
numbersMap.values.remove(3)
println(numbersMap) // {two=2, threeAgain=3}
-=
操作符:
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3)
numbersMap -= "two"
numbersMap -= "five"
println(numbersMap) // {one=1, three=3}