java - 如何在 Kotlin 中组合 lambda

标签 java kotlin lambda collections functional-interface

我目前正在尝试将 Java lambda 表达式与 Kotlin lambda 表达式进行比较。我认为 kotlin 不需要函数式接口(interface)来创建 lambda 是一个优点。我认为概述 Java 中的所有功能接口(interface)以很好地使用 lambda 和集合操作是有一点不同的。

但我在研究过程中也发现了一个缺点。我认为 Java 中的谓词有一个默认函数,它可以让你组合一些 lambda。

所以你可以在 Java 中做这样的事情:

final Predicate<Person> isAdult = person -> person.getAge() >= 18;
final Predicate<Person> isMale = person -> person.getGender() == Gender.MALE;

// Combine 
final Predicate<Person> isAdultAndMale = isAdult.and(isMale);

我认为 Kotlin 中现在有类似的东西。我在 Head First Kotlin 中读到有一个组合函数。但它在 Kotlin Playground 中不起作用。 所以我最终得到了一个扩展函数。分别具有两个扩展功能。一个用于两个 lambda,另一个用于两个以上的 lambda 并带有可变参数。

enum class Gender{MALE, FEMALE}
enum class EyeColor{BLUE, GREEN}

data class Person(
    var name: String, 
    var age: Int, 
    var gender: Gender,
    var eyeColor: EyeColor
)

fun List<Person>.combineTwoLambdas(firstLambda: (Person) -> Boolean, secondLambda: (Person) -> Boolean): List<Person> {
    return this.filter(firstLambda).filter(secondLambda)
}

fun List<Person>.combineMoreLambdas(vararg personFilters: (Person) -> Boolean): List<Person> {
    var myPersons = listOf<Person>()

    personFilters.forEach {
        myPersons = this.filter(it)
    }

    return myPersons
}

typealias PredicatePersons = (Person) -> Boolean

fun main() {
    val persons = listOf(
        Person("Susi", 20, Gender.FEMALE, EyeColor.BLUE), 
        Person("Ralf", 19, Gender.MALE, EyeColor.BLUE),
        Person("Michael", 20, Gender.MALE, EyeColor.GREEN))

    val isAdult: (Person) -> Boolean = {person -> person.age >= 18}
    val isMale: (Person) -> Boolean = {it.gender == Gender.MALE}
    val hasGreenEyes: PredicatePersons = {it.eyeColor == EyeColor.GREEN}

    // combine two lambdas
    val isAdultAndMale = persons.combineTwoLambdas(isAdult, isMale)

    // combine more than two lambdas
    val isAdultAndMaleAndHasGreenEyes = persons.combineMoreLambdas(isAdult, isAdult, hasGreenEyes)


    print("combine all ${isAdultAndMaleAndHasGreenEyes}")
}

链接多个 lambda 是否更容易?谢谢。

更新

这是一个更新。感谢@Sweeper

val isAdultAndMale: (Person) -> Boolean = {isAdult(it) && isMale(it)}

// with alias
val isAdultAndMale: PredicatePersons = {isAdult(it) && isMale(it)}

最佳答案

您可以轻松定义 andor 的等效项作为扩展函数:

fun <T> ((T) -> Boolean).and(arg: (T) -> Boolean): (T) -> Boolean = { this(it) && arg(it) }
fun <T> ((T) -> Boolean).or(arg: (T) -> Boolean): (T) -> Boolean = { this(it) || arg(it) }

...
val isAdultAndMale = isAdult.and(isMale)

关于java - 如何在 Kotlin 中组合 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61114760/

相关文章:

Java - 继续对整数添加值

kotlin - 从 Dart 向 Kotlin 发送回调函数

android - java.lang.IllegalArgumentException : Platform class java. time.LocalDateTime(没有注释)需要显式 JsonAdapter

java - 捕获 C++ lambda 表达式错误中的 JNIENV*

python - 对多语言国家/地区名称进行排序

c# - 如何使 EqualityComparer 与两个字段进行比较?

Java EL 评估 bean 的属性

java - 为什么我的 startActivityForResult() 在将 ArrayList<String> 转换为 String[] 时返回 null?

java - 使用 list.addElement(JOptionPane.showInputDialog(); 的不兼容类型

kotlin - 如何在kotlin中将lambdas与函数式接口(interface)一起使用并直接将lambda分配给var