Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Map.compute() take a BiFunction

I don't understand why Map.compute() and Map.computeIfPresent() take BiFunction parameters as well as Map.computeIfAbsent() a Function:

V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)

I'd expect an ordinary Function<? super V, ? extends V>, mapping the old value to a new value, resp. a Supplier<? extends V> for the new value. The caller already has the key (first argument) so the function or the supplier can already make use of it. All examples I found don't use the key. The reasons that come to my mind:

  • the key must be (effectively) final -- that's easy to manage
  • there are some fancy easy-to-use method references

But I don't believe these are viable reasons for this design. Do you have any ideas?

like image 660
steffen Avatar asked Dec 09 '15 15:12

steffen


People also ask

What is BiFunction?

Interface BiFunction<T,U,R> Represents a function that accepts two arguments and produces a result. This is the two-arity specialization of Function . This is a functional interface whose functional method is apply(Object, Object) .

What is compute in map?

The compute(Key, BiFunction) method of HashMap class allows you to update a value in HashMap. The compute() method tries to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping is found).


1 Answers

You may see computeIfPresent as the single-entry pendant of replaceAll whereas the latter requires the key as a parameter, but it’s natural to support the same function as input to both operations and the API is consistent here: it always provides the key as parameter to the function.

Generally, providing the key raises the reusability of existing functions, be it method references or ordinary class implementations (i.e. non-lambda) of the BiFunction interface. But this reusability may also affect the performance of lambda expressions given the existing JRE implementation:

As described here, lambda expressions capturing values from the surrounding context may end up in individual instances for each capturing process, whereas lambda expressions only using their parameters (non-capturing lambdas) will end up as a singleton instance. In contrast, having an otherwise unused parameter has no performance impact. So receiving the key as a parameter is preferable for that reason as well.

like image 103
Holger Avatar answered Oct 11 '22 17:10

Holger