想要定义 kotlin 的集合比较简单, 你想要什么集合, 就给什么集合后面添加
Of
就出来了, setOf, hashSetOf, ArrayListOf, listOf, MapOf... 所以本文不讲如何创建集合了
集合转换
把旧集合通过某种方式转化成新的集合
map 映射
map 和 mapTo: 拿出一个个元素转化成新的
转化, 把 T
转化 成 R
, 然后再存入到一个新的集合中
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C {
for (item in this)
// ******************
destination.add(transform(item))
return destination
}
destination: 是
ArrayList
类型 transform: 是转化函数
val list = (1..10).toMutableList()
val map: List<Double> = list.map {
it * 0.9
}
println(map) // [0.9, 1.8, 2.7, 3.6, 4.5, 5.4, 6.3, 7.2, 8.1, 9.0]
mapIndexed 带索引的映射
源码:
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapIndexedTo(destination: C, transform: (index: Int, T) -> R): C {
var index = 0
for (item in this)
// ******************
destination.add(transform(checkIndexOverflow(index++), item))
return destination
}
val indexed = list.mapIndexed { index, i ->
"k: $index v: $i"
}
// [k: 0 v: 1, k: 1 v: 2, k: 2 v: 3, k: 3 v: 4, k: 4 v: 5, k: 5 v: 6, k: 6 v: 7, k: 7 v: 8, k: 8 v: 9, k: 9 v: 10]
println(indexed)
val notNullList: List<Byte> = list.mapNotNull {
if (it % 2 == 0) {
null
} else {
it.toByte()
}
}
// [1, 3, 5, 7, 9]
println(notNullList)
zip 多个集合整合成一个
zip pair
源码:
public inline fun <T, R, V> Iterable<T>.zip(other: Iterable<R>, transform: (a: T, b: R) -> V): List<V> {
val first = iterator()
val second = other.iterator()
val list = ArrayList<V>(minOf(collectionSizeOrDefault(10), other.collectionSizeOrDefault(10)))
while (first.hasNext() && second.hasNext()) {
// ******************
list.add(transform(first.next(), second.next()))
}
return list
}
根据方法简单的分析, 发现 T
发起的 zip合拢
操作, 将 R
类型的集合的数据, 借助 transform
函数, 将 T
和 R
传入 转化处新的类型 V
, 而返回的接口类型是 List<V>
是 ArrayList
类型
使用方法:
val colors = listOf("red", "brown", "grey")
val animals = listOf("fox", "bear", "wolf")
println(animals zip colors) // [(fox, red), (bear, brown), (wolf, grey)]
val twoAnimal = listOf("fox", "bear")
colors.zip(twoAnimal) // [(red, fox), (brown, bear)]
上面这段代码走的是 zip(other) { t1, t2 -> t1 to t2 }
也就是说, 默认走的是 Pair
, 也就是说将 Pair
存入到 ArrayList
中
zip 自定义方法拦截映射
那么现在给个自定义方式的 zip
, public inline fun <T, R, V> Iterable<T>.zip(other: Iterable<R>, transform: (a: T, b: R) -> V): List<V>
使用方法:
val colors = listOf("red", "brown", "grey")
val animals = listOf("fox", "bear", "wolf")
println(colors.zip(animals) { color, animal ->
"^$color, $animal^"
})
unzip 解开 pair
unzip
函数: 解开 Pair
的 first
和 second
源码:
public fun <T, R> Iterable<Pair<T, R>>.unzip(): Pair<List<T>, List<R>> {
val expectedSize = collectionSizeOrDefault(10)
val listT = ArrayList<T>(expectedSize)
val listR = ArrayList<R>(expectedSize)
for (pair in this) {
// ******************
listT.add(pair.first)
listR.add(pair.second)
}
return listT to listR
}
使用方法:
val numberPairs = listOf("one" to 1, "two" to 2, "three" to 3, "four" to 4)
val pair = numberPairs.unzip()
println(pair.first) // [one, two, three, four]
println(pair.second) // [1, 2, 3, 4]
associate 关联: 把元素拆分成两个存放到新的集合中
associate
看起来就是把 T
按照某种方式分割成 k
和 v
然后存储到 Pair
中
使用方式:
val numbers = listOf("one", "two", "three", "four")
val associate = numbers.associate { Pair(it.length, it) }
println(associate) // {3=two, 5=three, 4=four}
associateTo(LinkedHashMap<K, V>(capacity), transform)
他的返回值为 LinkedHashMap
源码:
public inline fun <T, K, V, M : MutableMap<in K, in V>> Iterable<T>.associateTo(destination: M, transform: (T) -> Pair<K, V>): M {
for (element in this) {
// ******************
destination += transform(element)
}
return destination
}
看其源码果然这样
不过值得注意的是 associateTo
associateTo: 提供集合和自定义拆解方法
val numbers = listOf("one", "two", "three", "four")
val hashMap = numbers.associateTo(HashMap(10)) {
Pair(it.length, it)
}
println(hashMap) // {3=two, 5=three, 4=four}
associateBy: 借助集合元素获得 Key
val numbers = listOf("one", "two", "three", "four")
val associateBy = numbers.associateBy { it.length }
println(associateBy) // {3=two, 5=three, 4=four}
源码:
public inline fun <T, K, M : MutableMap<in K, in T>> Iterable<T>.associateByTo(destination: M, keySelector: (T) -> K): M {
for (element in this) {
// ******************
destination.put(keySelector(element), element)
}
return destination
}
associateWith: 根据集合元素的值计算出 value
val numbers = listOf("one", "two", "three", "four")
val associateWith = numbers.associateWith {
it.length
}
println(associateWith) // {one=3, two=3, three=5, four=4}
源码:
public inline fun <K, V, M : MutableMap<in K, in V>> Iterable<K>.associateWithTo(destination: M, valueSelector: (K) -> V): M {
for (element in this) {
// ******************
destination.put(element, valueSelector(element))
}
return destination
}
associateBy: 自定义 key 和 自定义 value 方式
val numbers = listOf("one", "two", "three", "four")
println(numbers.associateBy({ it.length }, { it.toUpperCase() })) // {3=TWO, 5=THREE, 4=FOUR}
源码:
public inline fun <T, K, V> Iterable<T>.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map<K, V> {
val capacity = mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16)
return associateByTo(LinkedHashMap<K, V>(capacity), keySelector, valueTransform)
}
public inline fun <T, K, V, M : MutableMap<in K, in V>> Iterable<T>.associateByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M {
for (element in this) {
// 关键代码:
destination.put(keySelector(element), valueTransform(element))
}
return destination
}
flatten: 将集合的子集合全部拿出来创建成新的集合
List<List<String>>
val numberSets = listOf(setOf(1, 2, 3), setOf(4, 5, 6), setOf(1, 2))
val flatten = numberSets.flatten()
println(flatten) // [1, 2, 3, 4, 5, 6, 1, 2]
源码:
public fun <T> Iterable<Iterable<T>>.flatten(): List<T> {
val result = ArrayList<T>()
for (element in this) {
result.addAll(element)
}
return result
}
flatMap: 将子List拿出来addAll到一个新的集合中
val containers = listOf(
listOf("one", "two", "three"),
listOf("four", "five", "six"),
listOf("seven", "eight")
)
val flatMap = containers.flatMap {
it
}
println(flatMap) // [one, two, three, four, five, six, seven, eight]
源码:
public inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R> {
return flatMapTo(ArrayList<R>(), transform)
}
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapTo(destination: C, transform: (T) -> Iterable<R>): C {
for (element in this) {
val list = transform(element)
destination.addAll(list)
}
return destination
}
其他的函数就不演示了, 和上面的 Map 和 associate 差不多
joinToString: 字符串打印方式自定义
val numbers = listOf("one", "two", "three", "four")
val joinToString =
numbers.joinToString(separator = "^", prefix = "#", postfix = "#", transform = { it.toUpperCase() })
println(joinToString) // #ONE^TWO^THREE^FOUR#
源码:
public fun <T> Iterable<T>.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String {
return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString()
}
public fun <T, A : Appendable> Iterable<T>.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A {
// buffer ==> StringBuilder
buffer.append(prefix)
var count = 0
for (element in this) {
if (++count > 1) buffer.append(separator)
if (limit < 0 || count <= limit) {
buffer.appendElement(element, transform)
} else break
}
// 如果 count 大于 limit 的话, 直接加入阶段字符串
if (limit >= 0 && count > limit) buffer.append(truncated)
// 加入结尾标志
buffer.append(postfix)
return buffer
}
过滤
根据接受的lambda返回的 true or false 来产生新的集合
filter: 分析每个元素是否满足某种条件
从遍历元素, 然后判断元素是否满足某种条件返回 boolean 类型
val numbers = listOf("one", "two", "three", "four")
println(numbers.filter { it.length > 3 }) // [three, four]
过滤 map 的条件是否满足
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11)
println(numbersMap.filter { (key, value) ->
key.endsWith("1") && value > 3
}) // {key11=11}
filterIsInstance: 根据类型过滤
val numbers = listOf(1, "two", 3.0, "four")
val list = numbers.filterIsInstance<Double>()
println(list)
源码:
partition: 根据某种条件分割一个集合为多个集合
val numbers = listOf("one", "two", "three", "four")
val partition = numbers.partition { it.length > 3 }
println(partition.first)
println(partition.second)
源码:
public inline fun <T> Iterable<T>.partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>> {
val first = ArrayList<T>()
val second = ArrayList<T>()
for (element in this) {
// 核心代码在这里
if (predicate(element)) {
first.add(element)
} else {
second.add(element)
}
}
return Pair(first, second)
}
any all none 验证集合是否满足某个条件
val numbers = listOf("one", "two", "three", "four")
println(numbers.any { it.startsWith("t") }) // true 只要有一个元素满足条件就返回true
println(numbers.none { it.length < 2 }) // 如果有一个条件满足就返回 false , 否则返回 true
println(numbers.all { it.length == 3 }) // 所有都要满足条件才会返回 true, 否则返回false
groupby 分组
可以根据集合中的元素计算出分组的key
, 然后存放满足该key
的 List
val numbers = listOf("one", "two", "three", "four", "five")
val groupBy = numbers.groupBy { it.length }.toSortedMap { o1, o2 -> o1 - o2 }
println(groupBy) // {3=[one, two], 4=[four, five], 5=[three]}
val groupBy1 = numbers.groupBy({ it.length }) {
it.toUpperCase()
}
println(groupBy1) // {3=[ONE, TWO], 5=[THREE], 4=[FOUR, FIVE]}
grouping: 根据 value 获得 key
val numbers = listOf("one", "two", "three", "four", "five", "six")
val grouping = numbers.groupingBy { it.length }
println(grouping.keyOf("six")) // 3
println(grouping.keyOf("three")) // 5
取集合的⼀部分
Slice: 取一部分集合的元素(索引从0开始)
val numbers = listOf("one", "two", "three", "four", "five", "six")
val slice = numbers.slice(0..3) // [one, two, three, four]
println(slice)
val slice1 = numbers.slice(3..5) // [four, five, six]
println(slice1)
take: 从头开始取前n个元素
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.take(1)) // [one]
println(numbers.take(2)) // [one, two]
println(numbers.take(6)) // [one, two, three, four, five, six]
drop: 从头开始删除前n个元素
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.drop(1)) // 从前面开始删除前1个
println(numbers.drop(2)) // 从前面开始删除前2个
Chunked: 分块
/*
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13]]
[3, 12, 21, 30, 25]
*/
val numbers = (0..13).toList()
val chunked: List<List<Int>> = numbers.chunked(3)
println(chunked) // [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13]]
val chunked1 = numbers.chunked(3) { list ->
list.sum()
}
println(chunked1) // [3, 12, 21, 30, 25]
Windowed: 步长自定义的分块函数
val numbers = listOf("one", "two", "three", "four", "five")
val windowed = numbers.windowed(3, step = 1, partialWindows = false) { list ->
list.map { it.toUpperCase() }
}
println(windowed) // [[ONE, TWO, THREE], [TWO, THREE, FOUR], [THREE, FOUR, FIVE]]
subList: 从集合里找一个子集返回
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.javaClass) // class java.util.Arrays$ArrayList
val subList = numbers.subList(0, 2)
println(subList.javaClass) // class java.util.AbstractList$RandomAccessSubList
println(subList) // [one, two]
取单个元素
elementAt: 按位置取
val numbers = linkedSetOf("one", "two", "three", "four", "five")
println(numbers.elementAt(0)) // one
println(numbers.elementAt(3)) // four
first 和 last
val numbers = linkedSetOf("one", "two", "three", "four", "five")
println(numbers.first()) // one
println(numbers.last()) // five
first and last: 按条件取一个
val numbers = linkedSetOf("one", "two", "three", "four", "five")
println(numbers.first { it.length == 4 }) // four
find: 根据条件取一个
val numbers = listOf(1, 2, 3, 4)
println(numbers.find { it > 3 }) // 4
random: 随机取一个
val number = listOf(1, 2, 3, 4)
println(number.random()) // 2
检测存在与否
val numbers = listOf(1, 2, 3, 4)
println(numbers.contains(2))
println(numbers.containsAll(listOf(3, 4)))
还有
isEmpty
和isNotEmpty
就不做测试了
集合排序
Comparable
主要给类实现用
class Program(val version: Int) : Comparable<Int> {
override fun compareTo(other: Int): Int = this.version - other
}
fun main() {
val program = Program(13)
println(program > 10)
println(program > 13)
println(program < 20)
}
还可以不使用Comparable
class Program(val version: Int) {
operator fun compareTo(program2: Program): Int {
return this.version - program2.version
}
operator fun compareTo(i: Int): Int {
return this.version - i
}
}
fun main() {
val program1 = Program(13)
val program2 = Program(14)
println(program1 > program2)
program1 > 14
}
倒序和随机顺序
val numbers = listOf("one", "two", "three", "four")
println(numbers) // [one, two, three, four]
println(numbers.reversed()) // [four, three, two, one]
println(numbers.asReversed()) // [four, three, two, one]
println(numbers.shuffled()) // [four, one, three, two]
集合聚合操作
val numbers = listOf(6, 42, 10, 4)
println("Count: ${numbers.count()}") // Count: 4
println("Max: ${numbers.maxOrNull()}") // Max: 42
println("Min: ${numbers.minOrNull()}") // Min: 4
println("Average: ${numbers.average()}") // Average: 15.5
println("Sum: ${numbers.sum()}") // Sum: 62
fold: 有初始化值R和集合T的某种组合的结果R返回回去
reduce: 把集合的第一个值当作S, 然后和集合的每个元素T做某种操作最后返回 S
set相关操作
联合 union 、 交集 intersect 和 差集 subtract
val numbers = setOf("one", "two", "three")
// 合并两个集合
println(numbers union setOf("four", "five")) // [one, two, three, four, five]
// 找交集
println(numbers intersect setOf("one")) // [one]
// 差集
println(numbers subtract setOf("one", "three")) // [two]