常用高阶函数

  • 1、变换函数 map
  • 2、变换函数 flatMap
  • 3、过滤函数 filter
  • 4、合并函数 zip
  • 5、压缩 reduce
  • 6、折叠函数 fold
  • 7、全部代码


1、变换函数 map

Kotlin源码可知 map 函数就是对 Iterable<T> 的 扩展函数,作用就是将泛型T的集合变换成泛型R的集合

public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
    return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}
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
}

map使用如下功能:

  1. 将集合中的所有元素都添加【】,类型变换 String->String
  2. 将集合中所有的元素都变成字符串长度,类型变换String->Int
  3. 将集合中所有的元素都变成布尔值,类型变换Int->Boolean
val list = listOf("kotlin","c++","c#","java","html")
 
 //将集合中的所有元素都添加【】,类型变换 String->String
 val change1 = list.map {
    "【$it】"
 }
 println("map变换:$change1")

 //将集合中所有的元素都变成字符串长度,类型变换String->Int
 val change2 = change1.map {
	it.length
 }
 println("map变换:$change2")

 //将集合中所有的元素都变成布尔值,类型变换Int->Boolean
 val change3 = change2.map {
	it<6
 }
 println("map变换:$change3")

因为map的返回类型也是List,所以可以进行链式调用

//对list进行连续变换
val change4 = list.map {
	"【$it】"
}.map {
	it.length
}.map {
	it < 6
}
println("map连续变换:$change4")

输出:

map变换:[【kotlin】, 【c++】, 【c#】, 【java】, 【html】]
map变换:[8, 5, 4, 6, 6]
map变换:[false, true, true, false, false]
map连续变换:[false, true, true, false, false]

2、变换函数 flatMap

Kotlin源码可知 flatMap 函数也是对 Iterable<T> 的 扩展函数,作用就是将泛型T的集合变换成泛型R的集合,跟map 函数的区别就是 flatMap 针对的是嵌套的集合,所以泛型R 也是个集合类型

public inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R> {
    return flatMapTo(ArrayList<R>(), transform)
}
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
}
val list = listOf("kotlin","c++","c#","java","html")
val list2 = listOf(
	listOf("kotlin", "c++", "c#"),
	listOf(123, 456, 789),
	listOf(true, false, true)
)

//对非嵌套的集合进行flatMap 变换
val flatChange1 = list.flatMap {
	listOf("【$it】")
}
println("flatMap变换:$flatChange1")

//对嵌套集合进行flatMap 变换
val flatChange2 = list2.flatMap {
	listOf("【$it】")//it是一个集合了
}
println("flatMap变换:$flatChange2")

输出:从输出结果可以看出FlatMap处理的it是个集合

flatMap变换:[【kotlin】, 【c++】, 【c#】, 【java】, 【html】]
flatMap变换:[【[kotlin, c++, c#]】, 【[123, 456, 789]】, 【[true, false, true]】]

如果我们想对所有元素都进行【】处理,那么还要对flatMap的it进行map处理

val flatChange3 = list2.flatMap {
	it.map {
		"【$it】"
	}
}
println("flatMap变换:$flatChange3")
flatMap变换:[【kotlin】, 【c++】, 【c#】, 【123】, 【456】, 【789】, 【true】, 【false】, 【true】]

3、过滤函数 filter

从kotlin源码可知filter 函数也是针对集合的,作用就是过滤集合中满足条件的元素,然后返回新的集合

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 实现:

  1. 过滤集合1中满足长度大于等于3的元素
  2. 过滤集合2中属于Int类型的元素
val list = listOf("kotlin","c++","c#","java","html")
 val list2 = listOf(
	listOf("kotlin", "c++", "c#"),
	listOf(123, 456, 789),
	listOf(true, false, true)
)
 
//过滤集合中满足长度大于等于3的元素
val filter1 = list.filter {
	it.length >= 3
}
println("filter过滤:$filter1")

//过滤集合中属于Int类型的元素
val filter2 = list2.flatMap {
	it.filter {
		it is Int
	}
}
println("filter过滤:$filter2")

输出:

filter过滤:[kotlin, c++, java, html]
filter过滤:[123, 456, 789]

4、合并函数 zip

从kotlin源码可知zip 函数也是针对集合的,作用就是将两个集合合并成一个集合,集合元素变成了 Pair(集合1元素,集合2元素)

public infix fun <T, R> Iterable<T>.zip(other: Iterable<R>): List<Pair<T, R>> {
    return zip(other) { t1, t2 -> t1 to t2 }
}

合并集合,如果长度不相同,最终合并后的集合长度由长度最小的那个决定

val list = listOf("kotlin", "c++", "c#", "java", "html")
val list3 = listOf(1, 2, 3, 4, 5)
val list4 = listOf(1, 2, 3, 4, 5,6,7)

val zip1 = list.zip(list3)
println("zip合并:$zip1")

val zip2 = list.zip(list4)
println("zip合并:$zip2")

输出:

zip合并:[(kotlin, 1), (c++, 2), (c#, 3), (java, 4), (html, 5)]
zip合并:[(kotlin, 1), (c++, 2), (c#, 3), (java, 4), (html, 5)]

5、压缩 reduce

从源码中可知reduce 函数就是将集合所有元素压缩成一个元素
由:var accumulator: S = iterator.next() 而返回类型也是S 可知
由:operation(accumulator, iterator.next()) 可知返回结果 就是每个元素直接调用者规定的算法逻辑

所有: reduce 函数的返回值类型有元素决定,返回结果有调用者提供的算法提供

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
}

实现

  1. list4 所有元素相加、相乘结果
  2. list 所有元素拼接
val list = listOf("kotlin", "c++", "c#", "java", "html")
val list4 = listOf(1, 2, 3, 4, 5, 6, 7)

val reduce1 = list4.reduce { acc, i -> acc + i }
println("reduce压缩:$reduce1")

val reduce2 = list4.reduce { acc, i -> acc * i }
println("reduce压缩:$reduce2")

val reduce3 = list.reduce { acc, s ->
	acc.plus(s)
}
println("reduce压缩:$reduce3")

输出:

reduce压缩:28
reduce压缩:5040
reduce压缩:kotlinc++c#javahtml

6、折叠函数 fold

从源码可知 fold 接收一个初始值,然后再跟集合中所有元素进行制定规则的折叠,并且返回值类型没有进行约束

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
}

实现

  1. list4 所有元素相加、相乘结果+初始值
  2. list 所有元素拼接长度+初始值
val fold1 = list4.fold(100) { acc, i ->
	acc + i
}
println("fold折叠:$fold1")

val fold2 = list4.fold(100) { acc, i ->
	acc * i
}
println("fold折叠:$fold2")

val fold3 = list.fold(100) { acc, s ->
	acc + s.length
}
println("reduce压缩:$fold3")

输出:

fold折叠:128
fold折叠:504000
reduce压缩:119

7、全部代码

fun main() {

    val list = listOf("kotlin", "c++", "c#", "java", "html")


    //将集合中的所有元素都添加【】,类型变换 String->String
    val change1 = list.map {
        "【$it】"
    }
    println("map变换:$change1")

    //将集合中所有的元素都变成字符串长度,类型变换String->Int
    val change2 = change1.map {
        it.length
    }
    println("map变换:$change2")

    //将集合中所有的元素都变成布尔值,类型变换Int->Boolean
    val change3 = change2.map {
        it < 6
    }
    println("map变换:$change3")

    //对list进行连续变换
    val change4 = list.map {
        "【$it】"
    }.map {
        it.length
    }.map {
        it < 6
    }
    println("map连续变换:$change4")

    println()

    val list2 = listOf(
        listOf("kotlin", "c++", "c#"),
        listOf(123, 456, 789),
        listOf(true, false, true)
    )

    //对非嵌套的集合进行变换
    val flatChange1 = list.flatMap {
        listOf("【$it】")
    }
    println("flatMap变换:$flatChange1")

    //对嵌套集合进行变换
    val flatChange2 = list2.flatMap {
        listOf("【$it】")//it是一个集合了
    }
    println("flatMap变换:$flatChange2")

    println()
    //如果我们想对所有元素都进行【】处理,那么还要对flatMap的it进行map处理
    val flatChange3 = list2.flatMap {
        it.map {
            "【$it】"
        }
    }
    println("flatMap变换:$flatChange3")

    println()

    //过滤集合中满足长度大于等于3的元素
    val filter1 = list.filter {
        it.length >= 3
    }
    println("filter过滤:$filter1")

    //过滤集合中属于Int类型的元素
    val filter2 = list2.flatMap {
        it.filter {
            it is Int
        }
    }
    println("filter过滤:$filter2")

    println()
    val list3 = listOf(1, 2, 3, 4, 5)
    val list4 = listOf(1, 2, 3, 4, 5, 6, 7)


    val zip1 = list.zip(list3)
    println("zip合并:$zip1")

    val zip2 = list.zip(list4)
    println("zip合并:$zip2")

    println()

    val reduce1 = list4.reduce { acc, i -> acc + i }
    println("reduce压缩:$reduce1")

    val reduce2 = list4.reduce { acc, i -> acc * i }
    println("reduce压缩:$reduce2")

    val reduce3 = list.reduce { acc, s ->
        acc.plus(s)
    }
    println("reduce压缩:$reduce3")

    println()

    val fold1 = list4.fold(100) { acc, i ->
        acc + i
    }
    println("fold折叠:$fold1")

    val fold2 = list4.fold(100) { acc, i ->
        acc * i
    }
    println("fold折叠:$fold2")

    val fold3 = list.fold(100) { acc, s ->
        acc + s.length
    }
    println("reduce压缩:$fold3")

}