Kotlin集合函数式API解析_上

一、Kotlin集合介绍

设计初衷

Kotlin中将集合设计为可变和可读两种,设计的初衷是为了在实际开发过程中数据的行为逻辑更容易让人理解。

如果传递的参数是可变集合,一般表明函数内部涉及到集合修改操作。同理,如果传递只读集合参数,说明函数内部只涉及集合读取操作。

集合分类

Kotlin集合接口图表如下所示

其中可变集合MutableXXX与只读集合的关系是继承关系

IterableMutableIterable接口分别是只读和可变集合的父接口。

Collection继承IterableListSet接口继承自CollectionMap接口是单独的接口,MutableMap接口是继承自Map.

Java中的ArrayList类和HashSet类实际上对应Kotlin中的MutableListMutableSet集合接口的实现类。

二、函数式API操作符分类

这里简单对Kotlin集合中常见的函数式API操作符进行归纳分类

  • 筛选过滤类

    主要为slicefilter操作符系列,drop操作符系列,take操作符系列,distinct操作符系列

  • 并集类

    主要为anyallcountnone操作符系列,fold操作符系列,forEach操作符系列,maxmin操作符系列,reduce操作符系列、sum操作符系列

  • 映射类

    主要为flatMap系列,groupBy系列,map系列

  • 元素类

    主要为elementAt系列,first系列,find系列,indexOf系列,last系列,single系列,component系列

  • 排序类

    主要为reversesort系列

  • 生成类

    主要为partitionplus系列,zip系列

三、筛选过滤类操作符

3.1 slice系列

slice(indices: IntRange)slice(indices: Iterable<Int>)

  • 基本定义

    slice操作符可以取集合中一部分元素或者某个元素,最后组合成一个新元素

    slice(indices: IntRange):指定切片的起始位置和终止位置,将范围内的元素切出加入到新集合

    slice(indices: Iterable<Int>):指定下标分别切出对应的元素,放入新集合中

  • 源码定义与解析

    public fun <T> List<T>.slice(indices: IntRange): List<T> {
        if (indices.isEmpty()) return listOf()
        return this.subList(indices.start, indices.endInclusive + 1).toList()
    }
    
    
    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
    }
    复制代码

    slice函数是List\<T>的一个扩展函数,最终返回一个list集合。

    接收IntRange对象的函数拿到对应的startend位置,利用subList拿到子集合返回

    接收Iterable下标集合函数,内部创建一个新的集合对象,遍历原集合,将下标集合中的元素加入到新创建的集合中,返回这个新集合

  • 使用示例

    fun main(args: Array<String>) {
        val numberList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
    
        val newNumberList1 = numberList.slice(IntRange(3, 6))
        print("slice by IntRange: ")
        newNumberList1.forEach {
            print("$it ")	//打印结果:4 5 6 7
        }
    
        println()
    
        val newNumberList2 = numberList.slice(listOf(1, 3, 7))
        print("slice by iterator index: ")
        newNumberList2.forEach {
            print("$it ")	//打印结果:2 4 8
        }
    }
    复制代码

3.2 filter系列

filter(predicate: (T) -> Boolean)

filterTo(destination: C, predicate: (T) -> Boolean)

  • 基本定义

    根据用户定义的条件筛选集合中的数据,由此产生一个新的集合,该集合是原集合的子集。

  • 源码定义与解析

    public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
        return filterTo(ArrayList<T>(), predicate)
    }
    
    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
    }
    复制代码

    filter()是一个Iterable/<T>的扩展函数且是内联函数。filter内部调用了filterTo函数,传入新创建的ArrayList可变集合对象,继续把lambda表达式作为参数传递到filterTo函数中,在filterTo函数实现真正过滤操作。

    传入的lambda表达式predicate实际上就是外部调用者传入的过滤条件,内部利用一个for循环进行筛选判断符合lambda表达式条件的,就添加到新集合对象中,最后返回这个新集合对象。

  • 使用示例

    filter()适用于:从一个集合筛选出符合条件的元素,并以一个新集合返回。

    fun main(args: Array<String>) {
        val numberList = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
        val newNumberList = numberList.filter { number ->
            number % 2 == 0//筛选出偶数
        }
        newNumberList.forEach { print("$it   ")}	
    }
    /******打印结果******/
    0 2 4 6 8 10
    复制代码

    filterTo()适用于:从多个集合筛选出符合条件的元素,并最终用一个集合进行收集从每个集合筛选出的元素。

    fun main(args: Array<String>) {
        val numberList1 = listOf(23, 65, 14, 57, 99, 123, 26, 15, 88, 37, 56)
        val numberList2 = listOf(13, 55, 24, 67, 93, 137, 216, 115, 828, 317, 16)
        val numberList3 = listOf(20, 45, 19, 7, 9, 3, 26, 5, 38, 75, 46)
    
        //filterTo的destination是一个可变集合类型,所以这里使用的mutableListOf初始化
        val newNumberList = mutableListOf<Int>().apply {
            numberList1.filterTo(this) {
                it % 2 == 0
            }
            numberList2.filterTo(this) {
                it % 2 == 0
            }
            numberList3.filterTo(this) {
                it % 2 == 0
            }
        }
    
        print("从三个集合筛选出的偶数集合: ")
        newNumberList.forEach {
            print("$it   ")
        }
    }
    /******打印结果******/
    14  26  88  56  24  ......
    复制代码

filterIndexed(predicate: (index: Int, T) -> Boolean)

filterIndexedTo(destination: C, predicate: (index: Int, T) -> Boolean)

  • 基本定义

    filterIndexedfilter的区别在于其筛选条件的lambda表达式多暴露了一个参数,即元素在集合中的index。外部可以拿到这个元素以及这个元素的index,适合需要集合元素index参与筛选条件的case

  • 源码定义与解析

    public inline fun <T> Iterable<T>.filterIndexed(predicate: (index: Int, T) -> Boolean): List<T> {
        return filterIndexedTo(ArrayList<T>(), predicate)
    }
    
    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
    }
    
    public inline fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit {
        var index = 0
        for (item in this) action(checkIndexOverflow(index++), item)
    }
    复制代码

    filterIndexed实现涉及到filterIndexedToforEachIndexed

    filterIndexed是一个Iterable\<T>的扩展函数且是一个内联函数,实现原理与filter类似,其中index实际上是forEachIndexed内部的一个迭代自增计数器,在内部每次迭代,计数器就会自增一次,且把这个index回调到外部

  • 使用场示例

    filterIndexed()适用于:需要集合元素index参与筛选条件

    fun main(args: Array<String>) {
        val numberList = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
        val newNumberList = numberList.filterIndexed { index, number ->
            index < 5 && number % 2 == 0 //筛选出集合中前五个元素中是偶数的数
        }
        newNumberList.forEach {
            print("$it  ")
        }
    }
    /******打印结果******/
    0 2 4
    复制代码

    filterIndexedTo()适用于:从多个集合筛选出符合条件的元素,筛选条件需要index,并最终用一个集合进行收集从每个集合筛选出的元素。

    val numbers: List<Int> = listOf(0, 1, 2, 3, 4, 8, 6)
    val numbersOnSameIndexAsValue = mutableListOf<Int>()
    println(numbersOnSameIndexAsValue) // []
    numbers.filterIndexedTo(numbersOnSameIndexAsValue) { index, i -> index == i }
    println(numbersOnSameIndexAsValue) 
    /******打印结果******/
    [0, 1, 2, 3, 4, 6]
    复制代码

filterIsInstance()

filterIsInstanceTo(destination: C)

  • 基本定义

    filterIsInstance操作符:从集合中筛选出instance某个特定类型元素,并把该元素强转成该类型,最后返回这些元素集合。

  • 源码定义与解析

    public inline fun <reified R> Iterable<*>.filterIsInstance(): List<@kotlin.internal.NoInfer R> {
        return filterIsInstanceTo(ArrayList<R>())
    }
    
    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
    }
    复制代码

    filterIsInstance操作符是一个扩展函数,借助filterIsInstanceTo实现。

    通过外部传入的R泛型,创建一个R泛型的ArrayList可变集合,用于收集原集合中instance R类型的元素。filterIsInstanceTo内部是遍历集合然后利用is判断属于R类型的元素就加入到集合中,最后返回该集合。

  • 使用示例

    filterInstance()适用于:一个抽象类集合中还有多种子类型的元素,可以很方便筛选对应子类型的元素,并组成一个集合返回。

    abstract class Animal(var name: String, var age: Int){
        abstract fun eatFood(): String
    }
    class Bird(name: String, age: Int): Animal(name, age){
        override fun eatFood() = "bird eat worm"
    }
    class Cat(name: String, age: Int) : Animal(name, age) {
        override fun eatFood() = "Cat eat Fish"
    }
    class Dog(name: String, age: Int) : Animal(name, age) {
        override fun eatFood() = "dog eat bone"
    }
    
    fun main(args: Array<String>) {
        val animalList: List<Animal> = listOf(Bird(name = "Bird1", age = 12),
                Cat(name = "Cat1", age = 18),
                Cat(name = "Cat3", age = 20),
                Dog(name = "Dog2", age = 8),
                Cat(name = "Cat2", age = 8),
                Bird(name = "Bird2", age = 14),
                Bird(name = "Bird3", age = 16),
                Dog(name = "Dog1", age = 18)
        )
    
        //筛选出所有Dog的信息,借助filterIsInstance操作符
        animalList.filterIsInstance<Dog>().forEach { println("${it.name} is ${it.age} years old, and ${it.eatFood()}") }
    }
    复制代码

    等价于:

    //筛选出个所有Dog的信息,借助filter和map操作符
        animalList.filter {
            it is Dog
        }.map {
            it as Dog
        }.forEach {
            println("${it.name} is ${it.age} years old, and ${it.eatFood()}")
        }
    复制代码

    filterInstanceTo适用于筛选多个集合的情况。

filterNot(predicate: (T) -> Boolean)

filterNotTo(destination: C, predicate: (T) -> Boolean)

  • 基本定义

    从一个集合筛选出符合条件之外的元素,并以一个新集合返回。它是filter操作符取反操作。

  • 源码定义与解析

    public inline fun <T> Iterable<T>.filterNot(predicate: (T) -> Boolean): List<T> {
        return filterNotTo(ArrayList<T>(), predicate)
    }
    
    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
    }
    复制代码

  • 使用示例

    使用场景就是filter使用的取反条件使用,当然你也可以继续使用filter操作符,并且筛选条件为取反条件。

    示例参见filter操作符

filterNotNull()

filterNotNullTo(destination: C)

  • 基本定义

    filterNotNull操作符可以过滤集合中为null的元素。同理filterNotNullTo才是真正过滤操作,但是需要从外部传入一个可变集合。

  • 源码定义与解析

    public fun <T : Any> Iterable<T?>.filterNotNull(): List<T> {
        return filterNotNullTo(ArrayList<T>())
    }
    
    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
    }
    复制代码

    filterNotNull是集合的扩展函数,该集合中的元素是可null的T泛型,筛选条件即判断是否为null

    filterNotNull传入一个可变集合,然后在filterNotNullTo内部判断把null的元素直接过滤,其他元素就会被加入传入的可变集合中。

  • 使用场景与示例

    filterNotNull()适用于: 过滤掉集合中为null的元素,最后返回一个不含null的元素集合

    filterNotNullTo()适用于: 在外部传入一个可变的集合,然后过滤多个集合中为null的元素,最后将这些元素放入可变集合中,并返回这个集合。

    fun main(args: Array<String>) {
        val animalList: List<Animal?> = listOf(Bird(name = "Bird1", age = 12),
                Cat(name = "Cat1", age = 18),
                Cat(name = "Cat3", age = 20),
                Dog(name = "Dog2", age = 8),
                null,
                Bird(name = "Bird2", age = 14),
               	null,
                Dog(name = "Dog1", age = 18)
        )
        animalList.filterNotNull().forEach { println("${it.name} is ${it.age} years old and it ${it.eatFood()}") }
    }
    复制代码

3.3 drop系列

drop(n: Int)

  • 基本定义

    根据传入数值n,表示从左到右顺序地删除n个集合中的元素,并返回集合中剩余的元素。

  • 源码定义与解析

    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()
    }
    复制代码

  • 使用示例

    drop操作符适用于:把集合元素去除一部分,drop是顺序地删除,n则表示顺序删除几个元素,最后返回剩余元素集合

    fun main(args: Array<String>) {
        val numberList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
        numberList.drop(5).forEach { print("$it   ") }
    }
    /******打印结果******/
    6 7 8 9
    复制代码

dropLast(n: Int)

  • 基本定义

    根据传入数值n,表示从右到左倒序地删除n个集合中的元素,并返回集合中剩余的元素。

  • 源码定义与解析

    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))
    }
    
    
    //这是一个Int类型的扩展函数,用于判断某个值是否大于传入默认最小值,如果大于就直接返回这个值,否则返回这个默认最小值
    public fun Int.coerceAtLeast(minimumValue: Int): Int {
        return if (this < minimumValue) minimumValue else this
    }
    
    
    public fun <T> Iterable<T>.take(n: Int): List<T> {
        require(n >= 0) { "Requested element count $n is less than zero." }
        if (n == 0) return emptyList()
        if (this is Collection<T>) {
            if (n >= size) return toList()
            if (n == 1) return listOf(first())
        }
        var count = 0
        val list = ArrayList<T>(n)
        for (item in this) {
            list.add(item)
            if (++count == n)
                break
        }
        return list.optimizeReadOnlyList()
    }
    复制代码

    这是一个List/<T>的扩展函数,涉及到coerceAtLeasttake,其是通过调用take来实现

    takeIterable/<T>的扩展函数

  • 使用示例

    dropLast操作符使用场景与drop相反,整体作用与其相似

    fun main(args: Array<String>) {
        val strList = listOf("kotlin", "java", "javaScript", "C", "C++", "python", "Swift", "Go", "Scala")
        strList.dropLast(3).forEach { print("$it   ") }
    }
    /******打印结果******/
    kotlin java javaScript C C++ paython
    复制代码

dropWhile(predicate: (T) -> Boolean)

  • 基本定义

    从集合的第一项开始去掉满足条件元素,这样操作一直持续到出现第一个不满足条件元素出现为止,返回剩余元素(可能剩余元素有满足条件的元素)

  • 源码定义与解析

    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
    }
    复制代码

  • 使用示例

    dropWhile操作符适用于:去掉集合中前半部分具有相同特征的元素场景。

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx","python", "Swift", "Go", "Scala")
        strList.dropWhile { it.startsWith("java") }.forEach { print("$it  ") }
    }
    /******打印结果******/
    kotlin C C++ javaFx python Swift Go Scala
    复制代码

dropLastWhile(predicate: (T) -> Boolean)

  • 基本定义

    从集合的最后一项开始去掉满足条件元素,这样操作一直持续到出现第一个不满足条件元素出现为止,返回剩余元素(可能剩余元素有满足条件的元素)

  • 源码定义与解析

    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()
    }
    复制代码

  • 使用示例

    dropLastWhile操作符使用场景与dropWhile类似,不过删除元素顺序不一样

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        strList.dropLastWhile { it.startsWith("S") }.forEach { print("$it  ") }
    }
    /******打印结果******/
    java javaScript kotlin C C++ javaFx python Go
    复制代码

3.4 take系列

take(n: Int)

  • 基本定义

    从原集合的第一项开始顺序取集合的元素,取n个元素,最后返回取出这些元素的集合。换句话说就是取集合前n个元素组成新的集合返回。

  • 源码定义与解析

    public fun <T> Iterable<T>.take(n: Int): List<T> {
        require(n >= 0) { "Requested element count $n is less than zero." }
        if (n == 0) return emptyList()	//取0个元素集合,返回空集合
        if (this is Collection<T>) {
            if (n >= size) return toList()		//如果取元素集合大小大于或等于原集合大小,就直接返回原集合
            if (n == 1) return listOf(first())	//取一个元素,就是集合的first()
        }
        var count = 0
        val list = ArrayList<T>(n)
        for (item in this) {	//遍历集合
            list.add(item)
            if (++count == n)
                break
        }
        return list.optimizeReadOnlyList()
    }
    复制代码

  • 使用示例

    take操作符适用于:顺序从第一项开始取集合中的子集

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        strList.take(2).forEach { print("$it ") }
    }
    /*******打印结果******/
    java javaScript
    复制代码

takeLast(n: Int)

  • 基本定义

    从原集合的最后一项开始倒序取集合的元素,取n个元素,最后返回取出这些元素的集合。

  • 源码定义与解析

    public fun <T> List<T>.takeLast(n: Int): List<T> {
        require(n >= 0) { "Requested element count $n is less than zero." }
        if (n == 0) return emptyList()	//取0个元素,返回空集合
        val size = size
        if (n >= size) return toList()
        if (n == 1) return listOf(last())
        val list = ArrayList<T>(n)
        if (this is RandomAccess) {//RandomAccess是一个集合标记接口,如果集合类是RandomAccess的实现,则尽量用index下标 来遍历而不要用Iterator迭代器来遍历,在效率上要差一些。反过来,如果List是Sequence List,则最好用迭代器来进行迭代。
            for (index in size - n until size)
                list.add(this[index])
        } else {
            for (item in listIterator(size - n))
                list.add(item)
        }
        return list
    }
    复制代码

  • 使用示例

    takeLast操作符适用于:倒序从最后一项开始取集合中子集合

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        strList.takeLast(2).forEach { print("$it ") }
    }
    /******打印结果******/
    Swift Scala
    复制代码

takeLastWhile(predicate: (T) -> Boolean)

  • 基本定义

    从集合的最后一项开始取出满足条件元素,这样操作一直持续到出现第一个不满足条件元素出现为止,暂停取元素,返回取出元素的集合。

  • 源码定义与解析

    public inline fun <T> List<T>.takeLastWhile(predicate: (T) -> Boolean): List<T> {
        if (isEmpty())
            return emptyList()
        val iterator = listIterator(size)	//表示从集合index = size开始迭代,那么size - 1也是最后一个元素,也即是迭代器的previous,也就是从集合尾部开始向头部迭代
        while (iterator.hasPrevious()) {
            if (!predicate(iterator.previous())) {	//也是从最后一项开始遇到第一个不符合条件的元素,不进入以下操作
                iterator.next()
                val expectedSize = size - iterator.nextIndex()	//符合条件元素集合的expectedSize等于原集合size与当前下一个元素的index的差值
                if (expectedSize == 0) return emptyList()
                return ArrayList<T>(expectedSize).apply {	//拿到符合条件元素集合size,创建expectedSize大小新集合,并把迭代器中的元素遍历加入到新集合中
                    while (iterator.hasNext())
                        add(iterator.next())
                }
            }
        }
        return toList()
    }
    复制代码

  • 使用示例

    takeLastWhile操作符适用于:取出集合中后半部分具有相同特征的元素场景

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        strList.takeLastWhile { it.startsWith("S") }.forEach { print("$it ") }
    }
    /******打印结果******/
    Swift Scala
    复制代码

takeWhile(predicate: (T) -> Boolean)

  • 基本定义

    从集合的第一项开始取出满足条件元素,这样操作一直持续到出现第一个不满足条件元素出现为止,暂停取元素,返回取出元素的集合。

  • 源码定义与解析

    public inline fun <T> Iterable<T>.takeWhile(predicate: (T) -> Boolean): List<T> {
        val list = ArrayList<T>()
        for (item in this) {
            if (!predicate(item))	//不符合传入条件就跳出循环
                break
            list.add(item)
        }
        return list
    }
    复制代码

  • 使用示例

    takeshiWhile操作符适用于:取出集合中前半部分具有相同特征的元素场景

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        strList.takeWhile { it.startsWith("java") }.forEach { print("$it ") }
    }
    /******打印结果******/
    java javaScript
    复制代码

3.5 distinct系列

distinct()

  • 基本定义

    去除集合中的重复元素

  • 源码定义与解析

    public fun <T> Iterable<T>.distinct(): List<T> {
        return this.toMutableSet().toList()
    }
    
    public fun <T> Iterable<T>.toMutableSet(): MutableSet<T> {
        return when (this) {
            is Collection<T> -> LinkedHashSet(this)
            else -> toCollection(LinkedHashSet<T>())
        }
    }
    复制代码
  • 使用示例

    distinct操作符适用于:去除集合中的重复元素

    fun main(args: Array<String>) {
        val strList = listOf<String>("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        val numberList = listOf("111","222","333","444","555","111","333")
        print(numberList.distinct())
    }
    /******打印结果******/
    [111, 222, 333, 444, 555]
    复制代码

distinctBy(selector: (T) -> K)

  • 基本定义

    根据操作元素后的结果去除重复元素

  • 源码定义与解析

    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
    }
    复制代码
  • 使用示例

    distinctBy操作符适用于:根据元素操作的结果进行集合元素去重

    fun main(args: Array<String>) {
        val strList = listOf<String>("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        val numberList = listOf("111","212","332","444","555","111")
        print(numberList.distinctBy {
            it.toInt() % 111
        })
    }
    /******打印结果******/
    [111, 212, 332]
    复制代码

四、并集类操作符

4.1 any、all、count、none系列

any()

  • 基本定义

    判断是不是一个集合,若是,则再判断集合是否为空。若为空则返回false,反之返回true。若不是集合,则返回hasNext

  • 源码定义与解析

    public fun <T> Iterable<T>.any(): Boolean {
        if (this is Collection) return !isEmpty()
        return iterator().hasNext()
    }
    复制代码
  • 使用示例

    any()操作符适用于:判断是否是一个集合

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        print(strList.any())
    }
    /*******打印结果*******/
    true
    复制代码

any(predicate: (T) -> Boolean)

  • 基本定义

    判断集合中是否存在满足条件的元素。若存在则返回true,反之返回false

  • 源码定义与解析

    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
    }
    复制代码
  • 使用示例

    any{}操作符适用于:判断一个集合是否存在满足条件的元素

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        print(strList.any { it.startsWith("py") })
    }
    复制代码

all(predicate: (T) -> Boolean)

  • 基本定义

    判断集合中的所有元素是否都满足条件。若是则返回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类似

  • 使用示例

    all操作符适用场景与any相反,判断集合中所有元素是否都满足条件

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        print(strList.all { it.startsWith("py") })
    }
    /******打印结果******/
    false
    复制代码

count()

count(predicate: (T) -> Boolean)

  • 基本定义

    返回集合中的元素个数或查询集合中满足条件的元素个数

  • 源码定义与解析

    public fun <T> Iterable<T>.count(): Int {
        if (this is Collection) return size
        var count = 0
        for (element in this) checkCountOverflow(++count)
        return count
    }
    
    public inline fun <T> Collection<T>.count(): Int {
        return size
    }
    
    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
    }
    复制代码
  • 使用示例

    count操作符适用于:查询集合元素个数或集合中满足条件的元素个数

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        println(strList.count())
        println(strList.count { it.startsWith("java") })
    }
    /******打印结果******/
    10
    3
    复制代码

none()

none(predicate: (T) -> Boolean)

  • 基本定义

    如果一个集合是空集合,返回true或者集合中没有满足条件的元素,则返回true

  • 源码定义与解析

    public fun <T> Iterable<T>.none(): Boolean {
        if (this is Collection) return isEmpty()
        return !iterator().hasNext()
    }
    
    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
    }
    复制代码

    实现方式与any类似

  • 使用示例

    none操作符适用场景与any相反

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        println(strList.none())
        println(strList.none { it.startsWith("java") })
    }
    复制代码

4.2 fold系列

fold(initial: R, operation: (acc: R, T) -> R)

  • 基本定义

    在一个初始值的基础上从第一项到最后一项通过一个函数累计所有的元素。

  • 源码定义与解析

    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
    }
    复制代码
  • 使用示例

    fold操作符适用于:给定初始值,按照某个函数对集合中的每个元素进行累计

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        println(strList.fold("php"){result, element -> "$result$element"})
    }
    /******打印结果******/
    phpjavajavaScriptkotlinCC++javaFxpythonGoSwiftScala
    复制代码

foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R)

  • 基本定义

    在一个初始值的基础上,从第一项到最后一项通过一个函数累计所有的元素,该函数的参数可以包含元素索引

  • 源码定义与解析

    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
    }
    复制代码
  • 使用示例

    foldIndexed操作符适用场景与fold相似

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        println(strList.foldIndexed("php"){index,result, element -> "$result $element$index"})
    }
    /******打印结果******/
    php java0 javaScript1 kotlin2 C3 C++4 javaFx5 python6 Go7 Swift8 Scala9
    复制代码

foldRight(initial: R, operation: (T, acc: R) -> R)

  • 基本定义

    在一个初始值的基础上,从最后项到第一项通过一个函数累计所有的元素,与fold类似

  • 源码定义与解析

    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
    }
    复制代码
  • 使用示例

    foldRight操作符适用场景与fold类似,不过是从最后一项开始累计

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        println(strList.foldRight("php"){element, result -> "$result $element"})
    }
    /******打印结果******/
    php Scala Swift Go python javaFx C++ C kotlin javaScript java
    复制代码

foldRightIndexed(initial: R, operation: (index: Int, T, acc: R) -> R)

  • 基本定义

    在一个初始值的基础上,从最后一项到第一项通过一个函数累计所有的元素,该函数的参数可以包含元素索引

  • 源码定义与解析

    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
    }
    复制代码
  • 使用示例

    foldRightIndexed操作符使用场景与foldIndexed类似

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        println(strList.foldRightIndexed("php"){index,element, result -> "$result $element$index"})
    }
    /******打印结果******/
    php Scala9 Swift8 Go7 python6 javaFx5 C++4 C3 kotlin2 javaScript1 java0
    复制代码

4.3 forEach系列

forEach(action: (T) -> Unit)

  • 基本定义

    遍历元素

  • 源码定义与解析

    /**
     * Performs the given [action] on each element.
     */
    @kotlin.internal.HidesMembers
    public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
        for (element in this) action(element)
    }
    复制代码
  • 使用示例

    forEach操作符适用于:集合元素的遍历操作符

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        strList.forEach{
            print("$it ")
        }
    }
    /******打印结果******/
    java javaScript kotlin C C++ javaFx python Go Swift Scala
    复制代码

forEachIndexed(action: (index: Int, T) -> Unit)

  • 基本定义

    遍历元素,可获得集合中元素的下标

  • 源码定义与解析

    /**
     * Performs the given [action] on each element, providing sequential index with the element.
     * @param [action] function that takes the index of an element and the element itself
     * and performs the desired action on the element.
     */
    public inline fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit {
        var index = 0
        for (item in this) action(checkIndexOverflow(index++), item)
    }
    复制代码
  • 使用示例

    forEachIndexed操作符适用于:集合中带元素下标的遍历操作

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        strList.forEachIndexed { index, s -> print("$s$index ") }
    }
    /******打印结果******/
    java0 javaScript1 kotlin2 C3 C++4 javaFx5 python6 Go7 Swift8 Scala9 
    复制代码

4.4 max、min系列

max()

  • 基本定义

    获取集合中最大的元素,若为空元素集合,则返回null

  • 源码定义与解析

    /**
     * Returns the largest element or `null` if there are no elements.
     * 
     * If any of elements is `NaN` returns `NaN`.
     */
    @SinceKotlin("1.1")
    public fun Iterable<Float>.max(): Float? {
        val iterator = iterator()
        if (!iterator.hasNext()) return null
        var max = iterator.next()
        if (max.isNaN()) return max
        while (iterator.hasNext()) {
            val e = iterator.next()
            if (e.isNaN()) return e
            if (max < e) max = e
        }
        return max
    }
    
    
    @SinceKotlin("1.1")
    public fun Iterable<Double>.max(): Double? {
        val iterator = iterator()
        if (!iterator.hasNext()) return null
        var max = iterator.next()
        if (max.isNaN()) return max
        while (iterator.hasNext()) {
            val e = iterator.next()
            if (e.isNaN()) return e
            if (max < e) max = e
        }
        return max
    }
    
    
    public fun <T : Comparable<T>> Iterable<T>.max(): T? {
        val iterator = iterator()
        if (!iterator.hasNext()) return null
        var max = iterator.next()
        while (iterator.hasNext()) {
            val e = iterator.next()
            if (max < e) max = e
        }
        return max
    }
    复制代码
  • 使用示例

    max操作符适用于:获取集合中最大的元素,若为空元素集合,则返回null

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        println(strList.max())
    }
    复制代码

maxBy(selector: (T) -> R)

  • 基本定义

    获取方法处理后返回结果最大值对应那个元素的初始值,如果没有则返回

  • 源码定义与解析

    /**
     * Returns the first element yielding the largest value of the given function or `null` if there are no elements.
     * 
     * @sample samples.collections.Collections.Aggregates.maxBy
     */
    public inline fun <T, R : Comparable<R>> Iterable<T>.maxBy(selector: (T) -> R): T? {
        val iterator = iterator()
        if (!iterator.hasNext()) return null
        var maxElem = iterator.next()
        if (!iterator.hasNext()) return maxElem
        var maxValue = selector(maxElem)
        do {
            val e = iterator.next()
            val v = selector(e)
            if (maxValue < v) {
                maxElem = e
                maxValue = v
            }
        } while (iterator.hasNext())
        return maxElem
    }
    复制代码
  • 使用示例

    maxBy操作符适用于:根据给定的函数返回最大的一项,如果没有则返回null

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        println(strList.maxBy { "${it}kotlin" })
    }
    /******打印结果******/
    python
    复制代码

maxWith(comparator: Comparator<in T>)

  • 基本定义

    接受一个 Comparator 对象并且根据此 Comparator 对象返回最大元素

  • 源码定义与解析

    /**
     * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements.
     */
    public fun <T> Iterable<T>.maxWith(comparator: Comparator<in T>): T? {
        val iterator = iterator()
        if (!iterator.hasNext()) return null
        var max = iterator.next()
        while (iterator.hasNext()) {
            val e = iterator.next()
            if (comparator.compare(max, e) < 0) max = e
        }
        return max
    }
    复制代码
  • 使用示例

    maxWith操作符适用于:接受一个Comparator对象并且根据此Comparator对象返回最大元素

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        print(strList.maxWith(compareBy{it.length}))
    }
    /******打印结果******/
    javaScript
    复制代码

min操作符

min操作符作用与max相反,包括minByminWith

4.5 reduce系列

reduce(operation: (acc: S, T) -> S)

  • 基本定义

    从集合中的第一项到最后一项的累计操作,与fold操作符的区别是没有初始值

  • 源码定义与解析

    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
    }
    复制代码
  • 使用示例

    reduce操作符适用于:按照某个函数对集合中的每个元素进行累计

    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        print(strList.reduce{result, element -> "$result $element"})
    }
    /******打印结果******/
    java javaScript kotlin C C++ javaFx python Go Swift Scala
    复制代码

备注

其中reduceIndexedreduceRightreduceRightIndexed操作符都与前述的fold相关操作符类似,只是没有初始值

reduceOrNull(operation: (acc: S, T) -> S)

  • 基本定义

    从集合中的第一项到最后一项的累计操作,如果集合为空,返回null

  • 源码定义与解析

    /**
     * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. Returns null if the collection is empty.
     * 
     * @sample samples.collections.Collections.Aggregates.reduceOrNull
     */
    @SinceKotlin("1.3")
    @ExperimentalStdlibApi
    public inline fun <S, T : S> Iterable<T>.reduceOrNull(operation: (acc: S, T) -> S): S? {
        val iterator = this.iterator()
        if (!iterator.hasNext()) return null	//集合为空,返回null
        var accumulator: S = iterator.next()
        while (iterator.hasNext()) {
            accumulator = operation(accumulator, iterator.next())
        }
        return accumulator
    }
    复制代码
  • 使用示例

    reduceOrNull操作符适用于:集合元素的累计操作,且集合可能为null的情况

    @ExperimentalStdlibApi
    fun main(args: Array<String>) {
        val strList = listOf("java", "javaScript", "kotlin", "C", "C++", "javaFx", "python","Go", "Swift", "Scala")
        print(strList.reduceOrNull{result, element -> "$result $element"})
    }
    复制代码

备注

reduceRightOrNull操作符作用等价于reduceRight,不同的是当集合为空,返回null

4.6 sum系列

sum()

  • 基本定义

    计算出集合元素累加的结果

  • 源码定义与解析

    /**
     * Returns the sum of all elements in the collection.
     */
    @kotlin.jvm.JvmName("sumOfByte")
    public fun Iterable<Byte>.sum(): Int {
        var sum: Int = 0
        for (element in this) {
            sum += element
        }
        return sum
    }
    
    @kotlin.jvm.JvmName("sumOfLong")
    public fun Iterable<Long>.sum(): Long {
        var sum: Long = 0L
        for (element in this) {
            sum += element
        }
        return sum
    }
    
    //.......
    复制代码
  • 使用示例

    sum操作符适用于:计算集合中所有元素累加的结果

    fun main(args: Array<String>) {
        val intList = listOf(1,2,3,4,5,6,7,8,9,10)
        print(intList.sum())
    }
    /******打印结果******/
    55
    复制代码

sumBy(selector: (T) -> Int)

  • 基本定义

    返回所有每一项通过函数转换之后的数据的总和。

  • 源码定义与解析

    /**
     * Returns the sum of all values produced by [selector] function applied to each element in the collection.
     */
    public inline fun <T> Iterable<T>.sumBy(selector: (T) -> Int): Int {
        var sum: Int = 0
        for (element in this) {
            sum += selector(element)
        }
        return sum
    }
    复制代码
  • 使用示例

    sumBy操作符适用于:计算集合所有元素通过某个函数转换后数据之和

    fun main(args: Array<String>) {
        val intList = listOf(1,2,3,4,5,6,7,8,9,10)
        print(intList.sumBy { it * 2 })
    }
    /******打印结果******/
    110
    复制代码
  • 备注

    sumByDouble操作符与sumBy功能一致,只不过其对应double数据操作

猜你喜欢

转载自juejin.im/post/7073058698251206669