直接上一段 Kotlin 的函数式编程的代码:
1package com.easykotlin.lec02 2 3fun sum1(x: Int, y: Int): Int { 4 return x + y 5} 6 7fun sum2(x: Int, y: Int) = x + y 8 9// sum2 函数字面量: 匿名函数 10val sum3 = fun(x: Int, y: Int) = x + y 11val s3 = (fun(x: Int, y: Int) = x + y)(1, 1) 12val s32 = (fun(x: Int, y: Int) = x + y).invoke(1, 1) 13 14// Lambda 15val sum4 = { x: Int, y: Int -> x + y } 16val s4 = { x: Int, y: Int -> x + y }(1, 1) 17val s42 = { x: Int, y: Int -> x + y }.invoke(1, 1) 18 19val sum5: (Int, Int) -> Int = { x, y -> x + y } 20 21// 高阶函数 22fun repeat(n: Int, body: () -> Unit) { 23 for (i in 1..n) { 24 body() 25 } 26} 27 28// 类型别名 29typealias A = (String) -> Int 30 31typealias B = (Int) -> Boolean 32typealias C = (String) -> Boolean 33 34val length: A = { x -> x.length } 35val isOdd: B = { x -> x % 2 == 1 } 36// 高阶函数(复合函数) 37val filterOdd: C = { x -> 38 isOdd(length(x)) 39} 40 41fun main(args: Array<String>) { 42 val list = listOf("a", "abc", "abcbdf", "adsfeeff", "qwedddsssssdd") 43 // 过滤出 list 中字符串长度是奇数的元素 44 val result = list.filter(filterOdd) 45 println(result) 46 47 repeat(3) { 48 println("A") 49 } 50 51 // 1 + 2 + 。。。 + 100 52 var sum = 0 53 var i = 1 54 repeat(100) { 55 sum += i 56 i++ 57 } 58 println("sum = $sum") 59 60 61 62 sum1(1, 1) 63 sum2(1, 1) 64 sum3(1, 1) 65 sum4(1, 1) 66 sum5(1, 1) 67 println("s3 = $s3") 68 println("s32 = $s32") 69 println("s4 = $s4") 70 println("s42 = $s42") 71}
Java 8:
1public void filter(Filter f, List<Integer> integerList) { 2 for (Integer i : integerList) { 3 if (f.test(i)) { 4 System.out.println(i); 5 } 6 } 7} 8// 定义一个 SAM 9interface Filter { 10 boolean test(int x); 11} 12 13public void lambdaDemo() { 14 filter((x) -> x % 2 == 1, Arrays.asList(1, 2, 3, 4, 5, 6, 7)); 15}
Java 在一个拥有两个方法(不含默认方法)的接口中,是不可以使用 Lambda 表达式的,当一个接口中只有一个抽象方法,即达成了SAM(Single Abstract Method)条件时,Lambda表达式才可以使用。
Kotlin:
1fun filter(f: (Int) -> Boolean, integerList: List<Int>) { 2 for (i in integerList) { 3 if (f(i)) { 4 println(i) 5 } 6 } 7} 8 9fun lambdaDemo() { 10 filter({ x -> x % 2 == 1 }, Arrays.asList(1, 2, 3, 4, 5, 6, 7)) 11}
在 Kotlin 中,函数 f:(Int)->Boolean 也是一种类型,可以像普通的参数变量一样,在函数入参中传递,当然也可以返回一个函数。
再举个例子:
1fun repeat(times: Int, body: () -> Unit) { 2 for (i in 0 until times) { 3 body() 4 } 5} 6 7 8fun main(args: Array<String>) { 9 repeat(3, { 10 println("A") 11 }) 12 13 repeat(3) { 14 println("B") 15 } 16 17 var sum = 0 18 var i = 1 19 repeat(100) { 20 sum += i 21 i++ 22 } 23 println(sum) 24}
Function 接口
函数 Function 接口类型只有一个调用方法:invoke() 。
它包含三个动作:传入参数、处理参数、返回结果。
Kotlin定义了kotlin.Function<out R>接口来抽象所有函数,它没有定义任何方法。
关键在于:kotlin.jvm.functions包里定义了
1package kotlin.jvm.functions 2 3/** A function that takes 0 arguments. */ 4public interface Function0<out R> : Function<R> { 5 /** Invokes the function. */ 6 public operator fun invoke(): R 7} 8/** A function that takes 1 argument. */ 9public interface Function1<in P1, out R> : Function<R> { 10 /** Invokes the function with the specified argument. */ 11 public operator fun invoke(p1: P1): R 12} 13/** A function that takes 2 arguments. */ 14public interface Function2<in P1, in P2, out R> : Function<R> { 15 /** Invokes the function with the specified arguments. */ 16 public operator fun invoke(p1: P1, p2: P2): R 17} 18/** A function that takes 3 arguments. */ 19public interface Function3<in P1, in P2, in P3, out R> : Function<R> { 20 /** Invokes the function with the specified arguments. */ 21 public operator fun invoke(p1: P1, p2: P2, p3: P3): R 22} 23/** A function that takes 4 arguments. */ 24public interface Function4<in P1, in P2, in P3, in P4, out R> : Function<R> { 25 /** Invokes the function with the specified arguments. */ 26 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4): R 27} 28/** A function that takes 5 arguments. */ 29public interface Function5<in P1, in P2, in P3, in P4, in P5, out R> : Function<R> { 30 /** Invokes the function with the specified arguments. */ 31 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): R 32} 33/** A function that takes 6 arguments. */ 34public interface Function6<in P1, in P2, in P3, in P4, in P5, in P6, out R> : Function<R> { 35 /** Invokes the function with the specified arguments. */ 36 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): R 37} 38/** A function that takes 7 arguments. */ 39public interface Function7<in P1, in P2, in P3, in P4, in P5, in P6, in P7, out R> : Function<R> { 40 /** Invokes the function with the specified arguments. */ 41 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7): R 42} 43/** A function that takes 8 arguments. */ 44public interface Function8<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, out R> : Function<R> { 45 /** Invokes the function with the specified arguments. */ 46 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8): R 47} 48/** A function that takes 9 arguments. */ 49public interface Function9<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, out R> : Function<R> { 50 /** Invokes the function with the specified arguments. */ 51 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R 52} 53/** A function that takes 10 arguments. */ 54public interface Function10<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, out R> : Function<R> { 55 /** Invokes the function with the specified arguments. */ 56 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10): R 57} 58/** A function that takes 11 arguments. */ 59public interface Function11<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, out R> : Function<R> { 60 /** Invokes the function with the specified arguments. */ 61 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11): R 62} 63/** A function that takes 12 arguments. */ 64public interface Function12<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, out R> : Function<R> { 65 /** Invokes the function with the specified arguments. */ 66 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12): R 67} 68/** A function that takes 13 arguments. */ 69public interface Function13<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, out R> : Function<R> { 70 /** Invokes the function with the specified arguments. */ 71 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13): R 72} 73/** A function that takes 14 arguments. */ 74public interface Function14<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, out R> : Function<R> { 75 /** Invokes the function with the specified arguments. */ 76 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14): R 77} 78/** A function that takes 15 arguments. */ 79public interface Function15<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, out R> : Function<R> { 80 /** Invokes the function with the specified arguments. */ 81 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15): R 82} 83/** A function that takes 16 arguments. */ 84public interface Function16<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, out R> : Function<R> { 85 /** Invokes the function with the specified arguments. */ 86 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16): R 87} 88/** A function that takes 17 arguments. */ 89public interface Function17<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, out R> : Function<R> { 90 /** Invokes the function with the specified arguments. */ 91 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17): R 92} 93/** A function that takes 18 arguments. */ 94public interface Function18<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, out R> : Function<R> { 95 /** Invokes the function with the specified arguments. */ 96 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18): R 97} 98/** A function that takes 19 arguments. */ 99public interface Function19<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, out R> : Function<R> { 100 /** Invokes the function with the specified arguments. */ 101 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19): R 102} 103/** A function that takes 20 arguments. */ 104public interface Function20<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, out R> : Function<R> { 105 /** Invokes the function with the specified arguments. */ 106 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20): R 107} 108/** A function that takes 21 arguments. */ 109public interface Function21<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, in P21, out R> : Function<R> { 110 /** Invokes the function with the specified arguments. */ 111 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21): R 112} 113/** A function that takes 22 arguments. */ 114public interface Function22<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, in P21, in P22, out R> : Function<R> { 115 /** Invokes the function with the specified arguments. */ 116 public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22): R 117}
来分别抽象无参到22个参数的函数,它们都继承了kotlin.Function接口,同时定义了一个invoke()函数。

大于22个参数的函数,使用 FunctionN 接口:
1package kotlin.jvm.functions 2 3import kotlin.jvm.internal.FunctionBase 4 5/** 6 * A function that takes N >= 23 arguments. 7 * 8 * This interface must only be used in Java sources to reference a Kotlin function type with more than 22 arguments. 9 */ 10@SinceKotlin("1.3") 11interface FunctionN<out R> : Function<R>, FunctionBase<R> { 12 /** 13 * Invokes the function with the specified arguments. 14 * 15 * Must **throw exception** if the length of passed [args] is not equal to the parameter count returned by [arity]. 16 * 17 * @param args arguments to the function 18 */ 19 operator fun invoke(vararg args: Any?): R 20 21 /** 22 * Returns the number of arguments that must be passed to this function. 23 */ 24 override val arity: Int 25}
如下是Function2接口:
1interface Function2<in P1, in P2, out R> : Function<R> { 2 operator fun invoke(p1: P1, p2: P2): R 3}
p1和p2是传入的两个参数类型,R就是返回值类型。因为我们只会向函数传入参数、从函数中取出返回值,所以分别用in和out修饰。
invoke()函数定义了“调用”这个行为,它同时重载了括号操作符,允许用括号来传入参数、得到返回值。
我们可以定义一个匿名函数,然后把它赋值给sum变量:
val sum: (Int, Int) -> Int = fun(a: Int, b: Int) = a + b
由于匿名函数已经定义好参数列表和返回值类型了,我们可以省略sum的类型声明:
val sum = fun(a: Int, b: Int) = a + b
Lambda表达式就是一个匿名函数,可以把这个匿名函数改写为Lambda表达式:
val sum = { a: Int, b: Int -> a + b }
上面定义的sum函数对象,它会被编译为一个Function2类型的对象,(Int,Int)->Int是Function2接口的具体实现类,可以使用invoke()函数来调用它:
println(sum.invoke(1,2))
也可以直接用括号操作符:
println(sum(1,2))
小结
相比之下,Kotlin 对函数式编程的支持更加自然优雅。
Kotlin 开发者社区
国内第一Kotlin 开发者社区公众号,主要分享、交流 Kotlin 编程语言、Spring Boot、Android、React.js/Node.js、函数式编程、编程思想等相关主题。

开发者社区 QRCode.jpg
本文分享 CSDN - 东海陈光剑。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。