Reputation: 2095
I want to filter a collection of values in Kotlin using an instance of a java.util.Predicate implementation, basically something like this:
val predicate = JsQueryPredicate<SportEvent>(query)
schedule.sport_events.filter(predicate)
This doesn't compile though. The following works, is that the recommended way of doing this? Feels a bit cumbersome
val predicate = JsQueryPredicate<SportEvent>(query)
schedule.sport_events.filter { predicate.test(it) }
Upvotes: 2
Views: 752
Reputation: 23242
To answer it more directly: yes... predicate.test(it)
or the nearly equivalent method reference predicate::test
are the way to go... except...
If you have to deal with Java predicates more often and/or the refactoring of the Java functional types (e.g. Predicate
) to Kotlin function types is planned in future, you may also want to add appropriate extension functions instead, e.g.:
fun <T> Iterable<T>.filter(predicate: Predicate<T>) = filter { predicate.test(it) }
With the following usage then:
val javaPredicate : Predicate<String> = Predicate { it == "hello" }
listOf("hello", "world")
.filter(javaPredicate)
If you replaced the Predicate
in future to, e.g. (T) -> Boolean
you then don't need to adapt that filter, but just replace/remove the import statement to the extension function.
Extension functions to just transform the Predicate
to an appropriate Kotlin function type are possible too, but may not help you that much in future refactorings:
operator fun <T> Predicate<T>.invoke() : (T) -> Boolean = ::test
fun <T> Predicate<T>.transform() : (T) -> Boolean = ::test
Usage samples of those:
val javaPredicate : Predicate<String> = Predicate { it == "hello" }
// variant with Predicate.invoke:
listOf("hello", "world")
.filter(javaPredicate())
// variant using Predicate.transform()
listOf("hello", "world")
.filter(javaPredicate.transform())
So I recommend you the overloaded filter
-method in case you plan a refactoring or otherwise just stick to filter { predicate.test(it) }
/filter(predicate::test)
, which might make a future refactoring a bit (IDEs help ;-)) harder.
Upvotes: 0
Reputation: 19926
You can use a method reference, which gets converted implicitly to a (T) -> Boolean
and thus allows you to call the filter
method:
schedule.sport_events.filter(predicate::test)
Upvotes: 4