22

I need to pass a java.util.function.Predicate to a Java function. How can I implement it as Lambda in Kotlin?

The Java-Function I need to call:

public void foo(Predicate<String> p)

Java Lambda implemenation ✔ :

foo(text-> true)

Kotlin Lambda implemenation ❌:

foo{text:String -> true}  
    ^^^^^^^^^^^^ 
Type mismatch.
Required: Predicate<String>
Found:    (String) → Boolean

Kotlin-Version 1.2.21

Chriss
  • 5,157
  • 7
  • 41
  • 75

4 Answers4

20

Since Kotlin 1.4

foo({text -> true  })

or

foo {text -> true}     

Before Kotlin 1.4

These variants work:

foo(Predicate {text -> true  })  
foo(Predicate {true})
foo({true  }as Predicate<String>)
Chriss
  • 5,157
  • 7
  • 41
  • 75
3

If in case want to declare as a property:

private val normal = Predicate<Int> { true }
private val even = Predicate<Int> { it % 2 == 0 }
private val odd = even.negate()

fun main() {
 println("Normal count ${get(normal)}")
 println("Even count ${get(even)}")
 println("Odd count ${get(odd)}")

}

fun get(predicate: Predicate<Int>): Int {
 val filter = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).filter { predicate.test(it)}  
 println(filter)
 val map = filter.map { it * 2 }
 println(map)
 return map.sum()
}
KaviS
  • 31
  • 2
1

It works fine, here is a test that compiles with a Java List and the filter method that takes a Predicate as parameter:

val test = Arrays.asList("Hello", "Bye", "World!")
println(test)
println(test.filter { it.startsWith("W") })

Is the last sample code (foo{text:String -> true}) your code that does not compile?

Between the braces, your are supposed to pass the implementation of the lambda, not the type/interface of it. This part is inferred for you!

sjahan
  • 5,720
  • 3
  • 19
  • 42
  • The `filter` function is an extension function in Kotlin and takes actually not a `java.util.function.Predicate` argument, that's why your sample works for your sample but not the one in question. – Chriss Feb 22 '18 at 14:52
  • Oh! I didn't know that. I'm not currently in front of my computer, but I think I double checked it and IntelliJ confirmed me it was a predicate! Nice to know anyway, thanks for your comment :) – sjahan Feb 23 '18 at 16:00
1

As of Kotlin 1.4, there is support for Single Abstract Method (SAM) conversion for Java interfaces: https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions

From the example in the question, the following works now:

foo { text -> true }
AlexO
  • 1,311
  • 12
  • 18