< prev index next >

src/java.base/share/classes/java/util/Map.java

Print this page
rev 47953 : 8177290: add copy factory methods for unmodifiable List, Set, Map
8184690: add Collectors for collecting into unmodifiable List, Set, and Map
Reviewed-by: alanb, briangoetz, dholmes, jrose, rriggs, scolebourne

*** 108,128 **** * indirectly contains itself. This includes the {@code clone()}, * {@code equals()}, {@code hashCode()} and {@code toString()} methods. * Implementations may optionally handle the self-referential scenario, however * most current implementations do not do so. * ! * <h2><a id="immutable">Immutable Map Static Factory Methods</a></h2> ! * <p>The {@link Map#of() Map.of()} and ! * {@link Map#ofEntries(Map.Entry...) Map.ofEntries()} ! * static factory methods provide a convenient way to create immutable maps. * The {@code Map} * instances created by these methods have the following characteristics: * * <ul> ! * <li>They are <em>structurally immutable</em>. Keys and values cannot be added, ! * removed, or updated. Calling any mutator method will always cause ! * {@code UnsupportedOperationException} to be thrown. * However, if the contained keys or values are themselves mutable, this may cause the * Map to behave inconsistently or its contents to appear to change. * <li>They disallow {@code null} keys and values. Attempts to create them with * {@code null} keys or values result in {@code NullPointerException}. * <li>They are serializable if all keys and values are serializable. --- 108,129 ---- * indirectly contains itself. This includes the {@code clone()}, * {@code equals()}, {@code hashCode()} and {@code toString()} methods. * Implementations may optionally handle the self-referential scenario, however * most current implementations do not do so. * ! * <h2><a id="unmodifiable">Unmodifiable Maps</a></h2> ! * <p>The {@link Map#of() Map.of}, ! * {@link Map#ofEntries(Map.Entry...) Map.ofEntries}, and ! * {@link Map#copyOf Map.copyOf} ! * static factory methods provide a convenient way to create unmodifiable maps. * The {@code Map} * instances created by these methods have the following characteristics: * * <ul> ! * <li>They are <a href="Collection.html#unmodifiable"><i>unmodifiable</i></a>. Keys and values ! * cannot be added, removed, or updated. Calling any mutator method on the Map ! * will always cause {@code UnsupportedOperationException} to be thrown. * However, if the contained keys or values are themselves mutable, this may cause the * Map to behave inconsistently or its contents to appear to change. * <li>They disallow {@code null} keys and values. Attempts to create them with * {@code null} keys or values result in {@code NullPointerException}. * <li>They are serializable if all keys and values are serializable.
*** 1274,1285 **** } return newValue; } /** ! * Returns an immutable map containing zero mappings. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @return an empty {@code Map} * --- 1275,1286 ---- } return newValue; } /** ! * Returns an unmodifiable map containing zero mappings. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @return an empty {@code Map} *
*** 1288,1299 **** static <K, V> Map<K, V> of() { return ImmutableCollections.Map0.instance(); } /** ! * Returns an immutable map containing a single mapping. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the mapping's key * @param v1 the mapping's value --- 1289,1300 ---- static <K, V> Map<K, V> of() { return ImmutableCollections.Map0.instance(); } /** ! * Returns an unmodifiable map containing a single mapping. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the mapping's key * @param v1 the mapping's value
*** 1305,1316 **** static <K, V> Map<K, V> of(K k1, V v1) { return new ImmutableCollections.Map1<>(k1, v1); } /** ! * Returns an immutable map containing two mappings. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value --- 1306,1317 ---- static <K, V> Map<K, V> of(K k1, V v1) { return new ImmutableCollections.Map1<>(k1, v1); } /** ! * Returns an unmodifiable map containing two mappings. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value
*** 1325,1336 **** static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2); } /** ! * Returns an immutable map containing three mappings. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value --- 1326,1337 ---- static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2); } /** ! * Returns an unmodifiable map containing three mappings. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value
*** 1347,1358 **** static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3); } /** ! * Returns an immutable map containing four mappings. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value --- 1348,1359 ---- static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3); } /** ! * Returns an unmodifiable map containing four mappings. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value
*** 1371,1382 **** static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4); } /** ! * Returns an immutable map containing five mappings. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value --- 1372,1383 ---- static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4); } /** ! * Returns an unmodifiable map containing five mappings. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value
*** 1397,1408 **** static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); } /** ! * Returns an immutable map containing six mappings. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value --- 1398,1409 ---- static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5); } /** ! * Returns an unmodifiable map containing six mappings. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value
*** 1427,1438 **** return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6); } /** ! * Returns an immutable map containing seven mappings. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value --- 1428,1439 ---- return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6); } /** ! * Returns an unmodifiable map containing seven mappings. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value
*** 1459,1470 **** return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7); } /** ! * Returns an immutable map containing eight mappings. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value --- 1460,1471 ---- return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7); } /** ! * Returns an unmodifiable map containing eight mappings. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value
*** 1493,1504 **** return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8); } /** ! * Returns an immutable map containing nine mappings. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value --- 1494,1505 ---- return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8); } /** ! * Returns an unmodifiable map containing nine mappings. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value
*** 1529,1540 **** return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9); } /** ! * Returns an immutable map containing ten mappings. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value --- 1530,1541 ---- return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9); } /** ! * Returns an unmodifiable map containing ten mappings. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @param <K> the {@code Map}'s key type * @param <V> the {@code Map}'s value type * @param k1 the first mapping's key * @param v1 the first mapping's value
*** 1567,1579 **** return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); } /** ! * Returns an immutable map containing keys and values extracted from the given entries. * The entries themselves are not stored in the map. ! * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details. * * @apiNote * It is convenient to create the map entries using the {@link Map#entry Map.entry()} method. * For example, * --- 1568,1580 ---- return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10); } /** ! * Returns an unmodifiable map containing keys and values extracted from the given entries. * The entries themselves are not stored in the map. ! * See <a href="#unmodifiable">Unmodifiable Maps</a> for details. * * @apiNote * It is convenient to create the map entries using the {@link Map#entry Map.entry()} method. * For example, *
*** 1600,1635 **** * @since 9 */ @SafeVarargs @SuppressWarnings("varargs") static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) { ! if (entries.length == 0) { // implicit null check of entries return ImmutableCollections.Map0.instance(); } else if (entries.length == 1) { return new ImmutableCollections.Map1<>(entries[0].getKey(), entries[0].getValue()); } else { Object[] kva = new Object[entries.length << 1]; int a = 0; for (Entry<? extends K, ? extends V> entry : entries) { kva[a++] = entry.getKey(); kva[a++] = entry.getValue(); } return new ImmutableCollections.MapN<>(kva); } } /** ! * Returns an immutable {@link Entry} containing the given key and value. * These entries are suitable for populating {@code Map} instances using the * {@link Map#ofEntries Map.ofEntries()} method. * The {@code Entry} instances created by this method have the following characteristics: * * <ul> * <li>They disallow {@code null} keys and values. Attempts to create them using a {@code null} * key or value result in {@code NullPointerException}. ! * <li>They are immutable. Calls to {@link Entry#setValue Entry.setValue()} * on a returned {@code Entry} result in {@code UnsupportedOperationException}. * <li>They are not serializable. * <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>. * Callers should make no assumptions about the identity of the returned instances. * This method is free to create new instances or reuse existing ones. Therefore, --- 1601,1638 ---- * @since 9 */ @SafeVarargs @SuppressWarnings("varargs") static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) { ! if (entries.length == 0) { // implicit null check of entries array return ImmutableCollections.Map0.instance(); } else if (entries.length == 1) { + // implicit null check of the array slot return new ImmutableCollections.Map1<>(entries[0].getKey(), entries[0].getValue()); } else { Object[] kva = new Object[entries.length << 1]; int a = 0; for (Entry<? extends K, ? extends V> entry : entries) { + // implicit null checks of each array slot kva[a++] = entry.getKey(); kva[a++] = entry.getValue(); } return new ImmutableCollections.MapN<>(kva); } } /** ! * Returns an unmodifiable {@link Entry} containing the given key and value. * These entries are suitable for populating {@code Map} instances using the * {@link Map#ofEntries Map.ofEntries()} method. * The {@code Entry} instances created by this method have the following characteristics: * * <ul> * <li>They disallow {@code null} keys and values. Attempts to create them using a {@code null} * key or value result in {@code NullPointerException}. ! * <li>They are unmodifiable. Calls to {@link Entry#setValue Entry.setValue()} * on a returned {@code Entry} result in {@code UnsupportedOperationException}. * <li>They are not serializable. * <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>. * Callers should make no assumptions about the identity of the returned instances. * This method is free to create new instances or reuse existing ones. Therefore,
*** 1653,1658 **** --- 1656,1687 ---- */ static <K, V> Entry<K, V> entry(K k, V v) { // KeyValueHolder checks for nulls return new KeyValueHolder<>(k, v); } + + /** + * Returns an <a href="#unmodifiable">unmodifiable Map</a> containing the entries + * of the given Map. The given Map must not be null, and it must not contain any + * null keys or values. If the given Map is subsequently modified, the returned + * Map will not reflect such modifications. + * + * @implNote + * If the given Map is an <a href="#unmodifiable">unmodifiable Map</a>, + * calling copyOf will generally not create a copy. + * + * @param <K> the {@code Map}'s key type + * @param <V> the {@code Map}'s value type + * @param map a {@code Map} from which entries are drawn, must be non-null + * @return a {@code Map} containing the entries of the given {@code Map} + * @throws NullPointerException if map is null, or if it contains any null keys or values + * @since 10 + */ + @SuppressWarnings({"rawtypes","unchecked"}) + static <K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map) { + if (map instanceof ImmutableCollections.AbstractImmutableMap) { + return (Map<K,V>)map; + } else { + return (Map<K,V>)Map.ofEntries(map.entrySet().toArray(new Entry[0])); + } + } }
< prev index next >