Both calls are correct:
Collectors.groupingBy((String s)->s.toLowerCase(),Collectors.counting());
Collectors.groupingBy((String s)->s.toLowerCase(Locale.ENGLISH),Collectors.counting());
Since then, why the following one is wrong:
Collectors.groupingBy(String::toLowerCase,Collectors.counting());
after all String::toLowerCase
can not correspond to the second one... Then why IntelliJ says Reference to 'toLowerCase' is ambiguous, both 'toLowerCase(Locale)' and 'toLowerCase()' match
?
String::toLowerCase
must be unambiguously resolved to (String s)->s.toLowerCase()
or did I miss something?
Of course if I put more context to IntelliJ like:
Collector<String,?,Map<String,Long>> c = Collectors.groupingBy(String::toLowerCase,Collectors.counting());
that is correct, but alas in Java 10 var inference type context it is wrong:
var c = Collectors.groupingBy(String::toLowerCase,Collectors.counting());
I understand that compiler can not infer the input type of counting
. If I write:
Collector<String,?,Long> counter = Collectors.counting();
var c = Collectors.groupingBy(String::toLowerCase,counter);
it it correct. Thus again, why compiler is not able to infer the only acceptable form?
-------EDIT--------
I used IntelliJ/compiler interchangeably just because I used IntelliJ first and error reported was :
Reference to 'toLowerCase' is ambiguous, both 'toLowerCase(Locale)' and 'toLowerCase()' match
Compiler's error was much much more unreadable (but contains more hints on why inference fails), something like:
Demo.java:31: error: incompatible types: cannot infer type-variable(s) T#1,K,A,D,CAP#1,T#2
Collectors.groupingBy(String::toLowerCase,Collectors.counting());
^
(argument mismatch; invalid method reference
incompatible types: Object cannot be converted to Locale)
where T#1,K,A,D,T#2 are type-variables:
T#1 extends Object declared in method <T#1,K,A,D>groupingBy(Function<? super T#1,? extends K>,Collector<? super T#1,A,D>)
K extends Object declared in method <T#1,K,A,D>groupingBy(Function<? super T#1,? extends K>,Collector<? super T#1,A,D>)
A extends Object declared in method <T#1,K,A,D>groupingBy(Function<? super T#1,? extends K>,Collector<? super T#1,A,D>)
D extends Object declared in method <T#1,K,A,D>groupingBy(Function<? super T#1,? extends K>,Collector<? super T#1,A,D>)
T#2 extends Object declared in method <T#2>counting()
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
This is compiler "weakness", at least until this JEP is in place.
I have already answered almost the same exact question here. There is also another answer from JDK core developers too.
There is also yet another question that is very close to yours.
What matters is that this is known to cause a problem, at times, but has a trivial solution - use a lambda
, and thus an explicit type, according to the JLS
.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments