ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentMap.java
Revision: 1.70
Committed: Mon Oct 1 00:10:53 2018 UTC (5 years, 8 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.69: +3 -3 lines
Log Message:
update to using jdk11 by default, except link to jdk10 javadocs;
sync @docRoot references in javadoc with upstream

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