I am trying to sort List
of employees by name then age using Java8 Comparator
, I have created below Comparator
but it gives me a compiler error
Type mismatch: cannot convert from Comparator<Object> to <unknown>
Comparator<String> c = Comparator.comparing(s -> s.split("\\s+")[0])
.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1])); //compile error
but it works if I explicitly specify the Type
Comparator<String> c = Comparator.<String, String> comparing(s -> s.split("\\s+")[0])
.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1])); //works
or by creating two Compartor
s and chain
Comparator<String> name = Comparator.comparing(s -> s.split("\\s+")[0]);
Comparator<String> age = Comparator.comparingInt(s -> Integer.parseInt(s.split("\\s+")[1]));
Comparator<String> cc = name.thenComparing(age); //works
I have specified the type Comparator<String>
on the left side but why auto type inference is not finding the correct Type and expecting to specify explicitly.
Could someone clarify on this?
Here is the code
String[] arr = { "alan 25", "mario 30", "alan 19", "mario 25" };
Comparator<String> c = Comparator.<String, String> comparing(s -> s.split("\\s+")[0])
.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1]));
List<String> sorted = Arrays.stream(arr).sorted(c).collect(Collectors.toList());
System.out.println(sorted);
output
[alan 19, alan 25, mario 25, mario 30]
Java needs to know a type of all variables. In many lambdas it can infer a type, but in your first code snippet, it cannot guess the type of
s
. I think the standard way to solve that problem would be to declare it explicitly:If you look at this answer, it has a similar type declaration in the argument to
Comparator.comparing()
.Your method, explicitly giving the type arguments of
comparing()
, obviously works too.For your other method, declaring two comparators, I am pretty confident that in this case Java can infer from the
String
on the left side of the assignment, just as in the conventionalList <String> = new ArrayList<>();
. When you go on to callthenComparing()
in the same expression, Java can no longer see that the type from the left side is relevant. It would be a bit likeint size = new ArrayList<>().size();
This works too: