The one thing that frustrates me about merge is that it returns the value inserted, rather than the value being replaced (as Map::put does).<p>There are good uses cases for what it does - but there are also good use cases for returning the previous value, and when i have one of those, i can't use merge, and have to fall back to a get followed by a put.<p>Perhaps what i would really like is a Rust-style entry API, where i could use a key to obtain a Map.Entry, which i could then inspect and mutate how i liked. It might look like:<p><pre><code> Entry<K, V> getOrCreateEntry(K key, Function<? super K, ? extends V> mappingFunction)
</code></pre>
And then i could write:<p><pre><code> void sell(Potato) throws FarmException { ...}
Map<Field, Potato> potatoesByField = new HashMap<>();
for (var potato: getAllPotatoes()) {
var fieldAndPotato = potatoesByField.getOrCreateEntry(potato.getField(), f -> potato);
var oldPotato = fieldAndPotato.getValue();
if (potato.getWeight() > oldPotato.getWeight()) {
potatoAndField.setValue(potato);
sell(oldPotato);
} else {
sell(potato);
}
}
</code></pre>
To collect my prize potatoes into a map, and sell the rest. Still ugly, but hey, at least it's not Go.