目录
takeIf
/**
*return:返回值,如果传入的函数predicate的返回值为true则将T这个对象返回,否则返回null
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (predicate(this)) this else null
}
分解:
T:为任意对象
predicate: 传入的函数或表达式
(T) -> Boolean:函数的类型,即将T对象传入,返回一个布尔值
例:
(1)常见的if判断
java:
int a;
if(a>5){ doSomething(); }
kotlin:
var a
takeIf{ a>5 }?.apply{ doSomething() }
(2)判断一个对象的属性
java:
if(obj != null && obj.name == "小花"){
doSomething();
}
kotlin:
if(obj?.name == "小花"){
doSomething()
}
或:
obj.takeIf(obj.name == "小花")?.apply{ doSomething() }
当然takeIf里的obj对象可以用it代替
obj.takeIf(it.name == "小花")?.apply{ doSomething() }
总结:因为返回的是调用对象自己,所以可以进行链式调用
takeUnless
/**
* 与takeIf用法基本一致,只是在返回处做了取反操作,即predicate为true返回null,否则返回T对象自己
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (!predicate(this)) this else null
}
filter
/**
* 过滤器
* 返回符合predicate过滤条件的list
*
*/
public inline fun <T> Array<out T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate)
}
分解:
<T> Array<out T> :一个T或T子类的数组对象
predicate: 条件函数,即fun(T t){return boolean}
(T) -> Boolean : 函数类型,传入数组对象中的一个元素,返回一个布尔值
List<T> : 返回值类型,实现了List接口的子类
它直接返回了filterTo函数,主要处理逻辑在filterTo中
public inline fun <T, C : MutableCollection<in T>> Array<out T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
return destination
}
简单易懂,将满足条件(predicate)的数组添加到到list里返回了
例:
java:
public class Student{
String name;
int age;
public Student(String name,int age){}
}
Student[] arr;
List<Student> list = new ArrayList();
Student stu1 = new Student("小李",28)
Student stu2 = new Student("小王",15)
Student stu3 = new Student("小赵",23)
...
arr = new Student[]{stu1,stu2,stu3, …};
for(Student std : arr){
if(std.age > 20){
list.add(std)
}
}
kotlin:
//省略student实体类
var list = arr.filter{it.age > 20}
forEach
/// 以IntArray.forEach为例
/**
* 遍历数组里的每一个元素
* 这是IntArray的一个扩展函数
*/
public inline fun IntArray.forEach(action: (Int) -> Unit): Unit {
//遍历数组里的元素,然后将给个元素传给action函数
for (element in this) action(element)
}
分解:
action: (Int) -> Unit:传入的参数是一个(Int) -> Unit类型的函数
Unit:forEach函数的返回类型
使用:
var intArray :IntArray = intArrayOf(1,2,3,4,56)
案例1:
intArray.forEach({
println(it)
})
案例2:
intArray.forEach{
println(it)
}
案例3:
intArray.forEach(::print)
从案例1到案例3是语法上的演变过程,因为println的重载之一的类型的(Int) -> Unit,所以可以直接将println函数的引用直接传入forEach,同理自定义的(Int) -> Unit类型的函数都可以这样使用
firsrt
* 返回可迭代对象中符合predicate条件的第一个元素
* 若没有符合条件的元素,则抛出异常
* @throws [NoSuchElementException] if no such element is found.
*/
public inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T {
for (element in this) if (predicate(element)) return element
throw NoSuchElementException("Collection contains no element matching the predicate.")
}
分解:
inline fun:是一个内联函数
<T> Iterable<T> :实现了Iterable接口的对象才能使用first函数
predicate: (T) -> Boolean :返回布尔值得函数或lamada表达式
例:
var list :List<Int> = listOf<Int>(1,2,2,2,3,4,5)
val first :Int = list.first { it == 2 }
当第一个2满足条件时,直接就返回了第一个2
fold
/**
* 给定一个初始值initial
* 将初始值与这个函数的调用者(可迭代对象)中的元素,做动作累加(operation)操作
* 最后将动作累加后的结果返回
*/
public inline fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) -> R): R {
//将初始值赋值给临时对象accumulator
var accumulator = initial
//遍历所有元素
for (element in this)
//每个元素在之前的基础上做动作累加
accumulator = operation(accumulator, element)
//注意return不在循环体中
return accumulator
}
分解:
<T, R> Iterable<T> :调用fold函数的对象需要实现Iterable接口,T,R为两个泛型
initial: R :给定的一个初始值
operation: (acc: R, T) -> R :需要做的累加动作,累加动作不是单指做加法,这是基于上个值做操作的统称
案例1:依次累乘
val arr = intArrayOf(3, 5, 4, 7, 10)
val fold = arr.fold(2) { acc, i -> acc * i }
println(fold)
*为避免歧义,这个例子中累加动作为做乘法
即:initial = 2
累加动作为 R * T
运行过程为:
acc = 2 * 3
acc = 6 * 5 ,6即(上次的结果 2*3)
acc = 30 * 4
acc = 120 * 7
acc = 840 * 10
acc = 8400
返回8400
案例2:将集合拼接成字符串
println((0..6).fold(StringBuilder()) { acc, i ->
acc.append(i).append(",")
})
总结:operation(累加动作)是由使用者自己定义的运算逻辑