阅读 95

kotlin的集合操作

想要定义 kotlin 的集合比较简单, 你想要什么集合, 就给什么集合后面添加 Of 就出来了, setOf, hashSetOf, ArrayListOf, listOf, MapOf... 所以本文不讲如何创建集合了

集合转换

把旧集合通过某种方式转化成新的集合

map 映射

map 和 mapTo: 拿出一个个元素转化成新的

image.png

转化, 把 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 带索引的映射

image.png

源码:

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 函数, 将 TR 传入 转化处新的类型 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 函数: 解开 Pairfirstsecond

源码:

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

image.png

看起来就是把 T 按照某种方式分割成 kv 然后存储到 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

image.png

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 方式

image.png

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到一个新的集合中

image.png

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 差不多

image.png

joinToString: 字符串打印方式自定义

image.png

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: 分析每个元素是否满足某种条件

image.png

从遍历元素, 然后判断元素是否满足某种条件返回 boolean 类型

val numbers = listOf("one", "two", "three", "four") println(numbers.filter { it.length > 3 }) // [three, four] 复制代码

过滤 map 的条件是否满足

image.png

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) 复制代码

源码:

image.png

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 分组

image.png

可以根据集合中的元素计算出分组的key, 然后存放满足该keyList

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))) 复制代码

还有 isEmptyisNotEmpty 就不做测试了

集合排序

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返回回去

image.png

reduce: 把集合的第一个值当作S, 然后和集合的每个元素T做某种操作最后返回 S

image.png

set相关操作

联合 union 和 交集 intersect

val numbers = setOf("one", "two", "three") // 合并两个集合 println(numbers union setOf("four", "five")) // 找交集 println(numbers intersect setOf("one"))


作者:bangiao
链接:https://juejin.cn/post/7023015148382568461

文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐