调集操作符
今天介绍下 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] 抛出数组越界反常,能够运用 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
留意 这儿的 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
依据分组函数对调集进行分组,回来分组成果 Map
,Map
中的 key
类型由分组函数决议, value
的类型是 List
groupBy
两个参数的函数会对调集元素的值进行转化,终究增加到 Map
中
例如咱们需求对字符串按长度进行分组,那么 Map
中 key
便是 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
是获取第一个出现该元素的索引 ,lastIndexOf
与 indexOf
刚好相反
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]]
能够很明显看到 map
和 flatMap
的差异,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)
}
random
和 randomOrNull
随机获取某个元素,与咱们常用的 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
,只效果于 MutableList
,MutableList
与 List
的差异?MutableList
能够 curd
,List
只能获取和遍历
例如依据姓名或许年纪排序
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