笔者专注于Android安全领域, 欢迎关注个人的微信公众号《Android安全工程》(可点击进行扫码关注)。个人微信公众号主要围绕 Android 应用的安全防护和逆向分析, 分享各种安全攻防手段、Hook 技术、ARM 汇编等 Android 相关的知识。
Kotlin 的 filterNot
的实现源码如下:
/**
* Returns a list containing all elements that don't satisfy the given [predicate].
*/
public inline fun <T> Iterable<T>.filterNot(predicate: (T) -> Boolean): List<T> {
return filterNotTo(ArrayList(), predicate)
}
/**
* Appends all elements that don't satisfy the given [predicate] to the given [destination].
*
* @return the destination list.
*/
public inline fun <C : MutableCollection<in T>, T> Iterable<T>.filterNotTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (!predicate(element)) destination.add(element)
return destination
}
这两个函数都接受一个 predicate 参数,即过滤条件的 lambda 表达式。在函数执行中,如果 predicate 返回 false,则表示该元素保留;如果返回 true,则表示该元素被过滤掉。
具体来说,这两个函数内部使用了基于 for 循环和 if 语句的实现方式。它们会遍历输入的容器,对每个元素都使用 predicate 进行判断,然后根据判断结果选择是否保留该元素。过滤后的元素会被添加到新的 List 对象或目标列表中,最终返回给调用者。
for (element in this) if (!predicate(element)) destination.add(element)
this 是一个关键字,表示当前对象或者当前正在执行的函数。在这里,this 指的是使用 filterNotTo 函数的对象,即 Iterable 类型的容器对象。for (element in this) 语句中循环遍历的就是这个容器对象 this 中的所有元素。因为这个容器实现了 Iterable 接口,所以可以直接使用 for-in 循环进行遍历。
因此,for (element in this) if (!predicate(element)) destination.add(element) 这句代码的含义是:当遍历到 this 容器对象中某个元素时,如果该元素不满足 predicate 函数的条件,那么将其添加到目标列表 destination 中去。遍历结束后,函数返回目标列表对象本身。
predicate: (T) -> Boolean 是一个函数类型(Function Type)的参数声明。具体来说,它表示接受一个 T 类型的参数,返回一个 Boolean 类型结果的函数。
这个函数类型在 filterNot() 和 filterNotTo() 函数中都被用作过滤条件。使用者可以传入一个 lambda 表达式作为参数 predicate,在这个 lambda 表达式中指定所需的过滤逻辑。
对于 predicate: (T) -> Boolean
举例来说,假设有一个整数列表 listOf(1, 2, 3, 4, 5)
,我们可以使用 filterNot() 函数来过滤出所有不是偶数的元素:
val oddNumbers = listOf(1, 2, 3, 4, 5).filterNot { it % 2 == 0 }
println(oddNumbers) // [1, 3, 5]
这里,{ it % 2 == 0 } 是一个 lambda 表达式,它接受一个整数参数 it,并返回该整数是否为偶数的布尔值。在 filterNot() 函数中,这个 lambda 表达式就作为了参数 predicate 传入。函数会遍历整个列表,对每个元素都调用一次 predicate 判断其是否符合过滤条件。对于不符合条件的元素,就会被放入到新的列表中并最终返回给用户。