Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Map computeIfAbsent issue

So I found a curiosity with Java's Map computeIfAbsent (using java8) method and I hope someone can tell me why this is happening as I can not really follow the logic behind that issue.

So, I have a Map with a key (obviously) and the value is a list and I use the computeIfAbsent to create a new list when a key is not set yet. Now when I use an Integer as key I can use the following:

List<Object> list = map.computeIfAbsent(1, ArrayList::new);

But when I use a String as key trying to use

List<Object> list = map.computeIfAbsent("key", ArrayList::new);

I get the error that The method computeIfAbsent(String, Function<? super String,? extends List<Object>>) in the type Map<String,List<Object>> is not applicable for the arguments (String, ArrayList::new). Is there just the implementation missing? Using a String key I have to use the method like that, which is then working again.

List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>());

Maybe someone can enlighten me about that. Thanks :)

like image 314
Fussel Avatar asked Dec 19 '18 07:12

Fussel


People also ask

What does the computeIfAbsent () method on map do?

The computeIfAbsent(Key, Function) method of HashMap class is used to compute value for a given key using the given mapping function, if key is not already associated with a value (or is mapped to null) and enter that computed value in Hashmap else null.

Is ConcurrentHashMap computeIfAbsent thread safe?

ConcurrentHashMap is one of the most frequently used collection classes in our daily work, Its characteristic is high performance and thread-safety. However, there are two bugs that impact the performance of this familiar map. The problem is in computeIfAbsent .

What is HashMap in Java?

HashMap<K, V> is a part of Java's collection since Java 1.2. This class is found in java. util package. It provides the basic implementation of the Map interface of Java. It stores the data in (Key, Value) pairs, and you can access them by an index of another type (e.g. an Integer).


1 Answers

The mapping function - Function<? super K, ? extends V> mappingFunction - maps a key to a value, so when the key is Integer, ArrayList::new works, since ArrayList has a constructor that takes an int (the initial capacity). On the other hand, it doesn't have a constructor that takes a String.

Since the key probably shouldn't affect the initial capacity of the ArrayList, you should not use a method reference here (in both cases). Use lambda expression.

To make it clearer:

List<Object> list = map.computeIfAbsent(1, ArrayList::new);

behaves similar to:

List<Object> list = map.computeIfAbsent(1, k -> new ArrayList<>(k));

so it will create an ArrayList with initial capacity of 1.

On the other hand:

List<Object> list = map.computeIfAbsent("key", ArrayList::new);

behaves similar to:

List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));

where k is a String, so it doesn't pass compilation.

like image 178
Eran Avatar answered Sep 19 '22 16:09

Eran