I'm trying to translate the following Java code:
import java.util.Comparator;
public class ComparatorTestJava {
public static void test() {
Comparator<String> cmp = (s1, s2) -> 0;
cmp = cmp.thenComparing(s -> s);
}
}
into Scala. I think this should work:
import java.util.{Comparator, function}
object ComparatorTest {
var comparator: Comparator[String] = (t1, t2) ⇒ 0
comparator = comparator.thenComparing(new function.Function[String, String] {
override def apply(t: String): String = t
})
}
But it fails with the following error:
Error:(7, 41) type mismatch;
found : java.util.function.Function[String,String]
required: java.util.Comparator[? >: String]
comparator = comparator.thenComparing(new function.Function[String, String] {
It looks like the Scala compiler is convinced I'm trying to use thenComparing(Comparator)
instead of thenComparing(Function)
. Is there any way I can tell it which it is? Or is that actually not the issue?
(I realize there are other, perhaps more idiomatic, ways to do build a comparator in Scala, but I'm interested in understanding why this fails.)
Given the definitions
the following fails with the same error as in your question:
but this compiles successfully:
This is a very common type of errors that occur regularly whenever one tries to use generic Java interfaces from Scala. The reason is that Java's use-site variance does not play well with Scala's declaration-site variance, so that Java's
Comparator<? super T>
translates into a wildcard typeComparator[_ >: T]
, and it somehow confuses the type inference algorithm (especially if you combine it with overloaded methods and SAM). However, once recognized, the problem is very easily solved by specifying the type parameters explicitly, in this case, adding an explicit[String]
is enough.