Kotlin 集合操作符

集合操作符

  • 集合操作符 一 (首字母 a - f)

这篇文章介绍下 Kotlin 集合中的操作符,本文中 Kotlin 所用版本是 1.8.10

all

判断集合中的所有元素是否满足需求,返回值为 Boolean

例如我们需要判断字符串的长度是否大于4

val songs = listOf("一路向北", "搁浅", "最长的电影")
songs.all { it.length >= 4 } // false

源码实现

// 继承Collection并且为空集合,直接返回为true
// 假如有一个元素不满足条件,直接返回false
public inline fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean {
    if (this is Collection && isEmpty()) return true
    for (element in this) if (!predicate(element)) return false
    return true
}

any

判断集合中是否存在满足条件的元素,返回值为 Boolean

例如我们需要判断是否存在185cm 8块腹肌以上的小哥哥

val heights = listOf(188, 165, 175)
heights.any { it >= 185 } // true

源码实现

// 继承Collection并且为空集合,直接返回为false
// 假如有一个元素满足条件,直接返回true
public inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean {
    if (this is Collection && isEmpty()) return false
    for (element in this) if (predicate(element)) return true
    return false
}

contains

集合是否包含某个元素,返回为 Boolean

例如判断班上是否有个名叫蔡徐坤的童鞋

val nickname = listOf("蔡徐坤", "坤蔡徐", "蔡坤徐", "蔡徐坤")
println(nickname.contains("蔡徐坤"))  // true

源码实现

// 继承Collection,则通过Collection.contains()判断是否包含
// 负责通过indexOf判断
public operator fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.contains(element: T): Boolean {
    if (this is Collection)
        return contains(element)
    return indexOf(element) >= 0
}

count

返回集合中的长度

val nickname = listOf("蔡徐坤", "坤蔡徐", "蔡坤徐", "蔡徐坤")
println(nickname.count()) // 4

源码实现

// 继承Collection,返回size
// 使用for循环计数
public fun <T> Iterable<T>.count(): Int {
    if (this is Collection) return size
    var count = 0
    for (element in this) checkCountOverflow(++count)
    return count
}

根据条件返回集合中满足条件的所有元素长度

例如我们需要统计班上的童鞋身高达到 185cm 的人数

val height = listOf(188, 165, 175, 185)
println(height.count { it >= 185 } ) // 2

源码实现

// 集合并且长度为0,返回0
// 满足predicate,计数累加并返回
public inline fun <T> Iterable<T>.count(predicate: (T) -> Boolean): Int {
    if (this is Collection && isEmpty()) return 0
    var count = 0
    for (element in this) if (predicate(element)) checkCountOverflow(++count)
    return count
}

distinct

过滤掉集合中相同的元素,返回一个新集合,实际是通过 HashSet 保证元素不重复

例如过滤掉重名的同学

val nickname = listOf("蔡徐坤", "坤蔡徐", "蔡坤徐", "蔡徐坤")
nickname.distinct()  // [蔡徐坤, 坤蔡徐, 蔡坤徐]

源码实现

public fun <T> Iterable<T>.distinct(): List<T> {
    return this.toMutableSet().toList()
}

distinctBy

根据条件过滤掉集合中的元素,返回一个新集合,实际是通过 HashSet 保证元素不重复

例如根据名字长度过滤

val nickname = listOf("蔡徐坤", "蔡", "坤蔡徐", "蔡坤徐", "蔡徐")
nickname.distinctBy { it.length } // [蔡徐坤, 蔡, 蔡徐]

如果想实现 distinct 过滤相同的元素,这样写即可(那还不如直接用 distinct 呢)

nickname.distinctBy { it }

源码实现

// HashSet可以添加元素,就将元素添加到list
public inline fun <T, K> Iterable<T>.distinctBy(selector: (T) -> K): List<T> {
    val set = HashSet<K>()
    val list = ArrayList<T>()
    for (e in this) {
        val key = selector(e)
        if (set.add(key))
            list.add(e)
    }
    return list
}

drop

过滤集合中前 n 个 元素,返回新的集合。n < 0 时抛出 IllegalArgumentException 异常,n = 0 时返回原集合,n >= 集合长度时返回空集合

val heroName = listOf("蛮三刀", "托儿索", "儿童劫", "提款姬", "菊花信")
println(heroName.drop(0)) // [蛮三刀, 托儿索, 儿童劫, 提款姬, 菊花信]
println(heroName.drop(2)) // [儿童劫, 提款姬, 菊花信]
println(heroName.drop(6)) // []

源码实现

// n = 0,返回toList()
// 继承Collection时,获取去除后的集合长度,长度为0返回emptyList,长度为1返回最后一个元素,否则通过ArrayList添加元素
public fun <T> Iterable<T>.drop(n: Int): List<T> {
    require(n >= 0) { "Requested element count $n is less than zero." }
    if (n == 0) return toList()
    val list: ArrayList<T>
    if (this is Collection<*>) {
        val resultSize = size - n
        if (resultSize <= 0)
            return emptyList()
        if (resultSize == 1)
            return listOf(last())
        list = ArrayList<T>(resultSize)
        if (this is List<T>) {
            if (this is RandomAccess) {
                for (index in n until size)
                    list.add(this[index])
            } else {
                for (item in listIterator(n))
                    list.add(item)
            }
            return list
        }
    }
    else {
        list = ArrayList<T>()
    }
    var count = 0
    for (item in this) {
        if (count >= n) list.add(item) else ++count
    }
    return list.optimizeReadOnlyList()
}

dropLast

drop 刚好相反,dropLast 是从尾部过滤。n < 0 时抛出 IllegalArgumentException 异常,n = 0 时返回原集合,n >= 集合长度时返回空集合

val heroName = listOf("蛮三刀", "托儿索", "儿童劫", "提款姬", "菊花信")
println(heroName.dropLast(0))  // [蛮三刀, 托儿索, 儿童劫, 提款姬, 菊花信]
println(heroName.dropLast(2))  // [蛮三刀, 托儿索, 儿童劫]
println(heroName.dropLast(6))  // []

源码实现

// 通过take()获取结果,take后面再说
public fun <T> List<T>.dropLast(n: Int): List<T> {
    require(n >= 0) { "Requested element count $n is less than zero." }
    return take((size - n).coerceAtLeast(0))
}

dropLastWhile

根据条件从尾部开始过滤元素,直到某个元素不满足条件时返回

例如现在求职者太多了,公司需要秉承先来后到并且职位更适合高个子的原则,舍弃掉末尾的求职者

val heights = listOf(185, 158, 177, 190, 169, 170, 168)
println(heights.dropLastWhile { it <= 175 }) // [185, 158, 177, 190]
println(heights.dropLastWhile { it < 170 })  // [185, 158, 177, 190, 169, 170]

源码实现

// 通过迭代器从后到前迭代,直到不满足条件时通过take截取
public inline fun <T> List<T>.dropLastWhile(predicate: (T) -> Boolean): List<T> {
    if (!isEmpty()) {
        val iterator = listIterator(size)
        while (iterator.hasPrevious()) {
            if (!predicate(iterator.previous())) {
                return take(iterator.nextIndex() + 1)
            }
        }
    }
    return emptyList()
}

dropWhile

根据条件从头部开始过滤元素,跟 dropLastWhile 刚好相反,直到某个元素不满足条件时返回剩余集合

还是上面的例子,不过我们调整下筛选的规则,公司需要后来先到的原则并且男士(或女士)优先的原则,舍弃掉头部的求职者

val names = listOf("陈女士", "张先生", "王先生", "蔡女士", "李先生", "钟女士", "朱先生")
println(names.dropWhile { it.endsWith("女士") }) // [张先生, 王先生, 蔡女士, 李先生, 钟女士, 朱先生]
println(names.dropWhile { it.endsWith("先生") }) // [陈女士, 张先生, 王先生, 蔡女士, 李先生, 钟女士, 朱先生]

源码实现

// for循环遍历,如果某个元素不满足条件,就把这个元素添加到集合并且把yielding置为true,后续的元素全部添加到集合
public inline fun <T> Iterable<T>.dropWhile(predicate: (T) -> Boolean): List<T> {
    var yielding = false
    val list = ArrayList<T>()
    for (item in this)
        if (yielding)
            list.add(item)
        else if (!predicate(item)) {
            list.add(item)
            yielding = true
        }
    return list
}

elementAt

返回索引下的元素,当索引不在有效范围内[0, lastIndex] 抛出数组越界异常,可以使用 elementAtOrNullelementAtOrElse 代替

val mobileGames = listOf("和平精英", "英雄联盟手游", "欢乐斗地主")
println(mobileGames.elementAt(1)) // 英雄联盟手游
println(mobileGames.elementAt(mobileGames.lastIndex + 1)) // java.lang.ArrayIndexOutOfBoundsException 异常

源码实现

// List通过get方法获取
// 否则通过elementAtOrElse
public fun <T> Iterable<T>.elementAt(index: Int): T {
    if (this is List)
        return get(index)
    return elementAtOrElse(index) { throw IndexOutOfBoundsException("Collection doesn't contain element at index $index.") }
}

elementAtOrElse

返回索引下的元素,当索引不在有效范围内[0, lastIndex] 时返回默认值

val mobileGames = listOf("和平精英", "英雄联盟手游", "欢乐斗地主")
println(mobileGames.elementAtOrElse(1) { "未找到游戏" }) // 英雄联盟手游
println(mobileGames.elementAtOrElse(mobileGames.lastIndex + 1) { "未找到游戏" }) // 未找到游戏

源码实现

public fun <T> Iterable<T>.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T {
    if (this is List)
        return this.getOrElse(index, defaultValue)
    if (index < 0)
        return defaultValue(index)
    val iterator = iterator()
    var count = 0
    while (iterator.hasNext()) {
        val element = iterator.next()
        if (index == count++)
            return element
    }
    return defaultValue(index)
}

elementAtOrNull

返回索引下的元素,当索引不在有效范围内[0, lastIndex] 时返回null

例如

val list = listOf(1, 2, 3, 4, 5)
list.elementAtOrNull(3) = 4
list.elementAtOrNull(5) = null

源码实现

public fun <T> Iterable<T>.elementAtOrNull(index: Int): T? {
    if (this is List)
        return this.getOrNull(index)
    if (index < 0)
        return null
    val iterator = iterator()
    var count = 0
    while (iterator.hasNext()) {
        val element = iterator.next()
        if (index == count++)
            return element
    }
    return null
}

filter

按条件过滤元素,返回满足条件的所有元素

例如

val names = listOf("司马懿", "诸葛亮", "吕布", "黄忠", "赵云", "凤雏庞统")
println(names.filter { it.length >= 3 })

源码实现

// 通过filterTo实现,filterTo后面再说
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
    return filterTo(ArrayList<T>(), predicate)
}

filterIndexed

按条件过滤元素,跟 filter 不同的是 filterIndexed 的函数类型的参数会多一个 int 类型的 index 索引

例如我们以单双划分集合

val names = listOf("司马懿", "诸葛亮", "吕布", "黄忠", "赵云", "凤雏庞统")
val even = names.filterIndexed { index, _ -> index % 2 == 0 } // [司马懿, 吕布, 赵云] 
val odd =  names.filterIndexed { index, _ -> index % 2 == 1 } // [诸葛亮, 黄忠, 凤雏庞统]

源码实现

// 通过filterIndexedTo实现,传进去的集合是ArrayList
public inline fun <T> Iterable<T>.filterIndexed(predicate: (index: Int, T) -> Boolean): List<T> {
    return filterIndexedTo(ArrayList<T>(), predicate)
}

filterIndexedTo

按条件过滤元素,将过滤后的元素添加到集合中

val names = listOf("司马懿", "诸葛亮", "司马懿", "吕布", "黄忠", "赵云", "凤雏庞统")
val evenSet = hashSetOf<String>()
val oddSet = hashSetOf<String>()
val even = names.filterIndexedTo(evenSet) { index, _ -> index % 2 == 0 } // [司马懿, 凤雏庞统, 黄忠] 
val odd =  names.filterIndexedTo(oddSet) { index, _ -> index % 2 == 1 } // [吕布, 诸葛亮, 赵云]

源码实现

// 传进来的集合必须是MutableCollection,因为会通过这个集合去添加过滤后的元素,返回传进来的集合
// 通过forEachIndexed过滤满足条件的元素
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterIndexedTo(destination: C, predicate: (index: Int, T) -> Boolean): C {
    forEachIndexed { index, element ->
        if (predicate(index, element)) destination.add(element)
    }
    return destination
}

filterIsInstance

过滤同类型的元素,返回新的集合

例如我们有如下集合,我们需要以 StringInt 划分

val typeValues =  listOf("蔡徐坤", 88, "唱跳rap", "篮球", 177, 68)
println(typeValues.filterIsInstance<String>()) // [蔡徐坤, 唱跳rap, 篮球]
println(typeValues.filterIsInstance<Int>()) // [88, 177, 68]

源码实现

// 通过filterIsInstanceTo实现,参数是ArrayList
public inline fun <reified R> Iterable<*>.filterIsInstance(): List<@kotlin.internal.NoInfer R> {
    return filterIsInstanceTo(ArrayList<R>())
}

filterIsInstanceTo

过滤同类型的元素,将过滤后的元素添加到集合中

val stringSet = hashSetOf<String>()
val intSets = hashSetOf<Int>()
val typeValues = listOf("蔡徐坤", 88, "唱跳rap", "篮球", 177, 68)
println(typeValues.filterIsInstanceTo(stringSet))
println(typeValues.filterIsInstanceTo(intSets))

源码实现

// 通过for循环遍历集合,将符合类型的元素添加到传进来的集合中
public inline fun <reified R, C : MutableCollection<in R>> Iterable<*>.filterIsInstanceTo(destination: C): C {
    for (element in this) if (element is R) destination.add(element)
    return destination
}

filterNot

按条件过滤元素,返回不满足条件的所有元素,刚好跟 filter 相反

例如我们需要获取大学名字长度不等于4的大学

val universitySet =
    setOf("厦门大学", "四川大学", "清华大学", "中山大学", "武汉理工大学", "华南理工大学", "中国传媒大学")
println(universitySet.filterNot { it.length == 4 }) // [武汉理工大学, 华南理工大学, 中国传媒大学]

源码实现

// 通过filterNotTo过滤
public inline fun <T> Iterable<T>.filterNot(predicate: (T) -> Boolean): List<T> {
    return filterNotTo(ArrayList<T>(), predicate)
}

filterNotNull

过滤掉 null 的元素

val random = listOf<Any?>("蔡徐坤", 2.5f, "唱跳rap", null)
println(random.filterNotNull()) //[蔡徐坤, 2.5, 唱跳rap]

源码实现

// 通过filterNotNullTo过滤
public fun <T : Any> Iterable<T?>.filterNotNull(): List<T> {
    return filterNotNullTo(ArrayList<T>())
}

filterNotNullTo

过滤掉 null 的元素,将剩余的元素添加到传进来的集合中

val random = listOf<Any?>("蔡徐坤", 2.5f, "唱跳rap", null)
val hashSet = hashSetOf<Any>() 
println(random.filterNotNullTo(hashSet)) // [2.5, 唱跳rap, 蔡徐坤]

源码实现

// 如果元素为空,则添加到传进来的集合中
public fun <C : MutableCollection<in T>, T : Any> Iterable<T?>.filterNotNullTo(destination: C): C {
    for (element in this) if (element != null) destination.add(element)
    return destination
}

filterNotTo

按条件过滤元素,将不满足条件的元素添加到传进来的集合中

例如

val universitySet =
    setOf("厦门大学", "四川大学", "清华大学", "中山大学", "武汉理工大学", "华南理工大学", "中国传媒大学")
val lenNot4Items = hashSetOf<String>()
println(universitySet.filterNotTo(lenNot4Items) { it.length == 4 }) // [武汉理工大学, 华南理工大学, 中国传媒大学]

源码实现

// 将不满足条件的元素添加到传进来的集合中
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterNotTo(destination: C, predicate: (T) -> Boolean): C {
    for (element in this) if (!predicate(element)) destination.add(element)
    return destination
}

filterTo

按条件过滤元素,将满足条件的元素添加到传进来的集合中, 刚好跟 filterNotTo 相反

例如

@Test
fun filterToExample() {
    val universitySet =
        setOf("厦门大学", "四川大学", "清华大学", "中山大学", "武汉理工大学", "华南理工大学", "中国传媒大学")
    val len4Items = hashSetOf<String>()
    println(universitySet.filterTo(len4Items) { it.length == 4 }) // [厦门大学, 四川大学, 中山大学, 清华大学]
}

源码实现

// for循环遍历,将满足条件的添加到集合
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
    for (element in this) if (predicate(element)) destination.add(element)
    return destination
}

find

按条件查找满足条件的第一个元素,如果找到就直接返回,找不到返回null

例如

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.find { it.startsWith("A") }) // Apple
println(company.find { it.endsWith("G") }) // null

源码实现

// 内部通过firstOrNull实现
public inline fun <T> Iterable<T>.find(predicate: (T) -> Boolean): T? {
    return firstOrNull(predicate)
}

findLast

按条件查找满足条件的最后一个元素,如果找到就直接返回,找不到返回null,与 find 查找顺序相反

例如

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.findLast { it.startsWith("A") }) // Alibaba
println(company.findLast { it.endsWith("G") }) // null

源码实现

// 内部通过lastOrNull实现
public inline fun <T> List<T>.findLast(predicate: (T) -> Boolean): T? {
    return lastOrNull(predicate)
}

first

返回第一个元素或者第一个满足条件的元素,如果找不到该元素就抛出 NoSuchElementException 异常,可以使用 firstOrNull 代替

例如

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.first()) // Google
println(company.first { it.startsWith("A") }) // Apple
println(company.first { it.endsWith("G") }) // java.util.NoSuchElementException: Collection contains no element matching the predicate.

源码实现

public fun <T> List<T>.first(): T {
    if (isEmpty())
        throw NoSuchElementException("List is empty.")
    return this[0]
}

// List 返回首个元素
// 否则使用迭代器返回
public fun <T> Iterable<T>.first(): T {
    when (this) {
        is List -> return this.first()
        else -> {
            val iterator = iterator()
            if (!iterator.hasNext())
                throw NoSuchElementException("Collection is empty.")
            return iterator.next()
        }
    }
}

firstNotNullOf

返回第一个转换后的非空元素,如果没有就抛出 NoSuchElementException 异常

例如

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
val companyMap = hashMapOf("抖音" to "字节", "快手" to "快手集团", "企鹅" to "腾讯")
println(company.firstNotNullOf { it.length }) // 6
println(company.firstNotNullOf { companyMap[it] }) // java.util.NoSuchElementException: No element of the collection was transformed to a non-null value.

源码实现

// 将转换函数传递给firstNotNullOfOrNull,如果firstNotNullOfOrNull返回空则抛出异常
public inline fun <T, R : Any> Iterable<T>.firstNotNullOf(transform: (T) -> R?): R {
    return firstNotNullOfOrNull(transform) ?: throw NoSuchElementException("No element of the collection was transformed to a non-null value.")
}

firstNotNullOfOrNull

返回第一个转换后的非空元素,如果没有就返回 null

例如

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
val companyMap = hashMapOf("抖音" to "字节", "快手" to "快手集团", "企鹅" to "腾讯")
println(company.firstNotNullOfOrNull { it.length }) // 6
println(company.firstNotNullOfOrNull { companyMap[it] }) // null

源码实现

// 获取转换之后的值,如果不是空就返回
public inline fun <T, R : Any> Iterable<T>.firstNotNullOfOrNull(transform: (T) -> R?): R? {
    for (element in this) {
        val result = transform(element)
        if (result != null) {
            return result
        }
    }
    return null
}

firstOrNull

返回第一个元素或者第一个满足条件的元素,如果没有就返回 null

例如

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.firstOrNull()) // Google
println(company.firstOrNull { it.startsWith("A") }) // Apple
println(company.firstOrNull { it.endsWith("G") }) // null

源码实现

// 对list单独处理,其他都是通过迭代器处理
public fun <T> Iterable<T>.firstOrNull(): T? {
    when (this) {
        is List -> {
            if (isEmpty())
                return null
            else
                return this[0]
        }
        else -> {
            val iterator = iterator()
            if (!iterator.hasNext())
                return null
            return iterator.next()
        }
    }
}

// for循环遍历
public inline fun <T> Iterable<T>.firstOrNull(predicate: (T) -> Boolean): T? {
    for (element in this) if (predicate(element)) return element
    return null
}

flatMap

将集合中的元素根据转换函数得到新的值,并且将所有值铺平到新的集合中。跟 map 不同的是,flatMap 的转换函数需要返回一个新的集合,并且会将转换后的值都铺平到集合中,所以如果有嵌套的集合转换成单层的集合时请使用 flatMap

例如

val intList = listOf(1, 2, 3, 4, 5)
val nestList = listOf(listOf(1, 2), listOf(3, 4), listOf(5, 6, 7))
println(intList.flatMap { listOf(it + it, it * it, it * it * it) }) // [2, 1, 1, 4, 4, 8, 6, 9, 27, 8, 16, 64, 10, 25, 125]
println(nestList.flatMap { item -> item.map { it * it } }) // [1, 4, 9, 16, 25, 36, 49]

源码实现

// flatMapTo到ArrayList
public inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R> {
    return flatMapTo(ArrayList<R>(), transform)
}

flatMapIndexed

flatMap 一样,不过 lambda 中多了个 index 索引参数

例如

val intList = listOf(1, 2, 3, 4, 5)
println(intList.flatMapIndexed { index, it -> listOf(it + it, it * it, it * it * it) })

源码实现

// flatMapIndexedTo到ArrayList
public inline fun <T, R> Iterable<T>.flatMapIndexed(transform: (index: Int, T) -> Iterable<R>): List<R> {
    return flatMapIndexedTo(ArrayList<R>(), transform)
}

flatMapIndexedTo

flatMapIndexed 最终实现的源码,将转换后的元素添加到传进来的集合中

例如

val intList = listOf(1, 2, 3, 4, 5)
val hashSet = hashSetOf<Int>()
println(intList.flatMapIndexedTo(hashSet) { index, it -> listOf(it + it, it * it, it * it * it) }) // [16, 64, 1, 2, 4, 6, 8, 9, 25, 10, 27, 125]
println(hashSet) // [16, 64, 1, 2, 4, 6, 8, 9, 25, 10, 27, 125]

源码实现

// 遍历整个集合,将转换函数获得的集合添加到传进来的集合中
// checkIndexOverflow是防止数组越界
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapIndexedTo(destination: C, transform: (index: Int, T) -> Iterable<R>): C {
    var index = 0
    for (element in this) {
        val list = transform(checkIndexOverflow(index++), element)
        destination.addAll(list)
    }
    return destination
}

flatMapTo

flatMap 最终实现的源码,将转换后的元素添加到传进来的集合中

val nestList = listOf(listOf(1, 2), listOf(3, 4), listOf(5, 6, 7))
val destSet = hashSetOf<Int>()
println(nestList.flatMapTo(destSet) { item -> item.map { it * it } })
println(destSet)

源码实现

// 遍历整个集合,将转换函数获得的集合添加到传进来的集合中
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
}

fold

对每个元素进行操作,返回积累的总值。集合为空则返回初始值

例如需要计算1到5的总和或者平方和

val intList = listOf(1, 2, 3, 4, 5)
println(intList.fold(0) { prev, item -> prev + item  }) // 15
println(intList.fold(0) { prev, item -> prev + item * item  }) // 55

源码实现

// 遍历整个集合,将上一个的结果传到下一个的遍历中,需要传入初始值
public inline fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) -> R): R {
    var accumulator = initial
    for (element in this) accumulator = operation(accumulator, element)
    return accumulator
}

foldIndexed

fold 一样,只是 lambda 中多了个 index 索引参数

val intList = listOf(1, 2, 3, 4, 5)
println(intList.foldIndexed(0) { index, prev, item -> prev + item })
println(intList.foldIndexed(0) { index, prev, item -> prev + item * item })

源码实现

// 遍历整个集合,将上一个的结果传到下一个的遍历中,需要传入初始值
public inline fun <T, R> Iterable<T>.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R {
    var index = 0
    var accumulator = initial
    for (element in this) accumulator = operation(checkIndexOverflow(index++), accumulator, element)
    return accumulator
}

foldRight

对每个元素进行操作,返回积累的总值。与 fold 不同的是,foldRight 是从右到左积累,fold 是从左到右积累。因为是有顺序的,所以只作用于 list

val intList = listOf(1, 2, 3, 4, 5)
println(intList.foldRight(0) { prev, item -> prev + item }) // 15

源码实现

// 通过listIterator迭代整个list,如果为空返回默认值
public inline fun <T, R> *List*<T>.foldRight(initial: R, operation: (T, acc: R) -> R): R {
    var accumulator = initial
    if (!isEmpty()) {
        val iterator = listIterator(size)
        while (iterator.hasPrevious()) {
            accumulator = operation(iterator.previous(), accumulator)
        }
    }
    return accumulator
}

foldRightIndexed

foldRight 一样,只是 lambda 中多了个 index 索引参数

val intList = listOf(1, 2, 3, 4, 5)
println(intList.foldIndexed(0) { index, prev, item -> prev + item })

源码实现

// // 通过listIterator迭代整个list,如果为空返回默认值
public inline fun <T, R> *List*<T>.foldRightIndexed(initial: R, operation: (index: Int, T, acc: R) -> R): R {
    var accumulator = initial
    if (!isEmpty()) {
        val iterator = listIterator(size)
        while (iterator.hasPrevious()) {
            val index = iterator.previousIndex()
            accumulator = operation(index, iterator.previous(), accumulator)
        }
    }
    return accumulator
}

forEach

forEach 遍历,lambda 返回每一个元素

val intList = listOf(1, 2, 3, 4, 5)
intList.forEach {
    println(it)
}
// 1 2 3 4 5

源码实现

// for循环遍历
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
    for (element in this) action(element)
}

forEachIndexed

forEach 一样,只是 lambda 中多了个 index 索引参数

源码实现

// for循环遍历
public inline fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit {
    var index = 0
    for (item in this) action(checkIndexOverflow(index++), item)
}

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

img

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题

你可能感兴趣的:(kotlin,android,开发语言)