While initializing collections like TreeMap
, TreeSet
, etc. We can add our custom comparator.
The code looks something like:
Map<Integer, String> map1 = new TreeMap<>(new Comparator<Integer>() {
public int compare(Integer x, Integer y) {
return x-y;
}
});
Now, we can make replace this anonymous implementation with a lambda expression. The code would look like:
Map<Integer, String> map2 = new TreeMap<>((x,y) -> x-y);
Java-8 allows you to store lambda expressions in a variable through functional interfaces. So, I modified the above code to the following:
BiFunction<Integer, Integer, Integer> myComparator = (x,y) -> x-y;
Map<Integer, String> map3 = new TreeMap<>(myComparator);
But this last attempt did not work! It gave the following error:
Cannot infer type arguments for TreeMap<>
Why did it fail to resolve types in the last example?
Note: To confirm that this is not an IDE bug, I performed a raw compile using javac
and it still gave the same error.
Although the lambda expression seems the same, the BiFunction
is not the Comparator
therefore you cannot interchange them.
Comparator<Integer> comparator = (x,y) -> x - y;
Map<Integer, String> map3 = new TreeMap<>(comparator);
Let's take a look deeper into these interfaces and implement them using an anonymous class:
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer x, Integer y) {
return x - y;
}
};
BiFunction<Integer, Integer, Integer> biFun = new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(final Integer x, final Integer y) {
return x - y;
}
};
The difference is also the name of the method. TreeMap
expects Comparator
in its constructor because its internal implementation will call compare
according to the contract with Comparator
.
By the way, the BinaryOperator<T>
results in the same lambda expression as well.