kotlin源码刚开始阅读的时候还是挺难理解的,下面对自己看过的一些函数源码作下总结:
forEach
public inline fun Iterable.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
调用示范
val list = listOf(1,2,3,4,5)
list.forEach({arg : Int -> println(arg)})
T就是list的类型,按照上面调用的方法就是Int类型,传入的参数是action: (T) -> Unit,就是一个带有Int类型参数无返回值的函数,{arg : Int -> println(arg)}刚好就是一个这样的函数.
这里补充一下,通常{arg : Int -> println(arg)}过于臃肿,kotlin提供更简单的写法,利用类型推导,可以省略Int类型
list.forEach({arg -> println(arg)})
如果只有一个参数可以不需要声明,直接用it代替
list.forEach({println(it)})
这种参数传递最后一个参数可以提到()外面,并且省略(),如下
list.forEach{println(it)}
接下来看执行的代码
public inline fun Iterable.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element) //循环迭代,执行传入的action
}
reduce
public inline fun Iterable.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
}
调用示范
val list = listOf(1,2,3,4,5)
list.reduce { acc : Int, i -> i + acc}
源码中S, T类型到底是什么,整个执行过程是怎样的呢?
Iterable声明,这意味着S必须是T的父类或者就是T类型,在上面调用中完整的写法其实是
list.reduce { acc : Int, i -> i + acc}
那么这个S其实也是Int类型.搞清楚类型过后,接下来看执行的代码
public inline fun Iterable.reduce(operation: (acc: S, T) -> S): S {
val iterator = this.iterator() //this是指list,iterator是list的迭代器
if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
var accumulator: S = iterator.next() //累加值,保存list中第一个变量
while (iterator.hasNext()) {
accumulator = operation(accumulator, iterator.next()) //开始执行operation,这个具体怎么执行看传入的函数了,大概就是accumulator和iterator.next()执行某种算法后赋值给accumulator
}
return accumulator
}
fold
这个函数和reduce非常类似,区别就是有一个初始值而且R类型可以任意指定
public inline fun Iterable.fold(initial: R, operation: (acc: R, T) -> R): R {
var accumulator = initial
for (element in this) accumulator = operation(accumulator, element)
return accumulator
}
调用方法
(0..6).fold(5,{acc, i -> acc +i })
显然在这种情况下T类型是迭代器的类型, R一个可以任意指定的类型,在上面调用中T和R都是Int类型.接下来看一下代码注释
public inline fun Iterable.fold(initial: R, operation: (acc: R, T) -> R): R {
var accumulator = initial //赋值初始值
for (element in this) accumulator = operation(accumulator, element) //迭代,并执行传入的operation
return accumulator
}
另外前面提到R实际上可以任意指定,可以看看下面
(0..6).fold(StringBuilder(),{ acc : StringBuilder, i -> acc.append(i) }).toString()
filter
public inline fun Iterable.filter(predicate: (T) -> Boolean): List {
return filterTo(ArrayList(), predicate)
}
调用示范
val array = listOf(1,2,3)
array.filter { arg : Int -> arg % 2 == 0 }
在这种情况下T就是Int类型,返回一个boolean值. arg % 2就是判断依据
public inline fun > Iterable.filterTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
return destination
}
在里面还调用了一个filterTo(ArrayList
filterTo很好解释
public inline fun > Iterable.filterTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
return destination
}
传入destination实际就是ArrayList
为true的情况下会添加到destination上面.
takeWhile
public inline fun Iterable.takeWhile(predicate: (T) -> Boolean): List {
val list = ArrayList()
for (item in this) {
if (!predicate(item))
break
list.add(item)
}
return list
}
实际调用
val array = listOf(1,2,3,4,5,6)
array.takeWhile { it % 2 == 0 }
更具调用情况这里T就是int, predicate就是it % 2 == 0,predicate作为判断条件决定是否添加到新创建的list里面然后返回.
let
public inline fun T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
实际调用
"3".let { null }
根据实际调用情况T就是String, R就是null类型. 这个函数的主要作用实际上就是一个类型转换.
apply
public inline fun T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
实际调用
class Person{
fun work(){
print("")
}
}
fun applyT(){
findPerson().apply {
this.work()
print("调用完成")
}
}
block: T.() -> Unit实际上是一个T类型的扩展函数并且是无返回值, apply函数里面也就是调用这个扩展函数,然后返回自己.
with
public inline fun with(receiver: T, block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver.block()
}
with其实和apply还挺类似,apply的调用,而with是作为参数传入, 最后返回R类型,下面来看一个with的应用场景
fun writeToFile(){
val str = "my name is jay"
val bw = BufferedWriter(FileWriter("hello.txt"))
with(bw){
write(str)
close()
}
}
use
public inline fun T.use(block: (T) -> R): R {
var exception: Throwable? = null
try {
return block(this)
} catch (e: Throwable) {
exception = e
throw e
} finally {
when {
apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)
this == null -> {}
exception == null -> close()
else ->
try {
close()
} catch (closeException: Throwable) {
// cause.addSuppressed(closeException) // ignored here
}
}
}
}
这个调用类型必须是Closeable,它省去了调用close()的过程(已经封装到了use里面)
fun writeToFile(){
val str = "my name is jay"
val bw = BufferedWriter(FileWriter("hello.txt"))
bw.use { it.write(str) }
}