RFR: 8004518 & 8010122 : Default methods on Map (original) (raw)

David Holmes david.holmes at oracle.com
Tue Apr 9 02:22:24 UTC 2013


Hi Mike,

Looking only at Map itself for now.

On 9/04/2013 4:07 AM, Mike Duigou wrote:

Hello all;

This is a combined review for the new default methods on the java.util.Map interface being added for the JSR-335 lambda libraries. The reviews are being combined because they share a common unit test. http://cr.openjdk.java.net/~mduigou/JDK-8010122/0/webrev/

General style issues:

(where has our style guide gone? I can't find it on internal or external wikis :( )

8004518: Add in-place operations to Map forEach() replaceAll()

Both of those contain the boilerplate text:

but these methods are not, and can not be, atomic in ConcurrentMap

forEach and replaceAll are very similar in terms of taking and applying a "operation" to each entry, yet their descriptions use a completely different style. forEach describes thing in general terms while replaceAll talks about calling the functions' apply method with the current entry's key and value. I would suggest for replaceAll:

"Replaces each entry's value with the result of invoking the given function on that entry, in the order entries are returned by an entry set iterator, until all entries have been processed or the function throws an exception."

This is also makes "replace" the subject rather than "apply".

forEach doesn't declare the IllegalStateException that getKey and getValue can throw.

Some/many of the @throws text has obviously been copied from the Map.Entry methods eg:

but when put into Map itself they should not be referring to "the backing map" as there is no "backing map". Further we have inconsistent terminology being used, eg getOrDefault has:

and then there is a third variant in other methods:

These should all have the same basic wording, differing only in key/value.

8010122: Add atomic operations to Map

Meaning "backport some operations from ConcurrentMap" - they aren't actually atomic in Map.

getOrDefault()

No comment

putIfAbsent() *

The default implementation throws ConcurrentModificationException but this is not declared in the spec.

remove(K, V) replace(K, V) replace(K, V, V)

No comments

compute() * merge() * computeIfAbsent() * computeIfPresent() *

The following generally apply to this group of methods.

As Peter already stated the spec:

is somewhat unclear. The parenthesized part is not connected to the function returning null or otherwise; as the function won't be called.

I find the spec for these rather confusing from a concurrency perspective - this non-concurrent interface seems to be trying to say too much about how a concurrent interface should specify behaviour. Why does it need to say:

? Note computeIfAbsent does not say the same thing.

The @implSpec does not match the actual implementation. It looks to me like these implementations are trying to cater for concurrent situations

980 * be of use when combining multiple mapped values for a key. For 981 * example. to either create or append a {@code String msg} to a

Period after example should be a comma.

Cheers, David

The * operations treat null values as being absent. (ie. the same as there being no mapping for the specified key).

The default implementations provided in Map are overridden in HashMap for performance purposes, in Hashtable for atomicity and performance purposes and in Collections for atomicity. Mike



More information about the core-libs-dev mailing list