ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentMap.java
Revision: 1.53
Committed: Wed Dec 31 07:54:13 2014 UTC (9 years, 5 months ago) by jsr166
Branch: MAIN
Changes since 1.52: +1 -0 lines
Log Message:
standardize import statement order

File Contents

# User Rev Content
1 dl 1.2 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3 dl 1.17 * Expert Group and released to the public domain, as explained at
4 jsr166 1.31 * http://creativecommons.org/publicdomain/zero/1.0/
5 dl 1.2 */
6    
7 tim 1.1 package java.util.concurrent;
8 jsr166 1.53
9 tim 1.1 import java.util.Map;
10 dl 1.46 import java.util.Objects;
11     import java.util.function.BiConsumer;
12 dl 1.44 import java.util.function.BiFunction;
13 dl 1.46 import java.util.function.Function;
14 tim 1.1
15     /**
16 jsr166 1.43 * A {@link java.util.Map} providing thread safety and atomicity
17 dl 1.42 * guarantees.
18 dl 1.19 *
19 dl 1.46 * <p>To support atomic usages, ConcurrentMaps are expected not to
20     * allow {@code null} as a legal value (and to throw exceptions upon
21     * attempted insertions). This enables a return value of {@code null}
22     * to unambiguously indicate the absence of a mapping. This interface
23     * does not strictly forbid implementations that may hold {@code null}
24     * values. However, in any that do so, a {@code null} value must bear
25     * the same interpretation as the absence of a mapping in order to
26     * conform to method atomicity requirements. Further, any that do so
27     * must override all default method implementations.
28     *
29     * <p>Several methods (for example {@link #putIfAbsent}) inherited
30     * from {@link Map} do not have default implementations, and so must
31     * be provided by implementations of this interface, even though they
32     * have (non-atomic) default implementations in the {@link Map}
33     * interface.
34     *
35 jsr166 1.29 * <p>Memory consistency effects: As with other concurrent
36     * collections, actions in a thread prior to placing an object into a
37     * {@code ConcurrentMap} as a key or value
38     * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
39     * actions subsequent to the access or removal of that object from
40     * the {@code ConcurrentMap} in another thread.
41     *
42 dl 1.19 * <p>This interface is a member of the
43 jsr166 1.30 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
44 jsr166 1.47 * Java Collections Framework</a>.
45 jsr166 1.21 *
46 dl 1.4 * @since 1.5
47     * @author Doug Lea
48 dl 1.13 * @param <K> the type of keys maintained by this map
49 jsr166 1.21 * @param <V> the type of mapped values
50 dl 1.4 */
51 jsr166 1.47 public interface ConcurrentMap<K,V> extends Map<K,V> {
52 dl 1.41
53     /**
54     * {@inheritDoc}
55     *
56 dl 1.46 * @implNote The default implementation returns the result of
57     * {@code get(key)} unless {@code null}, in which case it returns
58     * the given defaultValue.
59     *
60     * @throws ClassCastException {@inheritDoc}
61     * @throws NullPointerException {@inheritDoc}
62     * @since 1.8
63 dl 1.41 */
64     @Override
65     default V getOrDefault(Object key, V defaultValue) {
66     V v;
67     return ((v = get(key)) != null) ? v : defaultValue;
68     }
69    
70 dl 1.46 /**
71     * {@inheritDoc}
72     *
73     * @implSpec The default implementation is equivalent to, for this
74     * {@code map}:
75 jsr166 1.52 * <pre> {@code
76 jsr166 1.49 * for (Map.Entry<K,V> entry : map.entrySet())
77 jsr166 1.52 * action.accept(entry.getKey(), entry.getValue());}</pre>
78 dl 1.46 *
79     * @implNote The default implementation assumes that {@code
80     * IllegalStateException} thrown by {@code getKey()} or {@code
81     * getValue()} indicates that the entry no longer exists.
82     * Operation continues for subsequent entries.
83     *
84     * @throws NullPointerException {@inheritDoc}
85     * @since 1.8
86     */
87     @Override
88     default void forEach(BiConsumer<? super K, ? super V> action) {
89     Objects.requireNonNull(action);
90 jsr166 1.47 for (Map.Entry<K,V> entry : entrySet()) {
91 dl 1.46 K k;
92     V v;
93     try {
94     k = entry.getKey();
95     v = entry.getValue();
96 jsr166 1.47 } catch (IllegalStateException ise) {
97 dl 1.46 // this usually means the entry is no longer in the map.
98     continue;
99     }
100     action.accept(k, v);
101     }
102     }
103    
104 tim 1.1 /**
105     * If the specified key is not already associated
106 dl 1.46 * with a value, associates it with the given value.
107 jsr166 1.51 * This is equivalent to, for this {@code map}:
108 jsr166 1.52 * <pre> {@code
109 jsr166 1.48 * if (map.containsKey(key))
110     * return map.get(key);
111     * else
112 jsr166 1.52 * return map.put(key, value);}</pre>
113 jsr166 1.36 *
114 jsr166 1.21 * except that the action is performed atomically.
115     *
116 dl 1.46 * @implNote There is no default implementation.
117     *
118 jsr166 1.24 * @param key key with which the specified value is to be associated
119     * @param value value to be associated with the specified key
120 jsr166 1.25 * @return the previous value associated with the specified key, or
121 jsr166 1.38 * {@code null} if there was no mapping for the key.
122     * (A {@code null} return can also indicate that the map
123     * previously associated {@code null} with the key,
124 jsr166 1.25 * if the implementation supports null values.)
125 jsr166 1.38 * @throws UnsupportedOperationException if the {@code put} operation
126 jsr166 1.24 * is not supported by this map
127 tim 1.1 * @throws ClassCastException if the class of the specified key or value
128 jsr166 1.24 * prevents it from being stored in this map
129     * @throws NullPointerException if the specified key or value is null,
130     * and this map does not permit null keys or values
131     * @throws IllegalArgumentException if some property of the specified key
132     * or value prevents it from being stored in this map
133 dl 1.18 */
134 jsr166 1.47 V putIfAbsent(K key, V value);
135 dl 1.6
136     /**
137 jsr166 1.21 * Removes the entry for a key only if currently mapped to a given value.
138 jsr166 1.51 * This is equivalent to, for this {@code map}:
139 jsr166 1.52 * <pre> {@code
140     * if (map.containsKey(key)
141     * && Objects.equals(map.get(key), value)) {
142 jsr166 1.36 * map.remove(key);
143     * return true;
144     * } else
145 jsr166 1.52 * return false;}</pre>
146 jsr166 1.36 *
147 dl 1.6 * except that the action is performed atomically.
148 jsr166 1.21 *
149 dl 1.46 * @implNote There is no default implementation.
150     *
151 jsr166 1.24 * @param key key with which the specified value is associated
152 jsr166 1.25 * @param value value expected to be associated with the specified key
153 jsr166 1.38 * @return {@code true} if the value was removed
154     * @throws UnsupportedOperationException if the {@code remove} operation
155 jsr166 1.24 * is not supported by this map
156 jsr166 1.25 * @throws ClassCastException if the key or value is of an inappropriate
157 jsr166 1.35 * type for this map
158 dl 1.33 * (<a href="../Collection.html#optional-restrictions">optional</a>)
159 jsr166 1.24 * @throws NullPointerException if the specified key or value is null,
160 dl 1.32 * and this map does not permit null keys or values
161 dl 1.33 * (<a href="../Collection.html#optional-restrictions">optional</a>)
162 dl 1.6 */
163 dl 1.7 boolean remove(Object key, Object value);
164 dl 1.14
165     /**
166 jsr166 1.21 * Replaces the entry for a key only if currently mapped to a given value.
167 jsr166 1.51 * This is equivalent to, for this {@code map}:
168 jsr166 1.52 * <pre> {@code
169     * if (map.containsKey(key)
170     * && Objects.equals(map.get(key), oldValue)) {
171 jsr166 1.36 * map.put(key, newValue);
172     * return true;
173     * } else
174 jsr166 1.52 * return false;}</pre>
175 jsr166 1.36 *
176 dl 1.14 * except that the action is performed atomically.
177 jsr166 1.21 *
178 dl 1.46 * @implNote There is no default implementation.
179     *
180 jsr166 1.24 * @param key key with which the specified value is associated
181     * @param oldValue value expected to be associated with the specified key
182     * @param newValue value to be associated with the specified key
183 jsr166 1.38 * @return {@code true} if the value was replaced
184     * @throws UnsupportedOperationException if the {@code put} operation
185 jsr166 1.24 * is not supported by this map
186 jsr166 1.25 * @throws ClassCastException if the class of a specified key or value
187     * prevents it from being stored in this map
188 jsr166 1.24 * @throws NullPointerException if a specified key or value is null,
189     * and this map does not permit null keys or values
190 jsr166 1.25 * @throws IllegalArgumentException if some property of a specified key
191     * or value prevents it from being stored in this map
192 dl 1.14 */
193     boolean replace(K key, V oldValue, V newValue);
194 dl 1.6
195 dl 1.15 /**
196 jsr166 1.21 * Replaces the entry for a key only if currently mapped to some value.
197 jsr166 1.51 * This is equivalent to, for this {@code map}:
198 jsr166 1.52 * <pre> {@code
199 jsr166 1.51 * if (map.containsKey(key))
200 jsr166 1.36 * return map.put(key, value);
201 jsr166 1.51 * else
202 jsr166 1.52 * return null;}</pre>
203 jsr166 1.36 *
204 dl 1.15 * except that the action is performed atomically.
205 jsr166 1.21 *
206 dl 1.46 * @implNote There is no default implementation.
207     *
208 jsr166 1.24 * @param key key with which the specified value is associated
209     * @param value value to be associated with the specified key
210 jsr166 1.25 * @return the previous value associated with the specified key, or
211 jsr166 1.38 * {@code null} if there was no mapping for the key.
212     * (A {@code null} return can also indicate that the map
213     * previously associated {@code null} with the key,
214 jsr166 1.25 * if the implementation supports null values.)
215 jsr166 1.38 * @throws UnsupportedOperationException if the {@code put} operation
216 jsr166 1.24 * is not supported by this map
217 jsr166 1.25 * @throws ClassCastException if the class of the specified key or value
218     * prevents it from being stored in this map
219 jsr166 1.24 * @throws NullPointerException if the specified key or value is null,
220     * and this map does not permit null keys or values
221 jsr166 1.25 * @throws IllegalArgumentException if some property of the specified key
222     * or value prevents it from being stored in this map
223 dl 1.15 */
224 dl 1.16 V replace(K key, V value);
225 dl 1.44
226     /**
227     * {@inheritDoc}
228     *
229 dl 1.46 * @implSpec
230     * <p>The default implementation is equivalent to, for this {@code map}:
231 jsr166 1.52 * <pre> {@code
232 jsr166 1.50 * for (Map.Entry<K,V> entry : map.entrySet()) {
233     * K k;
234     * V v;
235     * do {
236     * k = entry.getKey();
237     * v = entry.getValue();
238     * } while (!map.replace(k, v, function.apply(k, v)));
239 jsr166 1.51 * }}</pre>
240 dl 1.46 *
241     * The default implementation may retry these steps when multiple
242     * threads attempt updates, and may call the function multiple
243     * times.
244     *
245     * @throws UnsupportedOperationException {@inheritDoc}
246     * @throws NullPointerException {@inheritDoc}
247     * @throws ClassCastException {@inheritDoc}
248     * @throws IllegalArgumentException {@inheritDoc}
249     * @since 1.8
250 dl 1.44 */
251     @Override
252     default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
253 dl 1.46 Objects.requireNonNull(function);
254     forEach((k,v) -> {
255 jsr166 1.47 while (!replace(k, v, function.apply(k, v))) {
256 dl 1.46 // v changed or k is gone
257     if ( (v = get(k)) == null) {
258     // k is no longer in the map.
259     break;
260     }
261 dl 1.44 }
262 dl 1.46 });
263     }
264    
265     /**
266     * {@inheritDoc}
267     *
268     * @implSpec
269     * The default implementation is equivalent to the following steps for this
270     * {@code map}, then returning the current value or {@code null} if now
271     * absent:
272     *
273 jsr166 1.52 * <pre> {@code
274 dl 1.46 * if (map.get(key) == null) {
275 jsr166 1.51 * V newValue = mappingFunction.apply(key);
276     * if (newValue != null)
277     * return map.putIfAbsent(key, newValue);
278     * }}</pre>
279 dl 1.46 *
280     * The default implementation may retry these steps when multiple
281     * threads attempt updates, and may call the mapping function
282     * multiple times.
283     *
284     * @throws UnsupportedOperationException {@inheritDoc}
285     * @throws ClassCastException {@inheritDoc}
286     * @throws NullPointerException {@inheritDoc}
287     * @since 1.8
288     */
289     @Override
290     default V computeIfAbsent(K key,
291     Function<? super K, ? extends V> mappingFunction) {
292     Objects.requireNonNull(mappingFunction);
293     V v, newValue;
294     return ((v = get(key)) == null &&
295     (newValue = mappingFunction.apply(key)) != null &&
296     (v = putIfAbsent(key, newValue)) == null) ? newValue : v;
297     }
298 dl 1.44
299 dl 1.46 /**
300     * {@inheritDoc}
301     *
302     * @implSpec
303     * The default implementation is equivalent to performing the following
304     * steps for this {@code map}, then returning the current value or
305 jsr166 1.51 * {@code null} if now absent:
306 dl 1.46 *
307 jsr166 1.52 * <pre> {@code
308 dl 1.46 * if (map.get(key) != null) {
309 jsr166 1.51 * V oldValue = map.get(key);
310     * V newValue = remappingFunction.apply(key, oldValue);
311     * if (newValue != null)
312     * map.replace(key, oldValue, newValue);
313     * else
314     * map.remove(key, oldValue);
315     * }}</pre>
316 dl 1.46 *
317     * The default implementation may retry these steps when multiple
318     * threads attempt updates, and may call the remapping function
319     * multiple times.
320     *
321     * @throws UnsupportedOperationException {@inheritDoc}
322     * @throws ClassCastException {@inheritDoc}
323     * @throws NullPointerException {@inheritDoc}
324     * @since 1.8
325     */
326     @Override
327     default V computeIfPresent(K key,
328     BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
329     Objects.requireNonNull(remappingFunction);
330     V oldValue;
331 jsr166 1.47 while ((oldValue = get(key)) != null) {
332 dl 1.46 V newValue = remappingFunction.apply(key, oldValue);
333     if (newValue != null) {
334     if (replace(key, oldValue, newValue))
335     return newValue;
336     } else if (remove(key, oldValue))
337     return null;
338     }
339     return oldValue;
340     }
341    
342     /**
343     * {@inheritDoc}
344     *
345     * @implSpec
346     * The default implementation is equivalent to performing the following
347     * steps for this {@code map}, then returning the current value or
348     * {@code null} if absent:
349     *
350 jsr166 1.52 * <pre> {@code
351 dl 1.46 * V oldValue = map.get(key);
352     * V newValue = remappingFunction.apply(key, oldValue);
353     * if (oldValue != null ) {
354 jsr166 1.51 * if (newValue != null)
355     * map.replace(key, oldValue, newValue);
356     * else
357     * map.remove(key, oldValue);
358 dl 1.46 * } else {
359 jsr166 1.51 * if (newValue != null)
360     * map.putIfAbsent(key, newValue);
361     * else
362     * return null;
363     * }}</pre>
364 dl 1.46 *
365     * The default implementation may retry these steps when multiple
366     * threads attempt updates, and may call the remapping function
367     * multiple times.
368     *
369     * @throws UnsupportedOperationException {@inheritDoc}
370     * @throws ClassCastException {@inheritDoc}
371     * @throws NullPointerException {@inheritDoc}
372     * @since 1.8
373     */
374     @Override
375     default V compute(K key,
376     BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
377     Objects.requireNonNull(remappingFunction);
378     V oldValue = get(key);
379 jsr166 1.47 for (;;) {
380 dl 1.46 V newValue = remappingFunction.apply(key, oldValue);
381     if (newValue == null) {
382     // delete mapping
383     if (oldValue != null || containsKey(key)) {
384     // something to remove
385     if (remove(key, oldValue)) {
386     // removed the old value as expected
387     return null;
388     }
389    
390     // some other value replaced old value. try again.
391     oldValue = get(key);
392     } else {
393     // nothing to do. Leave things as they were.
394     return null;
395     }
396     } else {
397     // add or replace old mapping
398     if (oldValue != null) {
399     // replace
400     if (replace(key, oldValue, newValue)) {
401     // replaced as expected.
402     return newValue;
403     }
404    
405     // some other value replaced old value. try again.
406     oldValue = get(key);
407     } else {
408     // add (replace if oldValue was null)
409     if ((oldValue = putIfAbsent(key, newValue)) == null) {
410     // replaced
411     return newValue;
412     }
413    
414     // some other value replaced old value. try again.
415     }
416 dl 1.44 }
417     }
418     }
419    
420 dl 1.46 /**
421     * {@inheritDoc}
422     *
423     * @implSpec
424     * The default implementation is equivalent to performing the following
425     * steps for this {@code map}, then returning the current value or
426     * {@code null} if absent:
427     *
428 jsr166 1.52 * <pre> {@code
429 dl 1.46 * V oldValue = map.get(key);
430     * V newValue = (oldValue == null) ? value :
431 jsr166 1.51 * remappingFunction.apply(oldValue, value);
432 dl 1.46 * if (newValue == null)
433 jsr166 1.51 * map.remove(key);
434 dl 1.46 * else
435 jsr166 1.52 * map.put(key, newValue);}</pre>
436 dl 1.46 *
437     * The default implementation may retry these steps when multiple
438     * threads attempt updates, and may call the remapping function
439     * multiple times.
440     *
441     * @throws UnsupportedOperationException {@inheritDoc}
442     * @throws ClassCastException {@inheritDoc}
443     * @throws NullPointerException {@inheritDoc}
444     * @since 1.8
445     */
446     @Override
447     default V merge(K key, V value,
448     BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
449     Objects.requireNonNull(remappingFunction);
450     Objects.requireNonNull(value);
451     V oldValue = get(key);
452     for (;;) {
453     if (oldValue != null) {
454     V newValue = remappingFunction.apply(oldValue, value);
455     if (newValue != null) {
456     if (replace(key, oldValue, newValue))
457     return newValue;
458     } else if (remove(key, oldValue)) {
459     return null;
460     }
461     oldValue = get(key);
462     } else {
463     if ((oldValue = putIfAbsent(key, value)) == null) {
464     return value;
465     }
466     }
467     }
468     }
469 tim 1.1 }