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 truefor (element in this) if (!predicate(element)) return falsereturn 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 falsefor (element in this) if (predicate(element)) return truereturn 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 sizevar count = 0for (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 0var count = 0for (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 - nif (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 = 0for (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 = falseval 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 = 0while (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 nullval iterator = iterator()var count = 0while (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 nullelsereturn this[0]}else -> {val iterator = iterator()if (!iterator.hasNext())return nullreturn iterator.next()}}
}// for循环遍历
public inline fun <T> Iterable<T>.firstOrNull(predicate: (T) -> Boolean): T? {for (element in this) if (predicate(element)) return elementreturn 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 = 0for (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 = initialfor (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 = 0var accumulator = initialfor (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 = initialif (!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 = initialif (!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 = 0for (item in this) action(checkIndexOverflow(index++), item)
}

最后

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

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

img

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/27063.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

讯飞星火认知大模型成果发布会举行

目录 一、提出通用人工智能七大维度481项评测体系 二、讯飞星火认知大模型三大能力已超ChatGPT 现场语音输入流畅 多维实测燃爆全场 写邮件、做方案、讲故事&#xff0c;讯飞星火大模型到底有多会写&#xff1f; 中文理解十级测试&#xff0c;现场观众&#xff1a;讯飞星火…

OpenAI 推出漏洞赏金计划,最高奖励 2 万美元;京东零售开启 5 年来最大组织变革;​Django 4.2|极客头条...

「极客头条」—— 技术人员的新闻圈&#xff01; CSDN 的读者朋友们早上好哇&#xff0c;「极客头条」来啦&#xff0c;快来看今天都有哪些值得我们技术人关注的重要新闻吧。 整理 | 梦依丹 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 一分钟速览新闻点&#…

“三项能力超过ChatGPT”,科大讯飞星火大模型现场接受观众挑战,写稿制表PPT通通拿下...

杨净 发自 合肥量子位 | 公众号 QbitAI “三项能力超过ChatGPT” “1024将整体超过GPT水平&#xff01;” 在科大讯飞星火认知大模型发布会现场&#xff0c;董事长刘庆峰拍着胸脯保证&#xff0c;引起现场掌声雷动&#xff01; 而真机演示效果和多场景产品展示直接把观众们看呆…

自然机器人最新发布:智能流程助手,与GPT深度融合

ChatGPT自2022年11月上线后就受到现象级地广泛关注&#xff0c;5天时间用户就已经突破百万&#xff0c;仅2个月时间月活用户就突破1亿&#xff0c;成为史上增速最快的消费级应用&#xff0c;远超TikTok、Facebook、Google等全球应用。它展现了类似人类的语言理解和对话交互能力…

go语言实现聊天服务器(多人聊天)

用go语言实现一个server作中转群发消息&#xff0c;多个客户端聊天 1&#xff09;服务器开启&#xff0c;等待来自客户端的连接&#xff0c;把每一个客户端存储在map中 2&#xff09;客户端连接服务器&#xff0c;给自己取一个别名&#xff0c;存储在服务器 3&#xff09;服…

Golang 从零开始实现多人聊天室(三)上线通知与公屏聊天

系列文章目录 跟着&#x1f63d;猫猫学Golang&#xff0c;快人一步 系列初开&#xff0c;跟着我走进Go 语言的世界里&#x1f30d; 系列目录 Golang 从零开始实现多人聊天室&#xff08;一&#xff09;服务端监听 Golang 从零开始实现多人聊天室&#xff08;二&#xff09;客…

商务人士邮箱推荐?高大上邮箱来了!

既然点进文章那不用多说&#xff0c;大家肯定都是商务人士。在普通人眼里商务人士就等于精英人士&#xff0c;他们的行头都是一身西装梳着根根分明的大背头&#xff0c;他们会多国语言精通各种数字&#xff0c;总之就是看起来很厉害每天很精致。那商务人士到底是不是这样呢我也…

商务人士适合用什么邮箱?一款商务人士必备的邮箱推荐

在商务及办公场合中&#xff0c;电子邮箱的使用越加频繁&#xff0c;对于邮箱的选择安全及易用性成为了重中之重。 如果你是金融、互联网、法律、机关单位等领域的商务人士&#xff0c;或者你需要将邮箱作为对外的入口&#xff0c;对你而言&#xff0c;一个可靠的付费邮箱是非…

国内好用的邮箱评选,电子邮箱大全有你的吗?

国内邮箱、好用的邮箱、电子邮箱大全、163邮箱、TOM邮箱、邮箱品牌 早在三国时期&#xff0c;一种说法便流传至今&#xff0c;这酒是“三分天下”&#xff0c;最早是指三国时期魏、蜀、吴三国鼎立并且互相牵制的局面。在现代&#xff0c;也常常引用“三分天下”来形容某市场或…

你知道大量群发邮件用什么邮箱好吗?

随着社会的发展&#xff0c;我们的销售模式也在发生这巨大的变化&#xff0c;在之前我们的销售模式主要靠在线下的各种人的走街串巷的来进行营销&#xff0c;但是随着我们科技的进步&#xff0c;互联网也成为了我们生活中密不可分的一部分&#xff0c;在这时候一种全新的营销模…

堪称最佳邮箱Gmail邮箱的神奇的一号多名功能

QQ邮箱支持添加一个英文用户名的foxmail邮箱&#xff0c;已经比很多邮箱好用&#xff0c;但是gmail邮箱的一号多名的功能更为神奇&#xff0c;一个邮箱账号可以变成无数个邮箱&#xff0c;对于需要很多邮箱账号的情形&#xff0c;比如注册网络小号&#xff0c;非常有用&#xf…

推荐国内外,安全好用的电子邮箱

众多邮箱品牌&#xff0c;人们熟悉QQ、网易、新浪&#xff0c;较之而言&#xff0c;TOM邮箱更具安全性、实用性。小编整理分析详情如下。 性价比高、功能实用&#xff1a;TOM含免费邮箱&#xff0c;又相继推出了极致邮、畅享邮&#xff0c;后两款为VIP付费邮箱&#xff0c;容量…

最近沉迷美女图片无法自拔,所以我决定用PHP扒海量妹子图

为什么80%的码农都做不了架构师&#xff1f;>>> 学习PHPMySQL制作WEB应用有一阵子了&#xff0c;没有上过学所以只能学习到CURD的地步。 最近对国产美女图片、私房写真特别感兴趣&#xff0c;什么周妍希、刘飞儿、李可可、推女郎我一个都不知道~~ 经常调查我发现一…

TA(技术美术)宝藏网站

TA&#xff08;技术美术&#xff09;宝藏网站 我们不生产TA我们只是TA的搬运工&#xff08;感谢马甲大佬总结&#xff01;&#xff1f;&#xff09;T部分&#xff08;技术相关&#xff09;1.Shadertoy2.GLSL SandboX3.candycat的博客4.关于raymarching5.minionsart大神6.冯委大…

杜凯杰教学数据分析:python 图片爬取 爬取各校校花图片

python 图片爬取 爬取各校校花图片 —杜凯杰 爬取十页校花图片(可按需求更改页数&#xff0c;爬取更多图片)—杜凯杰 import requests from lxml import etree startUrlhttp://www.xiaohuar.com/list-1- headers{User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleW…

chatgpt赋能python:Python如何操作Word文档

Python如何操作Word文档 简介 Python是一种高级编程语言&#xff0c;具有易于学习和使用、高效、可移植性强等优点。相信许多Python开发者都遇到过需要使用Python操作Word文档的情况。本文旨在介绍如何使用Python操作Word文档&#xff0c;使开发者能够方便地实现自己的需求。…

Word2vec工作原理

文章目录 前言Word2Vec的工作原理CBOWSkip-Gram 参考文献点关注&#xff0c;防走丢&#xff0c;如有纰漏之处&#xff0c;请留言指教&#xff0c;非常感谢 前言 随着计算机应用领域的不断扩大&#xff0c;自然语言处理受到了人们的高度重视。尤其是最近出现的chatgpt&#xff0…

GPT-3 vs Bert vs GloVe vs Word2vec 文本嵌入技术的性能对比测试

来源&#xff1a;DeepHub IMBA 本文约3000字&#xff0c;建议阅读6分钟 随着NLP(自然语言处理)的最新进展&#xff0c;OpenAI的GPT-3已经成为市场上最强大的语言模型之一。 2022年1月25日&#xff0c;OpenAI公布了一个embedding endpoint(Neelakantan et al.&#xff0c; 2022)…

人大李崇轩:我的生成模型修炼之路丨智源大会嘉宾风采

导读 AIGC的飞速发展离不开生成模型、深度学习以及多模态学习等领域研究的不断累积&#xff0c;其中生成模型的原理与算法发展是不可或缺的一部分&#xff0c;如&#xff1a;生成对抗网络 GAN 及其一系列变体、变分自编码器 VAE 及其一系列变体、自回归模型 AR、流模型 FLOW &a…

一篇文章教会你用Python抓取抖音app热点数据

今天给大家分享一篇简单的安卓app数据分析及抓取方法。以抖音为例&#xff0c;我们想要抓取抖音的热点榜数据。 要知道&#xff0c;这个数据是没有网页版的&#xff0c;只能从手机端下手。 首先我们要安装charles抓包APP数据&#xff0c;它是一款收费的抓包修改工具&#xf…