kotlin07.函数式编程

138 阅读2分钟

用函数式编程来解决复杂计算问题的编程范式称为函数式编程. 每个函数都针对集合设计,它将输入集合经过变换,过滤,合并等多个简单函数组合后变成目标集合.

  • 函数式编程的设计理念就是不可变数据的副本在链上的函数间传递的过程
  • 处理函数处理的都是单个数据元素,变换后自动合并为新的集合

函数式编程三个大类

  • 变换transform
  • 过滤 filter
  • 合并 combine

变换 map / flatmap

针对集合元素的操作

map

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
}


val listOf = listOf("monkey", "giraffe" , "zebra")
listOf.map {it.length }.run { println(this) } // [6, 7, 5]


flatmap

将集合元素平铺.它将输入集合中的每个元素做变换后,添加到同一集合中

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 listOf = listOf("monkey", "giraffe" , "zebra")
listOf.flatMap { it.toSet()}.run { println(this) } //[m, o, n, k, e, y, g, i, r, a, f, e, z, e, b, r, a]

过滤 filter

过滤函数根据predicate的返回值来确定是否将遍历元素加入到结果集合中,如果为true则添加,为false则丢弃.

val listOf = listOf("monkey", "giraffe" , "zebra" )
listOf.filter { it.contains("a") }.run { println(this) } //[giraffe, zebra]


//例子,求素数
val intList = listOf(10, 8, 5, 7, 3, 100, 107, 233)
intList.filter { number->
    (2 until number).map { number % it }.none { it == 0 }
}

合并

zip

将两个集合转化为健值对的map , 注意长度是按照最短集合来定的

.比如elephant就丢弃了

val l = listOf("monkey", "giraffe" , "zebra", "elephant")
var weight = listOf(100 ,200 , 300)

l.zip(weight).run { println(this) } // [(monkey, 100), (giraffe, 200), (zebra, 300)]

fold

累加器,初始值 + 处理函数(每个元素) 的结果

//累加的列子
var weight = listOf(100 ,200 , 300)
weight.fold(10){acc,it->
    acc + it * 3
}.run { println(this) } // 1810 , acc是累加器的结果

// 求素数的进阶版例子
fun Int.isPrime() = ! (2 until this).map { this % it == 0 }.fold(false){acc, b -> acc || b }

listOf( 1 , 3 , 10 , 7 , 11 , 21).filter { it.isPrime() }.run { println(this) }

//求 5000以内的素数
(2..5000).filter { it.isPrime() }.take(1000).run { println(this) }

序列

产生未知数量的序列,不记录数据,也不记录未知,所有的数据都可以加入到序列中.

generateSequence

根据种子seed和函数,生产下一个数据.数据源本身是无限的.

//寻找1000个素数
generateSequence(1 ){ it + 2 }.filter { it.isPrime() }.take(1000).run { println(this) }