src/share/classes/java/util/Collections.java

Print this page
rev 6858 : 8004518: Add in-place operations to Map
8010122: Add defaults for ConcurrentMap operations to Map
Reviewed-by: darcy, briangoetz, mduigou, dholmes, ulfzibis
Contributed-by: Doug Lea <dl at cs.oswego.edu>, Henry Jen <henry.jen@oracle.com>, Akhil Arora <akhil.arora@oracle.com>, Peter Levart <peter.levart@gmail.com>

*** 26,35 **** --- 26,38 ---- package java.util; import java.io.Serializable; import java.io.ObjectOutputStream; import java.io.IOException; import java.lang.reflect.Array; + import java.util.function.BiConsumer; + import java.util.function.BiFunction; + import java.util.function.Function; /** * This class consists exclusively of static methods that operate on or return * collections. It contains polymorphic algorithms that operate on * collections, "wrappers", which return a new collection backed by a
*** 1389,1398 **** --- 1392,1462 ---- public boolean equals(Object o) {return o == this || m.equals(o);} public int hashCode() {return m.hashCode();} public String toString() {return m.toString();} + // Override default methods in Map + @Override + @SuppressWarnings("unchecked") + public V getOrDefault(Object k, V defaultValue) { + // Safe cast as we don't change the value + return ((Map<K, V>) m).getOrDefault(k, defaultValue); + } + + @Override + public void forEach(BiConsumer<? super K, ? super V> action) { + m.forEach(action); + } + + @Override + public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { + throw new UnsupportedOperationException(); + } + + @Override + public V putIfAbsent(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean replace(K key, V oldValue, V newValue) { + throw new UnsupportedOperationException(); + } + + @Override + public V replace(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { + throw new UnsupportedOperationException(); + } + + @Override + public V computeIfPresent(K key, + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + throw new UnsupportedOperationException(); + } + + @Override + public V compute(K key, + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + throw new UnsupportedOperationException(); + } + + @Override + public V merge(K key, V value, + BiFunction<? super V, ? super V, ? extends V> remappingFunction) { + throw new UnsupportedOperationException(); + } + /** * We need this class in addition to UnmodifiableSet as * Map.Entries themselves permit modification of the backing Map * via their setValue operation. This class is subtle: there are * many possible attacks that must be thwarted.
*** 1588,1600 **** * foo(i.next()); * } * </pre> * Failure to follow this advice may result in non-deterministic behavior. * ! * <p>The returned collection does <i>not</i> pass the <tt>hashCode</tt> ! * and <tt>equals</tt> operations through to the backing collection, but ! * relies on <tt>Object</tt>'s equals and hashCode methods. This is * necessary to preserve the contracts of these operations in the case * that the backing collection is a set or a list.<p> * * The returned collection will be serializable if the specified collection * is serializable. --- 1652,1664 ---- * foo(i.next()); * } * </pre> * Failure to follow this advice may result in non-deterministic behavior. * ! * <p>The returned collection does <i>not</i> pass the {@code hashCode} ! * and {@code equals} operations through to the backing collection, but ! * relies on {@code Object}'s equals and hashCode methods. This is * necessary to preserve the contracts of these operations in the case * that the backing collection is a set or a list.<p> * * The returned collection will be serializable if the specified collection * is serializable.
*** 2105,2114 **** --- 2169,2229 ---- synchronized (mutex) {return m.hashCode();} } public String toString() { synchronized (mutex) {return m.toString();} } + + // Override default methods in Map + @Override + public V getOrDefault(Object k, V defaultValue) { + synchronized (mutex) {return m.getOrDefault(k, defaultValue);} + } + @Override + public void forEach(BiConsumer<? super K, ? super V> action) { + synchronized (mutex) {m.forEach(action);} + } + @Override + public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { + synchronized (mutex) {m.replaceAll(function);} + } + @Override + public V putIfAbsent(K key, V value) { + synchronized (mutex) {return m.putIfAbsent(key, value);} + } + @Override + public boolean remove(Object key, Object value) { + synchronized (mutex) {return m.remove(key, value);} + } + @Override + public boolean replace(K key, V oldValue, V newValue) { + synchronized (mutex) {return m.replace(key, oldValue, newValue);} + } + @Override + public V replace(K key, V value) { + synchronized (mutex) {return m.replace(key, value);} + } + @Override + public V computeIfAbsent(K key, + Function<? super K, ? extends V> mappingFunction) { + synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);} + } + @Override + public V computeIfPresent(K key, + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);} + } + @Override + public V compute(K key, + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + synchronized (mutex) {return m.compute(key, remappingFunction);} + } + @Override + public V merge(K key, V value, + BiFunction<? super V, ? super V, ? extends V> remappingFunction) { + synchronized (mutex) {return m.merge(key, value, remappingFunction);} + } + private void writeObject(ObjectOutputStream s) throws IOException { synchronized (mutex) {s.defaultWriteObject();} } }
*** 2715,2724 **** --- 2830,2850 ---- if (value != null && !valueType.isInstance(value)) throw new ClassCastException(badValueMsg(value)); } + private BiFunction<? super K, ? super V, ? extends V> typeCheck( + BiFunction<? super K, ? super V, ? extends V> func) + { + Objects.requireNonNull(func); + return (k, v) -> { + V newValue = func.apply(k, v); + typeCheck(k, newValue); + return newValue; + }; + } + private String badKeyMsg(Object key) { return "Attempt to insert " + key.getClass() + " key into map with key type " + keyType; }
*** 2780,2789 **** --- 2906,2983 ---- if (entrySet==null) entrySet = new CheckedEntrySet<>(m.entrySet(), valueType); return entrySet; } + // Override default methods in Map + @Override + public void forEach(BiConsumer<? super K, ? super V> action) { + m.forEach(action); + } + + @Override + public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { + m.replaceAll(typeCheck(function)); + } + + @Override + public V putIfAbsent(K key, V value) { + typeCheck(key, value); + return m.putIfAbsent(key, value); + } + + @Override + public boolean remove(Object key, Object value) { + return m.remove(key, value); + } + + @Override + public boolean replace(K key, V oldValue, V newValue) { + typeCheck(key, newValue); + return m.replace(key, oldValue, newValue); + } + + @Override + public V replace(K key, V value) { + typeCheck(key, value); + return m.replace(key, value); + } + + @Override + public V computeIfAbsent(K key, + Function<? super K, ? extends V> mappingFunction) { + Objects.requireNonNull(mappingFunction); + return m.computeIfAbsent(key, k -> { + V value = mappingFunction.apply(k); + typeCheck(k, value); + return value; + }); + } + + @Override + public V computeIfPresent(K key, + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + return m.computeIfPresent(key, typeCheck(remappingFunction)); + } + + @Override + public V compute(K key, + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + return m.compute(key, typeCheck(remappingFunction)); + } + + @Override + public V merge(K key, V value, + BiFunction<? super V, ? super V, ? extends V> remappingFunction) { + Objects.requireNonNull(remappingFunction); + return m.merge(key, value, (v1, v2) -> { + V newValue = remappingFunction.apply(v1, v2); + typeCheck(null, newValue); + return newValue; + }); + } + /** * We need this class in addition to CheckedSet as Map.Entry permits * modification of the backing Map via the setValue operation. This * class is subtle: there are many possible attacks that must be * thwarted.
*** 3454,3463 **** --- 3648,3718 ---- return (o instanceof Map) && ((Map<?,?>)o).isEmpty(); } public int hashCode() {return 0;} + // Override default methods in Map + @Override + @SuppressWarnings("unchecked") + public V getOrDefault(Object k, V defaultValue) { + return defaultValue; + } + + @Override + public void forEach(BiConsumer<? super K, ? super V> action) { + Objects.requireNonNull(action); + } + + @Override + public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { + Objects.requireNonNull(function); + } + + @Override + public V putIfAbsent(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean replace(K key, V oldValue, V newValue) { + throw new UnsupportedOperationException(); + } + + @Override + public V replace(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public V computeIfAbsent(K key, + Function<? super K, ? extends V> mappingFunction) { + throw new UnsupportedOperationException(); + } + + @Override + public V computeIfPresent(K key, + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + throw new UnsupportedOperationException(); + } + + @Override + public V compute(K key, + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + throw new UnsupportedOperationException(); + } + + @Override + public V merge(K key, V value, + BiFunction<? super V, ? super V, ? extends V> remappingFunction) { + throw new UnsupportedOperationException(); + } + // Preserves singleton property private Object readResolve() { return EMPTY_MAP; } }
*** 3617,3626 **** --- 3872,3940 ---- if (values==null) values = singleton(v); return values; } + // Override default methods in Map + @Override + public V getOrDefault(Object key, V defaultValue) { + return eq(key, k) ? v : defaultValue; + } + + @Override + public void forEach(BiConsumer<? super K, ? super V> action) { + action.accept(k, v); + } + + @Override + public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { + throw new UnsupportedOperationException(); + } + + @Override + public V putIfAbsent(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean replace(K key, V oldValue, V newValue) { + throw new UnsupportedOperationException(); + } + + @Override + public V replace(K key, V value) { + throw new UnsupportedOperationException(); + } + + @Override + public V computeIfAbsent(K key, + Function<? super K, ? extends V> mappingFunction) { + throw new UnsupportedOperationException(); + } + + @Override + public V computeIfPresent(K key, + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + throw new UnsupportedOperationException(); + } + + @Override + public V compute(K key, + BiFunction<? super K, ? super V, ? extends V> remappingFunction) { + throw new UnsupportedOperationException(); + } + + @Override + public V merge(K key, V value, + BiFunction<? super V, ? super V, ? extends V> remappingFunction) { + throw new UnsupportedOperationException(); + } } // Miscellaneous /**