I posted an answer here where the code demonstrating use of the putIfAbsent method of ConcurrentMap read:
ConcurrentMap<String, AtomicLong> map = new ConcurrentHashMap<String, AtomicLong> ();
public long addTo(String key, long value) {
// The final value it became.
long result = value;
// Make a new one to put in the map.
AtomicLong newValue = new AtomicLong(value);
// Insert my new one or get me the old one.
AtomicLong oldValue = map.putIfAbsent(key, newValue);
// Was it already there? Note the deliberate use of '!='.
if ( oldValue != newValue ) {
// Update it.
result = oldValue.addAndGet(value);
}
return result;
}
The main downside of this approach is that you have to create a new object to put into the map whether it will be used or not. This can have significant effect if the object is heavy.
It occurred to me that this would be an opportunity to use Lambdas. I have not downloaded Java 8 n’or will I be able to until it is official (company policy) so I cannot test this but would something like this be valid and effective?
public long addTo(String key, long value) {
return map.putIfAbsent( key, () -> new AtomicLong(0) ).addAndGet(value);
}
I am hoping to use the lambda to delay the evaluation of the new AtomicLong(0) until it is actually determined that it should be created because it does not exist in the map.
As you can see this is much more succinct and functional.
Essentially I suppose my questions are:
- Will this work?
- Or have I completely misinterpreted lambdas?
- Might something like this work one day?
UPDATE 2015-08-01
The
computeIfAbsentmethod as described below has indeed been added to Java SE 8. The semantics appear to be very close to the pre-release version.In addition,
computeIfAbsent, along with a whole pile of new default methods, has been added to theMapinterface. Of course, maps in general can’t support atomic updates, but the new methods add considerable convenience to the API.What you’re trying to do is quite reasonable, but unfortunately it doesn’t work with the current version of
ConcurrentMap. An enhancement is on the way, however. The new version of the concurrency library includesConcurrentHashMapV8which contains a new methodcomputeIfAbsent. This pretty much allows you to do exactly what you’re looking to do. Using this new method, your example could be rewritten as follows:For further information about the
ConcurrentHashMapV8, see Doug Lea’s initial announcement thread on the concurrency-interest mailing list. Several messages down the thread is a followup message that shows an example very similar to what you’re trying to do. (Note however the old lambda syntax. That message was from August 2011 after all.) And here is recent javadoc forConcurrentHashMapV8.This work is intended to be integrated into Java 8, but it hasn’t yet as far as I can see. Also, this is still a work in progress, names and specs may change, etc.