Kotlin 수집 연산자

집합 연산자

  • 연산자 1 설정(이니셜 a - f)

이 문서 Kotlin에서는 컬렉션의 연산자를 소개합니다. Kotlin이 문서에서 사용된 버전은 1.8.10입니다.

all

컬렉션의 모든 요소가 요구 사항을 충족하는지 확인하고 반환 값은Boolean

예를 들어 문자열의 길이가 4보다 큰지 여부를 확인해야 합니다.

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

源码实现

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

any

컬렉션에 조건을 만족하는 요소가 있는지 확인하고 반환 값은Boolean

예를 들어 185cm 이상의 8팩 복근을 가진 남동생이 있는지 판단해야 합니다.

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

源码实现

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

contains

세트에 요소가 포함되어 있는지 여부로, 다음과 같이 반환됩니다.Boolean

예를 들어, 학급에 Cai Xukun이라는 아이가 있는지 확인하려면

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던지고 , 원래 컬렉션을 반환하고, 빈 컬렉션을 반환합니다.IllegalArgumentExceptionn = 0n >= 集合长度

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

반대 dropdropLast꼬리에서 필터링하는 것입니다. 예외를 n < 0던지고 , 원래 컬렉션을 반환하고, 빈 컬렉션을 반환합니다.IllegalArgumentExceptionn = 0n >= 集合长度

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입니다.filterIndexedintindex

예를 들어 컬렉션을 싱글과 더블로 나눕니다.

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

조건에 따라 조건을 만족하는 마지막 요소를 찾아 찾으면 바로 리턴하고 찾지 못하면 find검색 순서와 반대인 null을 리턴한다.

예를 들어

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

변환된 null이 아닌 첫 번째 요소를 반환하거나 없는 경우 NoSuchElementException예외를 throw합니다.

예를 들어

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이 아닌 첫 번째 요소를 반환하거나 없음을 반환합니다.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입니다 . 순차적이기 때문에foldRightfoldlist

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

마침내

건축가가 되고 싶거나 연봉 2~3만 대를 돌파하고 싶다면 코딩과 비즈니스에 국한하지 말고 모델을 선택하고 확장하고 프로그래밍 사고를 향상시킬 수 있어야 합니다. 또한 좋은 진로계획도 매우 중요하고, 배움의 습관도 매우 중요하지만 가장 중요한 것은 인내할 수 있는 것입니다.

방향이 없는 경우 여기에서 Ali의 수석 설계자가 작성한 "안드로이드의 8대 주요 모듈에 대한 고급 노트" 세트를 공유하여 복잡하고 흩어져 있고 조각난 지식을 체계적으로 정리할 수 있도록 도와드립니다. 안드로이드 개발의 다양한 지식 포인트를 체계적이고 효율적으로 마스터할 수 있습니다.

이미지

우리가 일반적으로 읽는 조각난 콘텐츠와 비교할 때 이 노트의 지식 포인트는 더 체계적이고 이해하고 기억하기 쉽고 지식 시스템에 따라 엄격하게 배열됩니다.

한 번의 클릭과 세 개의 링크로 지원하는 모든 사람을 환영합니다.기사의 정보가 필요한 경우 기사 끝에 있는 CSDN 공식 인증 WeChat 카드를 직접 스캔하여 무료로 얻을 수 있습니다↓↓↓

추신: 그룹에 ChatGPT 로봇도 있어 작업이나 기술적인 질문에 답할 수 있습니다.

추천

출처blog.csdn.net/weixin_43440181/article/details/131379631