Home > Back-end >  Strange lambda behaviour in Java stream
Strange lambda behaviour in Java stream

Time:10-14

I created the following method that adds the given UUID value with the given Integer to teh map variable.

final Map<Integer, List<UUID>> map = new TreeMap<>();

private void addToMap(Integer key, UUID value) {
    map.computeIfAbsent(key, val -> new ArrayList<>()).add(value);
}

Normally I was tried to use map.computeIfAbsent(key, value -> new ArrayList<>()).add(value); by passing value parameter to the lambda function, it it throws "Variable 'value' is already defined in the scope" error pointing the "value" in .. value -> ... part.

My updated addToMap method is working, but I think val is pointless. So, how should this method be updated?

CodePudding user response:

Your addToMap() method implies a wrong understanding of the parameters of the computeIfAbsent() method:

private void addToMap(Integer key, UUID value) {
    map.computeIfAbsent(key, val -> new ArrayList<>()).add(value);
}

The parameter in val -> new ArrayList<>() has nothing to do with the value that you pass into addToMap()!

If you look at the JavaDoc for Map.computeIfAbsent() you can see that the second parameter is a Function<? super K,​? extends V> - i.e. a function that takes a key and returns whatever should be stored in the map.

It would be better to write the addToMap() method as

private void addToMap(Integer key, UUID value) {
    map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
}

Note that the answer from toniedzwiedz is dangerous. It only works for a Map<Integer, ?> with keys greater than or equal to zero.

It is dangerous because it basically replaces k -> new ArrayList<>() with k -> new ArrayList<>(k) - this happens to work for maps with Integer keys and uses the key value to define the initial capacity of the ArrayList.

It will not work if k is negative (new ArrayList<>(k) will throw an IllegalArgumentException if k is negative).

It will also not work for a Map<String, UUID> because there is no ArrayList constructor that takes a String argument.

  • Related