Context:
I want to use the function computeIfAbsent on a Map. But, I get a compilation error when I use 
String.I get no compilation error when I use
Integer.String.Illustration:
The following statements are legal:
Map<Integer, List<Long>> map = new HashMap<>();
Integer key = Integer.valueOf(0);
Long value = Long.valueOf(2);
map.computeIfAbsent(key, ArrayList::new).add(value); // No compilation error
The following statements are illegal:
Map<String, List<Long>> map = new HashMap<>();
String key = "myKey";
Long value = Long.valueOf(2);
map.computeIfAbsent(key, ArrayList::new).add(value); // Compilation error: The type ArrayList does not define ArrayList(String) that is applicable here
The following statements are legal:
Map<String, List<Long>> map = new HashMap<>();
String key = "myKey";
Long value = Long.valueOf(2);
map.computeIfAbsent(key, x -> new ArrayList<>()).add(value); // No compilation error
Question:
I don't get why a String as key is that special when combined with method reference. Any idea?
When you call ArrayList::new instead of x -> new ArrayList<>() it's equals to call x -> new ArrayList<>(x).
Method computeIfAbsent requires lambda expression with one lambda parameter as second input argument, or a reference to method that consumes one argument of String type.
Your error
Compilation error: The type ArrayList does not define ArrayList(String) that is applicable here
is talking: you trying to call constructor with one String argument. Because, as I told above, lambda x -> someObject.method(x) is equal to someObject::method. Or lambda x -> new SomeClass(x) is equal to SomeClass::new. 
You can't use method (constructor) reference here, because here required method (constructor) that consumes one parameter, or a lambda expression. If there was lambda without any parameters, you will be able to call empty constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With