调集操作符

今天介绍下 Kotlin 调集中的操作符,本文中 Kotlin 所用版本是 1.8.10

大部分的操作符是运用内联完成的,假如对内联函数感兴趣,能够康康我的这篇文章,Kotlin inline内联函数

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
}
// 调集不是空就回来true了
public fun <T> Iterable<T>.any(): Boolean {
    if (this is Collection) return !isEmpty()
    return iterator().hasNext()
}

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

留意 这儿的 lambda 表达式的第一个参数是元素,第二个参数是上一次操作的值

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

源码完成

// 经过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 索引参数

留意 这儿的 lambda 表达式的第一个参数是索引,第二个参数是元素,第三个参数是上一次操作的值

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

源码完成

// // 经过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)
}

关于 forEach 如何退出,能够康康我的这篇文章 forEach 中 如何退出循环?

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)
}

getOrElse

获取 List 中某个索引的值,假如 索引不在范围 [0, lastIndex] 内时,则回来默认值。只效果于List

有的时分咱们需求获取某个索引的值又害怕出现数组越界,能够选用这个函数

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.getOrElse(8) { "unknown" }) // unknown
println(company.getOrElse(2) { "unknown" }) // IBM
println(company[8]) // java.lang.ArrayIndexOutOfBoundsException

源码完成

// 没有数组越界经过 get办法获取,数组越界回来默认值
public inline fun <T> List<T>.getOrElse(index: Int, defaultValue: (Int) -> T): T {
    return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index)
}

getOrNull

获取 List 中某个索引的值,假如 索引不在范围 [0, lastIndex] 内时,则回来 null,与 getOrElse 相似不过默认值是 null 。只效果于List

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.getOrNull(8)) // null
println(company.getOrNull(2)) // IBM

源码完成

// 没有数组越界经过 get办法获取,数组越界回来null
public fun <T> List<T>.getOrNull(index: Int): T? {
    return if (index >= 0 && index <= lastIndex) get(index) else null
}

groupBy

依据分组函数对调集进行分组,回来分组成果 MapMap 中的 key 类型由分组函数决议, value 的类型是 List

groupBy 两个参数的函数会对调集元素的值进行转化,终究增加到 Map

例如咱们需求对字符串按长度进行分组,那么 Mapkey 便是 Int 类型

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.groupBy { it.length }) // {6=[Google], 9=[Microsoft], 3=[IBM], 5=[Apple, Yahoo, Baidu], 7=[Alibaba]}
// 两个参数,给元素增加个_下标
println(company.groupBy({ it.length }) { it + "_" }) // {6=[Google_], 9=[Microsoft_], 3=[IBM_], 5=[Apple_, Yahoo_, Baidu_], 7=[Alibaba_]}

源码完成

// 经过groupByTo完成,传入的是LinkedHashMap,所以回来的其实是LinkedHashMap目标
public inline fun <T, K> Iterable<T>.groupBy(keySelector: (T) -> K): Map<K, List<T>> {
    return groupByTo(LinkedHashMap<K, MutableList<T>>(), keySelector)
}
public inline fun <T, K, V> Iterable<T>.groupBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map<K, List<V>> {
    return groupByTo(LinkedHashMap<K, MutableList<V>>(), keySelector, valueTransform)
}

groupByTo

groupBy 终究的完成,将键值对增加到传进来的 MutableMap

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
val lenToStringMap = hashMapOf<Int, MutableList<String>>()
val lenToStringTransformMap = hashMapOf<Int, MutableList<String>>()
println(company.groupByTo(lenToStringMap) { it.length })  // {3=[IBM], 5=[Apple, Yahoo, Baidu], 6=[Google], 7=[Alibaba], 9=[Microsoft]}
println(company.groupByTo(lenToStringTransformMap, { it.length }) { it + "_" }) // {3=[IBM_], 5=[Apple_, Yahoo_, Baidu_], 6=[Google_], 7=[Alibaba_], 9=[Microsoft_]}
println(lenToStringMap) // {3=[IBM], 5=[Apple, Yahoo, Baidu], 6=[Google], 7=[Alibaba], 9=[Microsoft]}
println(lenToStringTransformMap) // {3=[IBM_], 5=[Apple_, Yahoo_, Baidu_], 6=[Google_], 7=[Alibaba_], 9=[Microsoft_]}

源码完成

// 依据分组函数获取Map的key值,经过MutableMap的getOrPut获取value,将元素增加到list中
public inline fun <T, K, M : MutableMap<in K, MutableList<T>>> Iterable<T>.groupByTo(destination: M, keySelector: (T) -> K): M {
    for (element in this) {
        val key = keySelector(element)
        val list = destination.getOrPut(key) { ArrayList<T>() }
        list.add(element)
    }
    return destination
}
// 在上面的基础上多了一步转化
public inline fun <T, K, V, M : MutableMap<in K, MutableList<V>>> Iterable<T>.groupByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M {
    for (element in this) {
        val key = keySelector(element)
        val list = destination.getOrPut(key) { ArrayList<V>() }
        list.add(valueTransform(element))
    }
    return destination
}

indexOf

获取元素的索引,当不存在该元素时回来 -1,假如仅仅判别是否在调集中 优先选用 contains

val kingdoms = setOf("秦", "楚", "齐", "燕", "赵", "魏", "韩")
println(kingdoms.indexOf("齐")) // 2
println(kingdoms.indexOf("唐")) // -1

源码完成

// for循环遍历整个调集,若在调集内则回来索引,不然回来-1
public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.indexOf(element: T): Int {
    if (this is List) return this.indexOf(element)
    var index = 0
    for (item in this) {
        checkIndexOverflow(index)
        if (element == item)
            return index
        index++
    }
    return -1
}

indexOfFirst

获取第一个满意条件的元素的索引,当一切元素都不满意条件时回来 -1

val typeValues = listOf("蔡徐坤", 88, "唱跳rap", "篮球", 177, 68)
println(typeValues.indexOfFirst { it == "唱跳rap" }) // 2
println(typeValues.indexOfFirst { it == "两年半" })  // -1

源码完成

// for循环遍历整个调集,若元素满意条件则回来该元素的索引,不然回来-1
public inline fun <T> List<T>.indexOfFirst(predicate: (T) -> Boolean): Int {
    var index = 0
    for (item in this) {
        if (predicate(item))
            return index
        index++
    }
    return -1
}

indexOfLast

获取终究一个满意条件的元素的索引,当一切元素都不满意条件时回来 -1

val typeValues = listOf("蔡徐坤", 88, "唱跳rap", "篮球", 177, "唱跳rap", 68)
println(typeValues.indexOfLast { it == "唱跳rap" }) // 5
println(typeValues.indexOfLast { it == "两年半" })  // -1

源码完成

// for循环遍历整个调集,若某个元素满意条件则将lastIndex置为该索引,终究回来lastIndex
public inline fun <T> Iterable<T>.indexOfLast(predicate: (T) -> Boolean): Int {
    var lastIndex = -1
    var index = 0
    for (item in this) {
        checkIndexOverflow(index)
        if (predicate(item))
            lastIndex = index
        index++
    }
    return lastIndex
}

intersect

获取两个调集中交集,回来的是 set

val finalFourBy2023 = listOf("凯尔特人", "热火", "湖人", "")
val finalFourBy2022 = listOf("凯尔特人", "勇士", "热火", "独行侠")
println(finalFourBy2023.intersect(finalFourBy2022)) // [凯尔特人, 热火]

源码完成

// 经过retainAll获取交集
public infix fun <T> Iterable<T>.intersect(other: Iterable<T>): Set<T> {
    val set = this.toMutableSet()
    set.retainAll(other)
    return set
}

joinTo

将一切的元素衔接到一同,经过前缀、后缀和分隔符衔接。一般咱们都是运用 StringBuilder 进行格式化输出,用得更多的是 joinToString

val finalFourBy2023 = listOf("凯尔特人", "热火", "湖人", "")
val sb = StringBuilder()
println(finalFourBy2023.joinTo(sb, separator = "#", prefix = "{", postfix = "}")) // {凯尔特人#热火#湖人#}

源码完成

// 经过Appendable增加前缀、转化后的元素、分隔符和后缀
// StringBuilder 承继了Appendable
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.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
    }
    if (limit >= 0 && count > limit) buffer.append(truncated)
    buffer.append(postfix)
    return buffer
}

joinToStrin

格式化输出调集中的一切元素,回来字符串

val finalFourBy2023 = listOf("凯尔特人", "热火", "湖人", "")
println(finalFourBy2023.joinToString(separator = "#", prefix = "{", postfix = "}")) // {凯尔特人#热火#湖人#}

源码完成

// 经过joinTo完成,StringBuilder承继了Appendable
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()
}

last

获取终究一个元素或许终究一个满意条件的元素,假如找不到该元素就抛出 NoSuchElementException 反常,能够运用 lastOrNull 替代,与 first 刚好相反

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.last()) // Baidu
println(company.last { it.startsWith("A") }) // Alibaba
println(company.first { it.endsWith("G") }) // java.util.NoSuchElementException

源码完成

// 经过found去判别是否有满意条件的元素
// 满意条件给last赋值并终究回来last
public inline fun <T> Iterable<T>.last(predicate: (T) -> Boolean): T {
    var last: T? = null
    var found = false
    for (element in this) {
        if (predicate(element)) {
            last = element
            found = true
        }
    }
    if (!found) throw NoSuchElementException("Collection contains no element matching the predicate.")
    @Suppress("UNCHECKED_CAST")
    return last as T
}
// 对List独自处理,回来List.last
// 运用迭代器迭代,回来终究一个元素
public fun <T> Iterable<T>.last(): T {
    when (this) {
        is List -> return this.last()
        else -> {
            val iterator = iterator()
            if (!iterator.hasNext())
                throw NoSuchElementException("Collection is empty.")
            var last = iterator.next()
            while (iterator.hasNext())
                last = iterator.next()
            return last
        }
    }
}
// 获取索引lastIndex的元素
public fun <T> List<T>.last(): T {
    if (isEmpty())
        throw NoSuchElementException("List is empty.")
    return this[lastIndex]
}

lastIndexOf

获取某个元素在调集中终究一个元素的索引,当不存在该元素时回来-1。indexOf 是获取第一个出现该元素的索引 ,lastIndexOfindexOf 刚好相反

val typeValues = listOf("蔡徐坤", 88, "唱跳rap", "篮球", 177, "唱跳rap", 68)
println(typeValues.lastIndexOf("唱跳rap")) // 5
println(typeValues.lastIndexOf("两年半"))  // -1

源码完成

// 对list独自处理,回来List.lastIndexOf
// 不然for循环遍历调集,获取lastIndex
public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.lastIndexOf(element: T): Int {
    if (this is List) return this.lastIndexOf(element)
    var lastIndex = -1
    var index = 0
    for (item in this) {
        checkIndexOverflow(index)
        if (element == item)
            lastIndex = index
        index++
    }
    return lastIndex
}

lastOrNull

获取终究一个元素或许终究一个满意条件的元素,假如找不到该元素则回来 null

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

源码完成

// for循环遍历调集,满意条件就给last赋值,终究回来last
public inline fun <T> Iterable<T>.lastOrNull(predicate: (T) -> Boolean): T? {
    var last: T? = null
    for (element in this) {
        if (predicate(element)) {
            last = element
        }
    }
    return last
}
// 对list独自判别,假如是空回来null,不然回来终究一个元素
// 迭代器迭代调集,回来last
public fun <T> Iterable<T>.lastOrNull(): T? {
    when (this) {
        is List -> return if (isEmpty()) null else this[size - 1]
        else -> {
            val iterator = iterator()
            if (!iterator.hasNext())
                return null
            var last = iterator.next()
            while (iterator.hasNext())
                last = iterator.next()
            return last
        }
    }
}

map

依据转化函数进行转化元素,得到一个包括一切转化之后的元素的 List

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

能够很明显看到 mapflatMap 的差异,flatMap 会铺平整个调集,而 map 仅仅将转化元素累计

源码完成

// 调用mapTo完成,传入转化函数和ArrayList
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
    return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

mapIndexed

map 相同,仅仅 lambda 中多了个 index 索引参数

val intList = listOf(1, 2, 3, 4, 5)
val nestList = listOf(listOf(1, 2), listOf(3, 4), listOf(5, 6, 7))
println(intList.mapIndexed { index, i -> "$index: $i" }) // [0: 1, 1: 2, 2: 3, 3: 4, 4: 5]
println(nestList.mapIndexed { index, item ->
    item.map {
        when (index) {
            nestList.lastIndex -> it * it * it
            else -> it * it
        }
    }
}) // [[1, 4], [9, 16], [125, 216, 343]]

源码完成

// 调用mapIndexedTo完成,传入转化函数和ArrayList
public inline fun <T, R> Iterable<T>.mapIndexed(transform: (index: Int, T) -> R): List<R> {
    return mapIndexedTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

mapIndexedNotNull

依据转化函数进行转化元素,得到一个包括一切转化之后的非空元素的 List,与 mapIndexed 对比 mapIndexedNotNull 不包括 null 元素

val intList = listOf(1, 2, 3, 4, 5)
println(intList.mapIndexedNotNull { index, i ->
    when (index) {
        intList.lastIndex -> null
        else -> i * i
    }
})  // [1, 4, 9, 16]
    // 由于终究一个元素咱们转化为了 null,所以不输出

源码完成

// 经过mapIndexedNotNullTo
public inline fun <T, R : Any> Iterable<T>.mapIndexedNotNull(transform: (index: Int, T) -> R?): List<R> {
    return mapIndexedNotNullTo(ArrayList<R>(), transform)
}

mapIndexedNotNullTo

mapIndexedNotNull 的终极完成,将转化后的非空元素增加到调集参数中

val intList = listOf(1, 2, 3, 4, 5)
val hashSet = hashSetOf<Int>()
println(intList.mapIndexedNotNullTo(hashSet) { index, i ->
    when (index) {
        intList.lastIndex -> null
        else -> i * i
    }
}) // [16, 1, 4, 9]

源码完成

// forEachIndexed遍历,然后对每个元素进行转化,?.是判别元素非空
public inline fun <T, R : Any, C : MutableCollection<in R>> Iterable<T>.mapIndexedNotNullTo(destination: C, transform: (index: Int, T) -> R?): C {
    forEachIndexed { index, element -> transform(index, element)?.let { destination.add(it) } }
    return destination
}

mapIndexedTo

mapIndexed 的终极完成,将转化后的元素增加到调集参数中

val intList = listOf(1, 2, 3, 4, 5)
val nestList = listOf(listOf(1, 2), listOf(3, 4), listOf(5, 6, 7))
val stringSet = hashSetOf<String>()
val nestSet = linkedSetOf<List<Int>>()
println(intList.mapIndexedTo(stringSet) { index, i -> "$index: $i" }) // [3: 4, 4: 5, 1: 2, 2: 3, 0: 1]
println(nestList.mapIndexedTo(nestSet) { index, item ->
    item.map {
        when (index) {
            nestList.lastIndex -> it * it * it
            else -> it * it
        }
    }
})  // [[1, 4], [9, 16], [125, 216, 343]]

源码完成

// for循环遍历,转化后增加到调集参数中
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
}

mapNotNull

依据转化函数进行转化元素,得到一个包括一切转化之后的非空元素的 List 。与map 不同的是,mapNotNull 不会出现 null

val intList = listOf(1, 2, 3, 4, 5)
println(intList.mapNotNull { if (it == 4) null else it * it }) // [1, 4, 9, 25]

源码完成

// 调用mapNotNullTo完成,传入转化函数
public inline fun <T, R : Any> Iterable<T>.mapNotNull(transform: (T) -> R?): List<R> {
    return mapNotNullTo(ArrayList<R>(), transform)
}

mapNotNullTo

mapNotNull 的终极完成,将转化后的非空元素增加到调集参数中

val intList = listOf(1, 2, 3, 4, 5)
val hashSet = hashSetOf<Int>()
println(intList.mapNotNullTo(hashSet) { if (it == 4) null else it * it }) // [1, 4, 9, 25]

源码完成

// forEach遍历元素,将元素依据转化函数进行转化,将转化之后的非空元素增加到调集
public inline fun <T, R : Any, C : MutableCollection<in R>> Iterable<T>.mapNotNullTo(destination: C, transform: (T) -> R?): C {
    forEach { element -> transform(element)?.let { destination.add(it) } }
    return destination
}

mapTo

map 的终极完成,将转化后的元素增加到调集参数中

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

源码完成

// 转化函数进行转化后增加到调集,会修正传进来的调集参数
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
}

minus

获取两个调集中的差值,或许调集中去除某个元素,回来 List

val finalFourBy2023 = listOf("凯尔特人", "热火", "湖人", "")
val finalFourBy2022 = listOf("凯尔特人", "勇士", "热火", "独行侠")
println(finalFourBy2023.minus(finalFourBy2022)) // [湖人, ]
println(finalFourBy2023 - finalFourBy2022) // 跟上面的表述是相同的,由于minus是一个操作符operator
println(finalFourBy2023.minus("热火")) // [凯尔特人, 湖人, ]
println(finalFourBy2023 - "热火")      // 跟上面的表述是相同的,由于minus是一个操作符operator

源码完成

// 实践是经过filterNot过滤掉在另一个调集中的元素
public operator fun <T> Iterable<T>.minus(elements: Iterable<T>): List<T> {
    val other = elements.convertToListIfNotCollection()
    if (other.isEmpty())
        return this.toList()
    return this.filterNot { it in other }
}
// 经过filterTo过滤掉元素,过滤完后将removed置为true
public operator fun <T> Iterable<T>.minus(element: T): List<T> {
    val result = ArrayList<T>(collectionSizeOrDefault(10))
    var removed = false
    return this.filterTo(result) { if (!removed && it == element) { removed = true; false } else true }
}

none

判别调集中是否不存在满意条件的元素,回来值为 Boolean,假如存在回来 false,假如不存在回来 true,与 any 刚好相反

例如判别调集中是否不存在偶数或许大于6

val intList = listOf(1, 2, 3, 4, 5)
println(intList.none { it % 2 == 0 }) // false
println(intList.none { it > 6 })      // true

源码完成

// 调集为空就回来true
// for循环遍历,满意条件就回来false了
// 源码跟any函数刚好相反
public inline fun <T> Iterable<T>.none(predicate: (T) -> Boolean): Boolean {
    if (this is Collection && isEmpty()) return true
    for (element in this) if (predicate(element)) return false
    return true
}
// 调集是空就回来true
public fun <T> Iterable<T>.none(): Boolean {
    if (this is Collection) return isEmpty()
    return !iterator().hasNext()
}

onEach

遍历整个调集,与 forEach 不同的是,onEach 回来调集本身,所以咱们运用 onEach 之后能够继续调用链式调用调集操作符

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
company.onEach { println(it) } // 输出整个调集
    .filter { it.length > 5 }  // 过滤元素

源码完成

// 经过apply函数遍历调集,关于apply函数咱们能够去学习下,主要是apply、let、run、with和also,apply会回来目标本身
public inline fun <T, C : Iterable<T>> C.onEach(action: (T) -> Unit): C {
    return apply { for (element in this) action(element) }
}

onEachIndexed

遍历整个调集,与 onEach 不同的是会在 lambda 中对一个 index 索引参数

val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
company.onEachIndexed { index, item -> if (index != 3) println(item) } // 输出除了apple外的一切元素
    .filter { it.length > 5 } // // 过滤元素

源码完成

// forEachIndexed遍历
public inline fun <T, C : Iterable<T>> C.onEachIndexed(action: (index: Int, T) -> Unit): C {
    return apply { forEachIndexed(action) }
}

partition

将调集进行分类,满意条件和不满意条件的,回来 Pair,类型是 List 。说实话 我没怎么用过 Pair,看了下 Pair 才知道是数据类型

public data class Pair<out A, out B>(
    public val first: A,
    public val second: B
) : Serializable {
    /**
     * Returns string representation of the [Pair] including its [first] and [second] values.
     */
    public override fun toString(): String = "($first, $second)"
}

例如咱们需求将小伙伴依据性别进行分类,非男即女嘛

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

源码完成

// for循环遍历,将满意条件的增加到first,不然增加到second
// 回来pair数据类型,传进first和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)
}

plus

获取两个调集中的总和,或许调集中增加某个元素,回来 List。假如要确保元素唯一,请运用 set

val finalFourBy2023 = listOf("凯尔特人", "热火", "湖人", "")
val finalFourBy2022 = listOf("凯尔特人", "勇士", "热火", "独行侠")
println(finalFourBy2023.plus(finalFourBy2022)) // [凯尔特人, 热火, 湖人, , 凯尔特人, 勇士, 热火, 独行侠]
println(finalFourBy2023 + finalFourBy2022) // 跟上面的表述相同,由于plus是一个操作符operator
println(finalFourBy2023.plus("热火")) // [凯尔特人, 热火, 湖人, , 热火]
println(finalFourBy2023 + "热火") // 跟上面的表述相同,由于plus是一个操作符operator

源码完成

// 假如是Collection,则调用它的plus办法
public operator fun <T> Iterable<T>.plus(elements: Iterable<T>): List<T> {
    if (this is Collection) return this.plus(elements)
    val result = ArrayList<T>()
    result.addAll(this)
    result.addAll(elements)
    return result
}
// 增加的调集是Collection,则获取调集的长度,然后增加调集总值
public operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T> {
    if (elements is Collection) {
        val result = ArrayList<T>(this.size + elements.size)
        result.addAll(this)
        result.addAll(elements)
        return result
    } else {
        val result = ArrayList<T>(this)
        result.addAll(elements)
        return result
    }
}
// 增加单个元素
public operator fun <T> Iterable<T>.plus(elements: Array<out T>): List<T> {
    if (this is Collection) return this.plus(elements)
    val result = ArrayList<T>()
    result.addAll(this)
    result.addAll(elements)
    return result
}
// 增加单个元素
public operator fun <T> Collection<T>.plus(element: T): List<T> {
    val result = ArrayList<T>(size + 1)
    result.addAll(this)
    result.add(element)
    return result
}

plusElement

增加某个元素到调集中,不是操作符,所以不能运用 “+”,其内部也是经过 plus 完成

源码完成

public inline fun <T> Iterable<T>.plusElement(element: T): List<T> {
    return plus(element)
}

randomrandomOrNull

随机获取某个元素,与咱们常用的 random 差不多意思,假如调集为空, random 抛出 NoSuchElementException 反常,randomOrNull 回来空,只效果于 Collection。其实完成原理很简单,便是随机拿到索引,然后经过索引回来元素

源码完成

public fun <T> Collection<T>.random(random: Random): T {
    if (isEmpty())
        throw NoSuchElementException("Collection is empty.")
    return elementAt(random.nextInt(size))
}
public fun <T> Collection<T>.randomOrNull(random: Random): T? {
    if (isEmpty())
        return null
    return elementAt(random.nextInt(size))
}

reduce

对调集中的每个元素进行操作,回来堆集的总值。与 fold 不同的是,reduce 不需求传入初始值,而且假如调集为空,则抛出 UnsupportedOperationException 反常,能够运用 reduceOrNull 替代

val intList = listOf(1, 2, 3, 4, 5)
println(emptyList<Int>().reduce { acc, item -> acc + item }) // java.lang.UnsupportedOperationException
println(intList.reduce { acc, item -> acc + item }) // 15
println(intList.reduce { acc, item -> acc + item * item }) // 55

源码完成

// 经过迭代器迭代调集,假如为空则抛出UnsupportedOperationException反常
// 初次accumulator是首个元素,将accumulator传入下一次操作中
public inline fun <S, T : S> Iterable<T>.reduce(operation: (acc: S, T) -> S): S {
    val iterator = this.iterator()
    if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
    var accumulator: S = iterator.next()
    while (iterator.hasNext()) {
        accumulator = operation(accumulator, iterator.next())
    }
    return accumulator
}

reduceIndexed

reduce 相同,仅仅 lambda 中多了个 index 索引参数,index 从 1 开端的,不是从 0 开端

val intList = listOf(1, 2, 3, 4, 5)
println(emptyList<Int>().reduceIndexed { index, acc, item -> acc + item }) // java.lang.UnsupportedOperationException
println(intList.reduceIndexed { index, acc, item -> if (index != 1) acc + item else acc * item }) // 14
println(intList.reduceIndexed { index, acc, item -> acc + item * item }) // 55

源码完成

// 经过迭代器迭代调集,假如为空则抛出UnsupportedOperationException反常
// 初次accumulator是首个元素,将accumulator传入下一次操作中
// 留意看这儿初始index是1,为什么是1?由于第一次取值现已拿出首个元素了
public inline fun <S, T : S> Iterable<T>.reduceIndexed(operation: (index: Int, acc: S, T) -> S): S {
    val iterator = this.iterator()
    if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
    var index = 1
    var accumulator: S = iterator.next()
    while (iterator.hasNext()) {
        accumulator = operation(checkIndexOverflow(index++), accumulator, iterator.next())
    }
    return accumulator
}

reduceIndexedOrNull

reduceIndexed相同,仅仅调集为空的时分回来 null

val intList = listOf(1, 2, 3, 4, 5)
println(emptyList<Int>().reduceIndexedOrNull { index, acc, item -> acc + item }) // null
println(intList.reduceIndexedOrNull { index, acc, item -> if (index != 1) acc + item else acc * item }) // 14
println(intList.reduceIndexedOrNull { index, acc, item -> acc + item * item }) // 55

源码完成

// 经过迭代器迭代调集,假如为空则回来null
// 初次accumulator是首个元素,将accumulator传入下一次操作中
// 留意看这儿初始index是1,为什么是1?由于第一次取值现已拿出首个元素了
public inline fun <S, T : S> Iterable<T>.reduceIndexedOrNull(operation: (index: Int, acc: S, T) -> S): S? {
    val iterator = this.iterator()
    if (!iterator.hasNext()) return null
    var index = 1
    var accumulator: S = iterator.next()
    while (iterator.hasNext()) {
        accumulator = operation(checkIndexOverflow(index++), accumulator, iterator.next())
    }
    return accumulator
}

reduceOrNull

reduce 相同,仅仅调集为空的时分回来 null

val intList = listOf(1, 2, 3, 4, 5)
println(emptyList<Int>().reduceOrNull { acc, item -> acc + item }) // null
println(intList.reduceOrNull { acc, item -> acc + item })          // 15
println(intList.reduceOrNull { acc, item -> acc + item * item })   // 55

源码完成

// 调集为空则回来null
public inline fun <S, T : S> Iterable<T>.reduceOrNull(operation: (acc: S, T) -> S): S? {
    val iterator = this.iterator()
    if (!iterator.hasNext()) return null
    var accumulator: S = iterator.next()
    while (iterator.hasNext()) {
        accumulator = operation(accumulator, iterator.next())
    }
    return accumulator
}

reduceRight

对调集中的每个元素进行操作,回来堆集的总值。与 reduce 不同的是,reduceRight 是从右到左堆集,reduce 是从左到右堆集。由于是有次序的,所以只效果于 list

留意 这儿的 lambda 表达式的第一个参数是元素,第二个参数是上一次操作的值

val intList = listOf(1, 2, 3, 4, 5)
println(emptyList<Int>().reduceRight { item, acc -> acc + item })  // java.lang.UnsupportedOperationException
println(intList.reduceRight { item, acc -> acc + item }) // 15
println(intList.reduceRight { item, acc -> acc + item * item }) // 35

源码完成

// 运用listIterator迭代器遍历
public inline fun <S, T : S> List<T>.reduceRight(operation: (T, acc: S) -> S): S {
    val iterator = listIterator(size)
    if (!iterator.hasPrevious())
        throw UnsupportedOperationException("Empty list can't be reduced.")
    var accumulator: S = iterator.previous()
    while (iterator.hasPrevious()) {
        accumulator = operation(iterator.previous(), accumulator)
    }
    return accumulator
}

reduceRightIndexed

reduceRight 相同,仅仅 lambda 中多了个 index 索引参数

留意 这儿的 lambda 表达式的第一个参数是索引,第二个参数是元素,第三个参数是上一次操作的值

val intList = listOf(1, 2, 3, 4, 5)
println(emptyList<Int>().reduceRightIndexed { index, item, acc -> acc + item }) // java.lang.UnsupportedOperationException
println(intList.reduceRightIndexed { index, item, acc -> acc + item }) // 15
println(intList.reduceRightIndexed { index, item, acc -> acc + item * item }) // 35

源码完成

// 运用listIterator迭代器遍历
public inline fun <S, T : S> List<T>.reduceRightIndexed(operation: (index: Int, T, acc: S) -> S): S {
    val iterator = listIterator(size)
    if (!iterator.hasPrevious())
        throw UnsupportedOperationException("Empty list can't be reduced.")
    var accumulator: S = iterator.previous()
    while (iterator.hasPrevious()) {
        val index = iterator.previousIndex()
        accumulator = operation(index, iterator.previous(), accumulator)
    }
    return accumulator
}

reduceRightIndexedOrNull

reduceRightIndexed 相同,仅仅调集为空的时分回来 null

val intList = listOf(1, 2, 3, 4, 5)
println(emptyList<Int>().reduceRightIndexedOrNull { index, item, acc -> acc + item }) // null
println(intList.reduceRightIndexedOrNull { index, item, acc -> acc + item })  // 15
println(intList.reduceRightIndexedOrNull { index, item, acc -> acc + item * item })  // 35

源码完成

// 运用listIterator迭代器遍历
// 调集为空时回来null
public inline fun <S, T : S> List<T>.reduceRightIndexedOrNull(operation: (index: Int, T, acc: S) -> S): S? {
    val iterator = listIterator(size)
    if (!iterator.hasPrevious())
        return null
    var accumulator: S = iterator.previous()
    while (iterator.hasPrevious()) {
        val index = iterator.previousIndex()
        accumulator = operation(index, iterator.previous(), accumulator)
    }
    return accumulator
}

reduceRightOrNull

reduceRight 相同,仅仅调集为空的时分回来 null

val intList = listOf(1, 2, 3, 4, 5)
println(emptyList<Int>().reduceRightOrNull { item, acc -> acc + item }) // null
println(intList.reduceRightOrNull { item, acc -> acc + item })  // 15
println(intList.reduceRightOrNull { item, acc -> acc + item * item })  // 35

源码完成

// 运用listIterator迭代器遍历
// 调集为空时回来null
public inline fun <S, T : S> List<T>.reduceRightOrNull(operation: (T, acc: S) -> S): S? {
    val iterator = listIterator(size)
    if (!iterator.hasPrevious())
        return null
    var accumulator: S = iterator.previous()
    while (iterator.hasPrevious()) {
        accumulator = operation(iterator.previous(), accumulator)
    }
    return accumulator
}

requireNoNulls

假如调集中存在 null 元素,抛出 IllegalArgumentException 反常,不然回来一个不包括 null 元素 的调集

val random = listOf<Any?>("蔡徐坤", 2.5f, "唱跳rap", null)
val intList = listOf(1, 2, 3, 4, 5)
println(intList.requireNoNulls())   // [1, 2, 3, 4, 5]
println(random.requireNoNulls())    // java.lang.IllegalArgumentException

源码完成

// 很简单,for循环遍历,假如有null则跑出反常,不然强转类型
public fun <T : Any> Iterable<T?>.requireNoNulls(): Iterable<T> {
    for (element in this) {
        if (element == null) {
            throw IllegalArgumentException("null element found in $this.")
        }
    }
    @Suppress("UNCHECKED_CAST")
    return this as Iterable<T>
}
public fun <T : Any> List<T?>.requireNoNulls(): List<T> {
    for (element in this) {
        if (element == null) {
            throw IllegalArgumentException("null element found in $this.")
        }
    }
    @Suppress("UNCHECKED_CAST")
    return this as List<T>
}

reversed

反序调集,回来 List

val finalFourBy2023 = listOf("凯尔特人", "热火", "湖人", "")
println(finalFourBy2023.reversed())  // [, 湖人, 热火, 凯尔特人]

源码完成

// 长度小于1,回来toList,不然toMutableList
public fun <T> Iterable<T>.reversed(): List<T> {
    if (this is Collection && size <= 1) return toList()
    val list = toMutableList()
    list.reverse()
    return list
}
// reverse 拓展函数,expect好像是跨平台函数完成?作者没找到具体完成是哪,有小伙伴知道能够告诉下
public expect fun <T> MutableList<T>.reverse(): Unit

runningFold

从左到右进行累加值,并将每一次履行之后的累计值放进调集中,回来的是 List,需求传入初始值。与 Fold 本质差异在于,Fold 是回来累加值的总值,而 runningFold 是将每个累加值都增加到 List 中回来。假如调集为空,则回来只带有初始值的 List

val intList = listOf(1, 2, 3, 4, 5)
println(intList.runningFold(0) { prev, item -> prev + item }) // [0, 1, 3, 6, 10, 15]
println(intList.runningFold(0) { prev, item -> prev + item * item }) // [0, 1, 5, 14, 30, 55]

源码完成

// collectionSizeOrDefault获取的是调集的长度
// 为什么ArrayList的长度是estimatedSize + 1?由于它还有个初始值,初始值是直接加入到ArrayList的
// 每履行一次函数,就值放入到ArrayList中,终究回来
public inline fun <T, R> Iterable<T>.runningFold(initial: R, operation: (acc: R, T) -> R): List<R> {
    val estimatedSize = collectionSizeOrDefault(9)
    if (estimatedSize == 0) return listOf(initial)
    val result = ArrayList<R>(estimatedSize + 1).apply { add(initial) }
    var accumulator = initial
    for (element in this) {
        accumulator = operation(accumulator, element)
        result.add(accumulator)
    }
    return result
}
internal fun <T> Iterable<T>.collectionSizeOrDefault(default: Int): Int = if (this is Collection<*>) this.size else default

runningFoldIndexed

runningFold 相同,仅仅 lambda 多了个 index 索引参数

val intList = listOf(1, 2, 3, 4, 5)
println(intList.runningFoldIndexed(0) { index, prev, item -> if (index == 0) prev + item else prev + item * item }) // [0, 1, 5, 14, 30, 55]
println(intList.runningFoldIndexed(0) { index, prev, item -> if (index == 0) prev + item * item else prev * item * item }) // [0, 1, 4, 36, 576, 14400]

源码完成

// collectionSizeOrDefault获取的是调集的长度
// 为什么ArrayList的长度是estimatedSize + 1?由于它还有个初始值,初始值是直接加入到ArrayList的
// 每履行一次函数,就值放入到ArrayList中,终究回来
public inline fun <T, R> Iterable<T>.runningFoldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): List<R> {
    val estimatedSize = collectionSizeOrDefault(9)
    if (estimatedSize == 0) return listOf(initial)
    val result = ArrayList<R>(estimatedSize + 1).apply { add(initial) }
    var index = 0
    var accumulator = initial
    for (element in this) {
        accumulator = operation(index++, accumulator, element)
        result.add(accumulator)
    }
    return result
}
internal fun <T> Iterable<T>.collectionSizeOrDefault(default: Int): Int = if (this is Collection<*>) this.size else default

runningReduce

从左到右进行累加值,并将每一次履行之后的累计值放进调集中,回来的是 List。与 reduce 本质差异在于,reduce 是回来累加值的总值,而 runningReduce 是将每个累加值都增加到 List 中回来。与 runningFold 的差异在于, runningReduce 不需求传入初始值,假如调集为空则直接回来空调集

val intList = listOf(1, 2, 3, 4, 5)
println(emptyList<Int>().runningReduce { acc, item -> acc + item }) // []
println(intList.runningReduce { acc, item -> acc + item })   // [1, 3, 6, 10, 15]
println(intList.runningReduce { acc, item -> acc + item * item }) // [1, 5, 14, 30, 55]

源码完成

// 空调集则直接回来emptyList
// 这儿将调集中的首个元素当做了初始值,并增加到调集中
public inline fun <S, T : S> Iterable<T>.runningReduce(operation: (acc: S, T) -> S): List<S> {
    val iterator = this.iterator()
    if (!iterator.hasNext()) return emptyList()
    var accumulator: S = iterator.next()
    val result = ArrayList<S>(collectionSizeOrDefault(10)).apply { add(accumulator) }
    while (iterator.hasNext()) {
        accumulator = operation(accumulator, iterator.next())
        result.add(accumulator)
    }
    return result
}

runningReduceIndexed

runningReduce 相同,仅仅 lambda 中多了个 index 索引参数

val intList = listOf(1, 2, 3, 4, 5)
println(emptyList<Int>().runningReduceIndexed { index, acc, item -> if (index == 1) acc + item else acc * item }) // []
println(intList.runningReduceIndexed { index, acc, item -> if (index == 1) acc + item else acc * item })  // [1, 3, 9, 36, 180]
println(intList.runningReduceIndexed { index, acc, item -> if (index == 1) acc + item * item else acc * item * item }) //  [1, 5, 45, 720, 18000]

源码完成

// 空调集则直接回来emptyList
// 这儿将调集中的首个元素当做了初始值,并增加到调集中
// 留意这儿的index是从1开端的,由于初次现已将索引为0的元素直接增加到调集中了
public inline fun <S, T : S> Iterable<T>.runningReduceIndexed(operation: (index: Int, acc: S, T) -> S): List<S> {
    val iterator = this.iterator()
    if (!iterator.hasNext()) return emptyList()
    var accumulator: S = iterator.next()
    val result = ArrayList<S>(collectionSizeOrDefault(10)).apply { add(accumulator) }
    var index = 1
    while (iterator.hasNext()) {
        accumulator = operation(index++, accumulator, iterator.next())
        result.add(accumulator)
    }
    return result
}

scan

runningFold 相同都是累加总值回来 List, 其内部完成便是经过 runningFold,这儿就不多说了

源码完成

public inline fun <T, R> Iterable<T>.scan(initial: R, operation: (acc: R, T) -> R): List<R> {
    return runningFold(initial, operation)
}

scanIndexed

runningFoldIndexed 相同都是累加总值回来 List, 其内部完成便是经过 runningFoldIndexed,这儿就不多说了

public inline fun <T, R> Iterable<T>.scanIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): List<R> {
    return runningFoldIndexed(initial, operation)
}

shuffle

打乱调集的次序,随机摆放调集元素。

val finalFourBy2023 = setOf("凯尔特人", "热火", "湖人", "")
println(finalFourBy2023.shuffled()) // [湖人, , 凯尔特人, 热火],每一个都有可能是新的一次排序,这儿仅仅随机了其间一次

源码完成

Kotlin 是直接调用 Java 层的代码完成的,详细看下面

// java.util.Collections
public static void shuffle(List<?> list) {
    Random rnd = r;
    if (rnd == null)
        r = rnd = new Random(); // harmless race.
    shuffle(list, rnd);
}

当然,Kotlin 也有自己的完成,不过回来的是 Unit,咱们略微看一下

// 倒序遍历,也是经过random完成
// this[j] = this.set(i, this[j]) 是交流两个元素的方位
public fun <T> MutableList<T>.shuffle(random: Random): Unit {
    for (i in lastIndex downTo 1) {
        val j = random.nextInt(i + 1)
        this[j] = this.set(i, this[j])
    }
}

single

判别调集中有且只要一个元素满意条件,假如有多个元素满意条件则抛出 IllegalArgumentException 反常,假如没有元素满意条件则抛出 NoSuchElementException 反常,终究回来该元素

val finalFourBy2023 = setOf("凯尔特人", "热火", "湖人", "")
println(finalFourBy2023.single { it.length > 2 }) // 凯尔特人
println(finalFourBy2023.single { it.endsWith("人") })  // java.lang.IllegalArgumentException
println(finalFourBy2023.single { it == "太阳" }) // // java.util.NoSuchElementException

源码完成

// 经过found的值去判别,假如满意条件而且found为true则抛出IllegalArgumentException
// 遍历完调集后,found假如为false则抛出NoSuchElementException
public inline fun <T> Iterable<T>.single(predicate: (T) -> Boolean): T {
    var single: T? = null
    var found = false
    for (element in this) {
        if (predicate(element)) {
            if (found) throw IllegalArgumentException("Collection contains more than one matching element.")
            single = element
            found = true
        }
    }
    if (!found) throw NoSuchElementException("Collection contains no element matching the predicate.")
    @Suppress("UNCHECKED_CAST")
    return single as T
}
// single的重载函数,不需求传入函数类型的参数
// 这个就简单多了,假如调集为空则抛出NoSuchElementException
// 假如调集长度大于1,则抛出IllegalArgumentException
public fun <T> Iterable<T>.single(): T {
    when (this) {
        is List -> return this.single()
        else -> {
            val iterator = iterator()
            if (!iterator.hasNext())
                throw NoSuchElementException("Collection is empty.")
            val single = iterator.next()
            if (iterator.hasNext())
                throw IllegalArgumentException("Collection has more than one element.")
            return single
        }
    }
}

singleOrNull

判别调集中有且只要一个元素满意条件,假如有多个元素满意条件或许没有元素满意条件则回来 null

val finalFourBy2023 = setOf("凯尔特人", "热火", "湖人", "")
println(finalFourBy2023.singleOrNull { it.length > 2 })  // 凯尔特人
println(finalFourBy2023.singleOrNull { it.endsWith("人") }) // null
println(finalFourBy2023.singleOrNull { it == "太阳" }) // null

源码完成

// 与 single 的源码差不多,仅仅把single抛出反常的当地换成了回来null
public inline fun <T> Iterable<T>.singleOrNull(predicate: (T) -> Boolean): T? {
    var single: T? = null
    var found = false
    for (element in this) {
        if (predicate(element)) {
            if (found) return null
            single = element
            found = true
        }
    }
    if (!found) return null
    return single
}
// 这个重载函数就不用说了吧,依据调集元素个数判别,只要1个元素才回来值,不然回来null
public fun <T> Iterable<T>.singleOrNull(): T? {
    when (this) {
        is List -> return if (size == 1) this[0] else null
        else -> {
            val iterator = iterator()
            if (!iterator.hasNext())
                return null
            val single = iterator.next()
            if (iterator.hasNext())
                return null
            return single
        }
    }
}

slice

这个一听单词就知道是切开的效果,主要是切开调集后回来切开之后的一切元素,回来的是 List,只效果于 List,(插句话:不知道咱们有没试过切开数组?)

slice 有两个重载函数,一个是传入 IntRange,一个是传入索引的调集。一般来说用 IntRange 的更多,究竟需求切开获取连续值多点嘛

留意 IntRange 是两端闭区间

例如咱们需求前三个元素的调集,能够这样做

val names = listOf("陈女士", "张先生", "王先生", "蔡女士", "李先生", "钟女士", "朱先生")
println(names.slice(IntRange(0, 2))) // [陈女士, 张先生, 王先生]
println(names.slice(0..2)) // 等价与上面的IntRange(0, 2),0..2是一个极简的表达
println(names.slice(listOf(0, 1, 2)))  // [陈女士, 张先生, 王先生]

或许咱们需求随机获取调集,能够这样做

val names = listOf("陈女士", "张先生", "王先生", "蔡女士", "李先生", "钟女士", "朱先生")
println(names.slice(listOf(0, 5, 4, 3)))  // [陈女士, 钟女士, 李先生, 蔡女士]
println(names.slice(listOf(0, 5, 7, 3, 9))) // java.lang.ArrayIndexOutOfBoundsException

留意 不管是 IntRange 仍是 索引的调集,都需求在调集的有用索引内即[0, lastIndex],不然会出现数组越界

源码完成

// 假如是空,则回来空调集
// 为什么需求indices.endInclusive + 1? 
// 由于IntRange是两端闭区间[start, end],subList获取的是开区间[start, end)
// 留意数组越界问题
public fun <T> List<T>.slice(indices: IntRange): List<T> {
    if (indices.isEmpty()) return listOf()
    return this.subList(indices.start, indices.endInclusive + 1).toList()
}
// 依据索引获取元素,然后增加到List中
// 留意数组越界问题
public fun <T> List<T>.slice(indices: Iterable<Int>): List<T> {
    val size = indices.collectionSizeOrDefault(10)
    if (size == 0) return emptyList()
    val list = ArrayList<T>(size)
    for (index in indices) {
        list.add(get(index))
    }
    return list
}

sortBy

依据函数类型参数的回来值进行排序调集,其实是经过 ASCII 值排序。会修正原调集,回来的是 Unit,只效果于 MutableListMutableListList 的差异?MutableList 能够 curdList 只能获取和遍历

例如依据姓名或许年纪排序

data class Person(val name: String, val age: Int)
val virtualPeoples = mutableListOf(
    Person(name = "陈女士", age = 18),
    Person(name = "王先生", age = 28),
    Person(name = "王小姐", age = 23),
    Person(name = "陈先生", age = 33),
)
virtualPeoples.sortBy { it.name }
println(virtualPeoples) // [Person(name=王先生, age=28), Person(name=王小姐, age=23), Person(name=陈先生, age=33), Person(name=陈女士, age=18)]
virtualPeoples.sortBy { it.age }
println(virtualPeoples) // [Person(name=陈女士, age=18), Person(name=王小姐, age=23), Person(name=王先生, age=28), Person(name=陈先生, age=33)]

源码完成

// 经过sortWith排序
public inline fun <T, R : Comparable<R>> MutableList<T>.sortBy(crossinline selector: (T) -> R?): Unit {
    if (size > 1) sortWith(compareBy(selector))
}

sortByDescending

sortBy 相似,仅仅 sortBy 是升序,sortByDescending 是降序

data class Person(val name: String, val age: Int)
val virtualPeoples = mutableListOf(
    Person(name = "陈女士", age = 18),
    Person(name = "王先生", age = 28),
    Person(name = "王小姐", age = 23),
    Person(name = "陈先生", age = 33),
)
virtualPeoples.sortByDescending { it.name }
println(virtualPeoples) // [Person(name=陈女士, age=18), Person(name=陈先生, age=33), Person(name=王小姐, age=23), Person(name=王先生, age=28)]
virtualPeoples.sortByDescending { it.age }
println(virtualPeoples) // [Person(name=陈先生, age=33), Person(name=王先生, age=28), Person(name=王小姐, age=23), Person(name=陈女士, age=18)]

源码完成

// 经过sortWith排序
public inline fun <T, R : Comparable<R>> MutableList<T>.sortByDescending(crossinline selector: (T) -> R?): Unit {
    if (size > 1) sortWith(compareByDescending(selector))
}

sortDescending

依据 Comparable 进行降序排序,假如要自定义类支撑 sortDescending,必须承继 Comparable 重写 compareTo 办法

例如咱们依据姓名和年纪进行排序

data class ComparablePerson(val name: String, val age: Int) : Comparable<ComparablePerson> {
    override fun compareTo(other: ComparablePerson): Int {
        return if (name == other.name) {
            age - other.age
        } else {
            name.compareTo(other.name)
        }
    }
}
val virtualPeoples = mutableListOf(
    ComparablePerson(name = "陈女士", age = 18),
    ComparablePerson(name = "王先生", age = 28),
    ComparablePerson(name = "王小姐", age = 23),
    ComparablePerson(name = "陈女士", age = 33),
)
virtualPeoples.sortDescending()
println(virtualPeoples) // [ComparablePerson(name=陈女士, age=33), ComparablePerson(name=陈女士, age=18), ComparablePerson(name=王小姐, age=23), ComparablePerson(name=王先生, age=28)]

源码完成

// sortWith,传入reverseOrder,咱们能够大胆猜想便是reverseOrder是的排序降序的
public fun <T : Comparable<T>> MutableList<T>.sortDescending(): Unit {
    sortWith(reverseOrder())
}

sorted

依据 Comparable 进行升序排序,假如要自定义类支撑 sorted,必须承继 Comparable 重写 compareTo 办法。

留意sortByxxx 不同的是,sortedxxx 不会修正原调集,而是回来一个新的调集

data class ComparablePerson(val name: String, val age: Int) : Comparable<ComparablePerson> {
    override fun compareTo(other: ComparablePerson): Int {
        return if (name == other.name) {
            age - other.age
        } else {
            name.compareTo(other.name)
        }
    }
}
val virtualPeoples = mutableListOf(
    ComparablePerson(name = "陈女士", age = 18),
    ComparablePerson(name = "王先生", age = 28),
    ComparablePerson(name = "王小姐", age = 23),
    ComparablePerson(name = "陈女士", age = 33),
)
println(virtualPeoples.sorted()) // [ComparablePerson(name=王先生, age=28), ComparablePerson(name=王小姐, age=23), ComparablePerson(name=陈女士, age=18), ComparablePerson(name=陈女士, age=33)]
println(virtualPeoples) // [ComparablePerson(name=陈女士, age=18), ComparablePerson(name=王先生, age=28), ComparablePerson(name=王小姐, age=23), ComparablePerson(name=陈女士, age=33)]

源码完成

// 假如是Collection,经过数组来进行排序后转为List
public fun <T : Comparable<T>> Iterable<T>.sorted(): List<T> {
    if (this is Collection) {
        if (size <= 1) return this.toList()
        @Suppress("UNCHECKED_CAST")
        return (toTypedArray<Comparable<T>>() as Array<T>).apply { sort() }.asList()
    }
    return toMutableList().apply { sort() }
// 貌似是跨平台的完成?
expect fun <T : Comparable<T>> MutableList<T>.sort(): Unit

sortedBy

依据函数类型参数的回来值进行升序排序调集

留意sortByxxx 不同的是,sortedxxx 不会修正原调集,而是回来一个新的调集

data class Person(val name: String, val age: Int)
val virtualPeoples = mutableListOf(
    Person(name = "陈女士", age = 18),
    Person(name = "王先生", age = 28),
    Person(name = "王小姐", age = 23),
    Person(name = "陈先生", age = 33),
)
println(virtualPeoples.sortedBy { it.age }) // [Person(name=陈女士, age=18), Person(name=王小姐, age=23), Person(name=王先生, age=28), Person(name=陈先生, age=33)]
println(virtualPeoples.sortedBy { it.name }) // [Person(name=王先生, age=28), Person(name=王小姐, age=23), Person(name=陈先生, age=33), Person(name=陈女士, age=18)]
println(virtualPeoples) // [Person(name=陈女士, age=18), Person(name=王先生, age=28), Person(name=王小姐, age=23), Person(name=陈先生, age=33)]

源码完成

// sortedWith完成
public inline fun <T, R : Comparable<R>> Iterable<T>.sortedBy(crossinline selector: (T) -> R?): List<T> {
    return sortedWith(compareBy(selector))
}

sortedByDescending

依据函数类型参数的回来值进行降序排序调集,与 sortedBy 刚好相反

留意sortByxxx 不同的是,sortedxxx 不会修正原调集,而是回来一个新的调集

data class Person(val name: String, val age: Int)
val virtualPeoples = mutableListOf(
    Person(name = "陈女士", age = 18),
    Person(name = "王先生", age = 28),
    Person(name = "王小姐", age = 23),
    Person(name = "陈先生", age = 33),
)
println(virtualPeoples.sortedByDescending { it.age }) // [Person(name=陈先生, age=33), Person(name=王先生, age=28), Person(name=王小姐, age=23), Person(name=陈女士, age=18)]
println(virtualPeoples.sortedByDescending { it.name }) // [Person(name=陈女士, age=18), Person(name=陈先生, age=33), Person(name=王小姐, age=23), Person(name=王先生, age=28)]
println(virtualPeoples) // [Person(name=陈女士, age=18), Person(name=王先生, age=28), Person(name=王小姐, age=23), Person(name=陈先生, age=33)]

源码完成

public inline fun <T, R : Comparable<R>> Iterable<T>.sortedBy(crossinline selector: (T) -> R?): List<T> {
    return sortedWith(compareBy(selector))
}

sortedDescending

依据 Comparable 进行降序排序,假如要自定义类支撑 sortedDescending,必须承继 Comparable 重写 compareTo 办法。

留意sortByxxx 不同的是,sortedxxx 不会修正原调集,而是回来一个新的调集

data class ComparablePerson(val name: String, val age: Int) : Comparable<ComparablePerson> {
    override fun compareTo(other: ComparablePerson): Int {
        return if (name == other.name) {
            age - other.age
        } else {
            name.compareTo(other.name)
        }
    }
}
val virtualPeoples = mutableListOf(
    ComparablePerson(name = "陈女士", age = 18),
    ComparablePerson(name = "王先生", age = 28),
    ComparablePerson(name = "王小姐", age = 23),
    ComparablePerson(name = "陈女士", age = 33),
)
println(virtualPeoples.sortedDescending()) // [ComparablePerson(name=陈女士, age=33), ComparablePerson(name=陈女士, age=18), ComparablePerson(name=王小姐, age=23), ComparablePerson(name=王先生, age=28)]
println(virtualPeoples) // [ComparablePerson(name=陈女士, age=18), ComparablePerson(name=王先生, age=28), ComparablePerson(name=王小姐, age=23), ComparablePerson(name=陈女士, age=33)]

源码完成

// reverseOrder 降序
public fun <T : Comparable<T>> Iterable<T>.sortedDescending(): List<T> {
    return sortedWith(reverseOrder())
}

sortedWith

一切 sortxxx 排序的终究完成,需求传入一个 Comparator,一般都是用它的上层函数,不怎么会用到这个函数,除非要自定义排序的方法。

例如我这儿便是弄了升序和降序两种排序方法

data class Person(val name: String, val age: Int)
// 升序
object AscendComparator : Comparator<Person> {
    override fun compare(o1: Person, o2: Person): Int {
        return if (o1.name == o2.name) {
            o1.age - o2.age
        } else {
            o1.name.compareTo(o2.name)
        }
    }
}
// 降序
object DescendComparator : Comparator<Person> {
    override fun compare(o1: Person, o2: Person): Int {
        return if (o1.name == o2.name) {
            o2.age - o1.age
        } else {
            o2.name.compareTo(o1.name)
        }
    }
}
val virtualPeoples = mutableListOf(
    Person(name = "陈女士", age = 18),
    Person(name = "王先生", age = 28),
    Person(name = "王小姐", age = 23),
    Person(name = "陈女士", age = 33),
)
println(virtualPeoples.sortedWith(AscendComparator)) // [Person(name=王先生, age=28), Person(name=王小姐, age=23), Person(name=陈女士, age=18), Person(name=陈女士, age=33)]
println(virtualPeoples.sortedWith(DescendComparator))  // [Person(name=陈女士, age=33), Person(name=陈女士, age=18), Person(name=王小姐, age=23), Person(name=王先生, age=28)]

源码完成

// 假如是Collection则经过数组进行排序
public fun <T> Iterable<T>.sortedWith(comparator: Comparator<in T>): List<T> {
    if (this is Collection) {
       if (size <= 1) return this.toList()
       @Suppress("UNCHECKED_CAST")
       return (toTypedArray<Any?>() as Array<T>).apply { sortWith(comparator) }.asList()
    }
    return toMutableList().apply { sortWith(comparator) }
}

好累好累~,终于讲完了排序,排序的常识仍是蛮多的。插一句话,一般情况下都是 sortByxxx 会多点,它会修正原调集的次序,而假如你需求回来一个新的调集,则考虑运用 sortedxxx