Java8高阶函数和Kotlin Lambdas互操作性

时间:2019-02-20 21:38:11

标签: kotlin functional-interface

我有一个Java示例,其中方法实现为

COUNTA(A1:A10)

IntelliJ将其自动翻译为Kotlin是

=FILTER(A1:A10, NOT(COUNTIF(QUERY({B1:B8; 
 TRANSPOSE(SPLIT(REPT("♂♀", COUNTA(A1:A10)-COUNTA(B1:B8)+1), "♀"))}, 
 "limit "&COUNTA(A1:A10), 0), A1:A10)))

(我明确了项目类型,并将其更改为0.0)

我仍然看到Java的Function和Kotlin本机lambda存在兼容性问题,但我并不是最熟悉这些问题。错误是:

enter image description here

问题是:是否可以在Kotlin中覆盖此示例上的外部Java库的Fitness()方法,如果可以,如何覆盖?

2 个答案:

答案 0 :(得分:3)

问题:

您返回的是(Kotlin)lambda ISeq<Knapsack.Item> -> Double。但这不是您想要的。您要返回Java Function<ISeq<Knapsack.Item>, Double>

解决方案:

您可以使用SAM Conversion创建一个Function

  

就像Java 8一样,Kotlin支持SAM转换。这意味着   Kotlin函数文字可以自动转换为   Java接口的单个​​非默认方法的实现,   只要接口方法的参数类型与   Kotlin函数的参数类型。

我创建了一个最小的示例来说明这一点。考虑您有一个这样的Java类:

public class Foo {
    public Function<String, Integer> getFunction() {
        return item -> Integer.valueOf(item);
    }
}

如果您想在Kotlin中覆盖getFunction,您可以这样做:

class Bar: Foo() {
    override fun getFunction(): Function<String, Int> {
        return Function {
            it.toInt()
        }
    }
}

答案 1 :(得分:1)

当返回lambda作为Java的功能接口时,必须使用显式SAM构造函数:

override fun fitness(): Function<ISeq<Item>, Double> {
    return Function { items:ISeq<Item> ->
        val sum = items.stream().collect(Item.toSum())
        if (sum.size <= _knapsackSize) sum.value else 0.0
    }
}

也不要忘记导入java.util.function.Function,因为Kotlin有自己的同名类