这篇文章介绍下 Kotlin
集合中的操作符,本文中 Kotlin
所用版本是 1.8.10
all
判断集合中的所有元素是否满足需求,返回值为 Boolean
例如我们需要判断字符串的长度是否大于4
val songs = listOf("一路向北", "搁浅", "最长的电影")
songs.all { it.length >= 4 } // false
源码实现
// 继承Collection并且为空集合,直接返回为true
// 假如有一个元素不满足条件,直接返回false
public inline fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean {
if (this is Collection && isEmpty()) return true
for (element in this) if (!predicate(element)) return false
return true
}
any
判断集合中是否存在满足条件的元素,返回值为 Boolean
例如我们需要判断是否存在185cm 8块腹肌以上的小哥哥
val heights = listOf(188, 165, 175)
heights.any { it >= 185 } // true
源码实现
// 继承Collection并且为空集合,直接返回为false
// 假如有一个元素满足条件,直接返回true
public inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean {
if (this is Collection && isEmpty()) return false
for (element in this) if (predicate(element)) return true
return false
}
contains
集合是否包含某个元素,返回为 Boolean
例如判断班上是否有个名叫蔡徐坤的童鞋
val nickname = listOf("蔡徐坤", "坤蔡徐", "蔡坤徐", "蔡徐坤")
println(nickname.contains("蔡徐坤")) // true
源码实现
// 继承Collection,则通过Collection.contains()判断是否包含
// 负责通过indexOf判断
public operator fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.contains(element: T): Boolean {
if (this is Collection)
return contains(element)
return indexOf(element) >= 0
}
count
返回集合中的长度
val nickname = listOf("蔡徐坤", "坤蔡徐", "蔡坤徐", "蔡徐坤")
println(nickname.count()) // 4
源码实现
// 继承Collection,返回size
// 使用for循环计数
public fun <T> Iterable<T>.count(): Int {
if (this is Collection) return size
var count = 0
for (element in this) checkCountOverflow(++count)
return count
}
根据条件返回集合中满足条件的所有元素长度
例如我们需要统计班上的童鞋身高达到 185cm 的人数
val height = listOf(188, 165, 175, 185)
println(height.count { it >= 185 } ) // 2
源码实现
// 集合并且长度为0,返回0
// 满足predicate,计数累加并返回
public inline fun <T> Iterable<T>.count(predicate: (T) -> Boolean): Int {
if (this is Collection && isEmpty()) return 0
var count = 0
for (element in this) if (predicate(element)) checkCountOverflow(++count)
return count
}
distinct
过滤掉集合中相同的元素,返回一个新集合,实际是通过 HashSet
保证元素不重复
例如过滤掉重名的同学
val nickname = listOf("蔡徐坤", "坤蔡徐", "蔡坤徐", "蔡徐坤")
nickname.distinct() // [蔡徐坤, 坤蔡徐, 蔡坤徐]
源码实现
public fun <T> Iterable<T>.distinct(): List<T> {
return this.toMutableSet().toList()
}
distinctBy
根据条件过滤掉集合中的元素,返回一个新集合,实际是通过 HashSet
保证元素不重复
例如根据名字长度过滤
val nickname = listOf("蔡徐坤", "蔡", "坤蔡徐", "蔡坤徐", "蔡徐")
nickname.distinctBy { it.length } // [蔡徐坤, 蔡, 蔡徐]
如果想实现 distinct
过滤相同的元素,这样写即可(那还不如直接用 distinct
呢)
nickname.distinctBy { it }
源码实现
// HashSet可以添加元素,就将元素添加到list
public inline fun <T, K> Iterable<T>.distinctBy(selector: (T) -> K): List<T> {
val set = HashSet<K>()
val list = ArrayList<T>()
for (e in this) {
val key = selector(e)
if (set.add(key))
list.add(e)
}
return list
}
drop
过滤集合中前 n
个 元素,返回新的集合。n < 0
时抛出 IllegalArgumentException
异常,n = 0
时返回原集合,n >= 集合长度
时返回空集合
val heroName = listOf("蛮三刀", "托儿索", "儿童劫", "提款姬", "菊花信")
println(heroName.drop(0)) // [蛮三刀, 托儿索, 儿童劫, 提款姬, 菊花信]
println(heroName.drop(2)) // [儿童劫, 提款姬, 菊花信]
println(heroName.drop(6)) // []
源码实现
// n = 0,返回toList()
// 继承Collection时,获取去除后的集合长度,长度为0返回emptyList,长度为1返回最后一个元素,否则通过ArrayList添加元素
public fun <T> Iterable<T>.drop(n: Int): List<T> {
require(n >= 0) { "Requested element count $n is less than zero." }
if (n == 0) return toList()
val list: ArrayList<T>
if (this is Collection<*>) {
val resultSize = size - n
if (resultSize <= 0)
return emptyList()
if (resultSize == 1)
return listOf(last())
list = ArrayList<T>(resultSize)
if (this is List<T>) {
if (this is RandomAccess) {
for (index in n until size)
list.add(this[index])
} else {
for (item in listIterator(n))
list.add(item)
}
return list
}
}
else {
list = ArrayList<T>()
}
var count = 0
for (item in this) {
if (count >= n) list.add(item) else ++count
}
return list.optimizeReadOnlyList()
}
dropLast
跟 drop
刚好相反,dropLast
是从尾部过滤。n < 0
时抛出 IllegalArgumentException
异常,n = 0
时返回原集合,n >= 集合长度
时返回空集合
val heroName = listOf("蛮三刀", "托儿索", "儿童劫", "提款姬", "菊花信")
println(heroName.dropLast(0)) // [蛮三刀, 托儿索, 儿童劫, 提款姬, 菊花信]
println(heroName.dropLast(2)) // [蛮三刀, 托儿索, 儿童劫]
println(heroName.dropLast(6)) // []
源码实现
// 通过take()获取结果,take后面再说
public fun <T> List<T>.dropLast(n: Int): List<T> {
require(n >= 0) { "Requested element count $n is less than zero." }
return take((size - n).coerceAtLeast(0))
}
dropLastWhile
根据条件从尾部开始过滤元素,直到某个元素不满足条件时返回
例如现在求职者太多了,公司需要秉承先来后到并且职位更适合高个子的原则,舍弃掉末尾的求职者
val heights = listOf(185, 158, 177, 190, 169, 170, 168)
println(heights.dropLastWhile { it <= 175 }) // [185, 158, 177, 190]
println(heights.dropLastWhile { it < 170 }) // [185, 158, 177, 190, 169, 170]
源码实现
// 通过迭代器从后到前迭代,直到不满足条件时通过take截取
public inline fun <T> List<T>.dropLastWhile(predicate: (T) -> Boolean): List<T> {
if (!isEmpty()) {
val iterator = listIterator(size)
while (iterator.hasPrevious()) {
if (!predicate(iterator.previous())) {
return take(iterator.nextIndex() + 1)
}
}
}
return emptyList()
}
dropWhile
根据条件从头部开始过滤元素,跟 dropLastWhile
刚好相反,直到某个元素不满足条件时返回剩余集合
还是上面的例子,不过我们调整下筛选的规则,公司需要后来先到的原则并且男士(或女士)优先的原则,舍弃掉头部的求职者
val names = listOf("陈女士", "张先生", "王先生", "蔡女士", "李先生", "钟女士", "朱先生")
println(names.dropWhile { it.endsWith("女士") }) // [张先生, 王先生, 蔡女士, 李先生, 钟女士, 朱先生]
println(names.dropWhile { it.endsWith("先生") }) // [陈女士, 张先生, 王先生, 蔡女士, 李先生, 钟女士, 朱先生]
源码实现
// for循环遍历,如果某个元素不满足条件,就把这个元素添加到集合并且把yielding置为true,后续的元素全部添加到集合
public inline fun <T> Iterable<T>.dropWhile(predicate: (T) -> Boolean): List<T> {
var yielding = false
val list = ArrayList<T>()
for (item in this)
if (yielding)
list.add(item)
else if (!predicate(item)) {
list.add(item)
yielding = true
}
return list
}
elementAt
返回索引下的元素,当索引不在有效范围内[0, lastIndex] 抛出数组越界异常,可以使用 elementAtOrNull
或 elementAtOrElse
代替
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
过滤同类型的元素,返回新的集合
例如我们有如下集合,我们需要以 String
和 Int
划分
val typeValues = listOf("蔡徐坤", 88, "唱跳rap", "篮球", 177, 68)
println(typeValues.filterIsInstance<String>()) // [蔡徐坤, 唱跳rap, 篮球]
println(typeValues.filterIsInstance<Int>()) // [88, 177, 68]
源码实现
// 通过filterIsInstanceTo实现,参数是ArrayList
public inline fun <reified R> Iterable<*>.filterIsInstance(): List<@kotlin.internal.NoInfer R> {
return filterIsInstanceTo(ArrayList<R>())
}
filterIsInstanceTo
过滤同类型的元素,将过滤后的元素添加到集合中
val stringSet = hashSetOf<String>()
val intSets = hashSetOf<Int>()
val typeValues = listOf("蔡徐坤", 88, "唱跳rap", "篮球", 177, 68)
println(typeValues.filterIsInstanceTo(stringSet))
println(typeValues.filterIsInstanceTo(intSets))
源码实现
// 通过for循环遍历集合,将符合类型的元素添加到传进来的集合中
public inline fun <reified R, C : MutableCollection<in R>> Iterable<*>.filterIsInstanceTo(destination: C): C {
for (element in this) if (element is R) destination.add(element)
return destination
}
filterNot
按条件过滤元素,返回不满足条件的所有元素,刚好跟 filter
相反
例如我们需要获取大学名字长度不等于4的大学
val universitySet =
setOf("厦门大学", "四川大学", "清华大学", "中山大学", "武汉理工大学", "华南理工大学", "中国传媒大学")
println(universitySet.filterNot { it.length == 4 }) // [武汉理工大学, 华南理工大学, 中国传媒大学]
源码实现
// 通过filterNotTo过滤
public inline fun <T> Iterable<T>.filterNot(predicate: (T) -> Boolean): List<T> {
return filterNotTo(ArrayList<T>(), predicate)
}
filterNotNull
过滤掉 null
的元素
val random = listOf<Any?>("蔡徐坤", 2.5f, "唱跳rap", null)
println(random.filterNotNull()) //[蔡徐坤, 2.5, 唱跳rap]
源码实现
// 通过filterNotNullTo过滤
public fun <T : Any> Iterable<T?>.filterNotNull(): List<T> {
return filterNotNullTo(ArrayList<T>())
}
filterNotNullTo
过滤掉 null
的元素,将剩余的元素添加到传进来的集合中
val random = listOf<Any?>("蔡徐坤", 2.5f, "唱跳rap", null)
val hashSet = hashSetOf<Any>()
println(random.filterNotNullTo(hashSet)) // [2.5, 唱跳rap, 蔡徐坤]
源码实现
// 如果元素为空,则添加到传进来的集合中
public fun <C : MutableCollection<in T>, T : Any> Iterable<T?>.filterNotNullTo(destination: C): C {
for (element in this) if (element != null) destination.add(element)
return destination
}
filterNotTo
按条件过滤元素,将不满足条件的元素添加到传进来的集合中
例如
val universitySet =
setOf("厦门大学", "四川大学", "清华大学", "中山大学", "武汉理工大学", "华南理工大学", "中国传媒大学")
val lenNot4Items = hashSetOf<String>()
println(universitySet.filterNotTo(lenNot4Items) { it.length == 4 }) // [武汉理工大学, 华南理工大学, 中国传媒大学]
源码实现
// 将不满足条件的元素添加到传进来的集合中
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterNotTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (!predicate(element)) destination.add(element)
return destination
}
filterTo
按条件过滤元素,将满足条件的元素添加到传进来的集合中, 刚好跟 filterNotTo
相反
例如
@Test
fun filterToExample() {
val universitySet =
setOf("厦门大学", "四川大学", "清华大学", "中山大学", "武汉理工大学", "华南理工大学", "中国传媒大学")
val len4Items = hashSetOf<String>()
println(universitySet.filterTo(len4Items) { it.length == 4 }) // [厦门大学, 四川大学, 中山大学, 清华大学]
}
源码实现
// for循环遍历,将满足条件的添加到集合
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
return destination
}
find
按条件查找满足条件的第一个元素,如果找到就直接返回,找不到返回null
例如
val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.find { it.startsWith("A") }) // Apple
println(company.find { it.endsWith("G") }) // null
源码实现
// 内部通过firstOrNull实现
public inline fun <T> Iterable<T>.find(predicate: (T) -> Boolean): T? {
return firstOrNull(predicate)
}
findLast
按条件查找满足条件的最后一个元素,如果找到就直接返回,找不到返回null,与 find
查找顺序相反
例如
val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.findLast { it.startsWith("A") }) // Alibaba
println(company.findLast { it.endsWith("G") }) // null
源码实现
// 内部通过lastOrNull实现
public inline fun <T> List<T>.findLast(predicate: (T) -> Boolean): T? {
return lastOrNull(predicate)
}
first
返回第一个元素或者第一个满足条件的元素,如果找不到该元素就抛出 NoSuchElementException
异常,可以使用 firstOrNull
代替
例如
val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.first()) // Google
println(company.first { it.startsWith("A") }) // Apple
println(company.first { it.endsWith("G") }) // java.util.NoSuchElementException: Collection contains no element matching the predicate.
源码实现
public fun <T> List<T>.first(): T {
if (isEmpty())
throw NoSuchElementException("List is empty.")
return this[0]
}
// List 返回首个元素
// 否则使用迭代器返回
public fun <T> Iterable<T>.first(): T {
when (this) {
is List -> return this.first()
else -> {
val iterator = iterator()
if (!iterator.hasNext())
throw NoSuchElementException("Collection is empty.")
return iterator.next()
}
}
}
firstNotNullOf
返回第一个转换后的非空元素,如果没有就抛出 NoSuchElementException
异常
例如
val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
val companyMap = hashMapOf("抖音" to "字节", "快手" to "快手集团", "企鹅" to "腾讯")
println(company.firstNotNullOf { it.length }) // 6
println(company.firstNotNullOf { companyMap[it] }) // java.util.NoSuchElementException: No element of the collection was transformed to a non-null value.
源码实现
// 将转换函数传递给firstNotNullOfOrNull,如果firstNotNullOfOrNull返回空则抛出异常
public inline fun <T, R : Any> Iterable<T>.firstNotNullOf(transform: (T) -> R?): R {
return firstNotNullOfOrNull(transform) ?: throw NoSuchElementException("No element of the collection was transformed to a non-null value.")
}
firstNotNullOfOrNull
返回第一个转换后的非空元素,如果没有就返回 null
例如
val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
val companyMap = hashMapOf("抖音" to "字节", "快手" to "快手集团", "企鹅" to "腾讯")
println(company.firstNotNullOfOrNull { it.length }) // 6
println(company.firstNotNullOfOrNull { companyMap[it] }) // null
源码实现
// 获取转换之后的值,如果不是空就返回
public inline fun <T, R : Any> Iterable<T>.firstNotNullOfOrNull(transform: (T) -> R?): R? {
for (element in this) {
val result = transform(element)
if (result != null) {
return result
}
}
return null
}
firstOrNull
返回第一个元素或者第一个满足条件的元素,如果没有就返回 null
例如
val company = listOf("Google", "Microsoft", "IBM", "Apple", "Yahoo", "Alibaba", "Baidu")
println(company.firstOrNull()) // Google
println(company.firstOrNull { it.startsWith("A") }) // Apple
println(company.firstOrNull { it.endsWith("G") }) // null
源码实现
// 对list单独处理,其他都是通过迭代器处理
public fun <T> Iterable<T>.firstOrNull(): T? {
when (this) {
is List -> {
if (isEmpty())
return null
else
return this[0]
}
else -> {
val iterator = iterator()
if (!iterator.hasNext())
return null
return iterator.next()
}
}
}
// for循环遍历
public inline fun <T> Iterable<T>.firstOrNull(predicate: (T) -> Boolean): T? {
for (element in this) if (predicate(element)) return element
return null
}
flatMap
将集合中的元素根据转换函数得到新的值,并且将所有值铺平到新的集合中。跟 map
不同的是,flatMap
的转换函数需要返回一个新的集合,并且会将转换后的值都铺平到集合中,所以如果有嵌套的集合转换成单层的集合时请使用 flatMap
例如
val intList = listOf(1, 2, 3, 4, 5)
val nestList = listOf(listOf(1, 2), listOf(3, 4), listOf(5, 6, 7))
println(intList.flatMap { listOf(it + it, it * it, it * it * it) }) // [2, 1, 1, 4, 4, 8, 6, 9, 27, 8, 16, 64, 10, 25, 125]
println(nestList.flatMap { item -> item.map { it * it } }) // [1, 4, 9, 16, 25, 36, 49]
源码实现
// flatMapTo到ArrayList
public inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R> {
return flatMapTo(ArrayList<R>(), transform)
}
flatMapIndexed
跟 flatMap
一样,不过 lambda
中多了个 index
索引参数
例如
val intList = listOf(1, 2, 3, 4, 5)
println(intList.flatMapIndexed { index, it -> listOf(it + it, it * it, it * it * it) })
源码实现
// flatMapIndexedTo到ArrayList
public inline fun <T, R> Iterable<T>.flatMapIndexed(transform: (index: Int, T) -> Iterable<R>): List<R> {
return flatMapIndexedTo(ArrayList<R>(), transform)
}
flatMapIndexedTo
flatMapIndexed
最终实现的源码,将转换后的元素添加到传进来的集合中
例如
val intList = listOf(1, 2, 3, 4, 5)
val hashSet = hashSetOf<Int>()
println(intList.flatMapIndexedTo(hashSet) { index, it -> listOf(it + it, it * it, it * it * it) }) // [16, 64, 1, 2, 4, 6, 8, 9, 25, 10, 27, 125]
println(hashSet) // [16, 64, 1, 2, 4, 6, 8, 9, 25, 10, 27, 125]
源码实现
// 遍历整个集合,将转换函数获得的集合添加到传进来的集合中
// checkIndexOverflow是防止数组越界
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapIndexedTo(destination: C, transform: (index: Int, T) -> Iterable<R>): C {
var index = 0
for (element in this) {
val list = transform(checkIndexOverflow(index++), element)
destination.addAll(list)
}
return destination
}
flatMapTo
flatMap
最终实现的源码,将转换后的元素添加到传进来的集合中
val nestList = listOf(listOf(1, 2), listOf(3, 4), listOf(5, 6, 7))
val destSet = hashSetOf<Int>()
println(nestList.flatMapTo(destSet) { item -> item.map { it * it } })
println(destSet)
源码实现
// 遍历整个集合,将转换函数获得的集合添加到传进来的集合中
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapTo(destination: C, transform: (T) -> Iterable<R>): C {
for (element in this) {
val list = transform(element)
destination.addAll(list)
}
return destination
}
fold
对每个元素进行操作,返回积累的总值。集合为空则返回初始值
例如需要计算1到5的总和或者平方和
val intList = listOf(1, 2, 3, 4, 5)
println(intList.fold(0) { prev, item -> prev + item }) // 15
println(intList.fold(0) { prev, item -> prev + item * item }) // 55
源码实现
// 遍历整个集合,将上一个的结果传到下一个的遍历中,需要传入初始值
public inline fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) -> R): R {
var accumulator = initial
for (element in this) accumulator = operation(accumulator, element)
return accumulator
}
foldIndexed
跟 fold
一样,只是 lambda
中多了个 index
索引参数
val intList = listOf(1, 2, 3, 4, 5)
println(intList.foldIndexed(0) { index, prev, item -> prev + item })
println(intList.foldIndexed(0) { index, prev, item -> prev + item * item })
源码实现
// 遍历整个集合,将上一个的结果传到下一个的遍历中,需要传入初始值
public inline fun <T, R> Iterable<T>.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R {
var index = 0
var accumulator = initial
for (element in this) accumulator = operation(checkIndexOverflow(index++), accumulator, element)
return accumulator
}
foldRight
对每个元素进行操作,返回积累的总值。与 fold
不同的是,foldRight
是从右到左积累,fold
是从左到右积累。因为是有顺序的,所以只作用于 list
val intList = listOf(1, 2, 3, 4, 5)
println(intList.foldRight(0) { prev, item -> prev + item }) // 15
源码实现
// 通过listIterator迭代整个list,如果为空返回默认值
public inline fun <T, R> *List*<T>.foldRight(initial: R, operation: (T, acc: R) -> R): R {
var accumulator = initial
if (!isEmpty()) {
val iterator = listIterator(size)
while (iterator.hasPrevious()) {
accumulator = operation(iterator.previous(), accumulator)
}
}
return accumulator
}
foldRightIndexed
跟 foldRight
一样,只是 lambda
中多了个 index
索引参数
val intList = listOf(1, 2, 3, 4, 5)
println(intList.foldIndexed(0) { index, prev, item -> prev + item })
源码实现
// // 通过listIterator迭代整个list,如果为空返回默认值
public inline fun <T, R> *List*<T>.foldRightIndexed(initial: R, operation: (index: Int, T, acc: R) -> R): R {
var accumulator = initial
if (!isEmpty()) {
val iterator = listIterator(size)
while (iterator.hasPrevious()) {
val index = iterator.previousIndex()
accumulator = operation(index, iterator.previous(), accumulator)
}
}
return accumulator
}
forEach
forEach
遍历,lambda
返回每一个元素
val intList = listOf(1, 2, 3, 4, 5)
intList.forEach {
println(it)
}
// 1 2 3 4 5
源码实现
// for循环遍历
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
forEachIndexed
跟 forEach
一样,只是 lambda
中多了个 index
索引参数
源码实现
// for循环遍历
public inline fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit {
var index = 0
for (item in this) action(checkIndexOverflow(index++), item)
}
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓
PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题