views:

332

answers:

2

Normally (ie. not concurrently), putAll() cannot be more efficient than using lot's of calls to put(), even assuming that you exclude the cost of building the other Map that you pass to putAll(). That's because putAll() will need to iterate the passed Map's elements, as well as running through the algorithm for adding each key value pair to the Map that put() executes.

But for a ConcurrentHashMap, does it make sense to construct a regular Map and then use putAll() to update it? Or should I just do 10 (or 100, or 1000) calls to put()?

Does the answer change for multiple calls to putIfAbsent()?

Thanks!

+2  A: 

The first (mostly) threadsafe Map in Java Collections was the synchronized HashMap using Collections.synchronizedMap(). It worked by only allowing one operation at a time. Java 5 added the ConcurrentHashMap, which works differently. Basically the Map is divided into slices. A put() operation will only lock the relevant slice. It also added the threadsafe primitives like putIfAbsent().

The reason I explain this is that putAll() might be more or less efficient depending on how it's implemented. It may work by locking the whole map, which may actually be more efficient than trying to obtain individual locks on every put(). Or it may work by doing a bunch of put() calls anyway, in which case there's not much difference.

So if it makes sense for your code and you're doing a lot of updates at once, I would use putAll() unless it's putIfAbsent() that you're after.

Edit: I just checked, the Java 6 ConcurrentHashMap implements putAll() as a loop of put() operations so it's no better or worse than doing this yourself.

cletus
I thought it might get one lock for all the updates, but I guess not. I'll just make individual calls to ConcurrentHashMap's `put()` and avoid the cost of building another Map.
Rudiger
Nice for checking the source, however I content the "no better or worse" as more clear code is more clear code ^^
pst
It's nice to have clearer code, but to use `putAll()` I'd have to create a new Map (which engenders multiple calls to `put()` anyway).
Rudiger
@Rudiger: then it makes sense to not create a Map.
cletus
A: 

putAll() just delegates to put(). There's no need to build up an intermediate map if you don't have it already. You can see this in the source code, and it doesn't matter what Java implementation you're using, since the code is public domain and shared by all of them.

Note that putAll() is not atomic, but merely has the guarantee that each individual put() is atomic.

Kevin Bourrillion