--- jsr166/src/main/java/util/Map.java 2015/12/14 21:15:46 1.2
+++ jsr166/src/main/java/util/Map.java 2015/12/16 03:15:28 1.3
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -110,6 +110,31 @@ import java.io.Serializable;
* Implementations may optionally handle the self-referential scenario, however
* most current implementations do not do so.
*
+ *
+ * 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:
+ *
+ *
+ * - They are structurally immutable. Keys and values cannot be added,
+ * removed, or updated. Attempts to do so result in {@code UnsupportedOperationException}.
+ * 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.
+ *
- They disallow {@code null} keys and values. Attempts to create them with
+ * {@code null} keys or values result in {@code NullPointerException}.
+ *
- They are serializable if all keys and values are serializable.
+ *
- They reject duplicate keys at creation time. Duplicate keys
+ * passed to a static factory method result in {@code IllegalArgumentException}.
+ *
- The iteration order of mappings is unspecified and is subject to change.
+ *
- They are value-based.
+ * Callers should make no assumptions about the identity of the returned instances.
+ * Factories are free to create new instances or reuse existing ones. Therefore,
+ * identity-sensitive operations on these instances (reference equality ({@code ==}),
+ * identity hash code, and synchronization) are unreliable and should be avoided.
+ *
+ *
* This interface is a member of the
*
* Java Collections Framework.
@@ -126,7 +151,7 @@ import java.io.Serializable;
* @see Set
* @since 1.2
*/
-public interface Map {
+public interface Map {
// Query Operations
/**
@@ -157,10 +182,10 @@ public interface Map {
* key
* @throws ClassCastException if the key is of an inappropriate type for
* this map
- * (optional)
+ * (optional)
* @throws NullPointerException if the specified key is null and this map
* does not permit null keys
- * (optional)
+ * (optional)
*/
boolean containsKey(Object key);
@@ -177,10 +202,10 @@ public interface Map {
* specified value
* @throws ClassCastException if the value is of an inappropriate type for
* this map
- * (optional)
+ * (optional)
* @throws NullPointerException if the specified value is null and this
* map does not permit null values
- * (optional)
+ * (optional)
*/
boolean containsValue(Object value);
@@ -205,10 +230,10 @@ public interface Map {
* {@code null} if this map contains no mapping for the key
* @throws ClassCastException if the key is of an inappropriate type for
* this map
- * (optional)
+ * (optional)
* @throws NullPointerException if the specified key is null and this map
* does not permit null keys
- * (optional)
+ * (optional)
*/
V get(Object key);
@@ -265,10 +290,10 @@ public interface Map {
* is not supported by this map
* @throws ClassCastException if the key is of an inappropriate type for
* this map
- * (optional)
+ * (optional)
* @throws NullPointerException if the specified key is null and this
* map does not permit null keys
- * (optional)
+ * (optional)
*/
V remove(Object key);
@@ -373,7 +398,7 @@ public interface Map {
* @see Map#entrySet()
* @since 1.2
*/
- interface Entry {
+ interface Entry {
/**
* Returns the key corresponding to this entry.
*
@@ -468,7 +493,7 @@ public interface Map {
* @see Comparable
* @since 1.8
*/
- public static , V> Comparator> comparingByKey() {
+ public static , V> Comparator> comparingByKey() {
return (Comparator> & Serializable)
(c1, c2) -> c1.getKey().compareTo(c2.getKey());
}
@@ -485,7 +510,7 @@ public interface Map {
* @see Comparable
* @since 1.8
*/
- public static > Comparator> comparingByValue() {
+ public static > Comparator> comparingByValue() {
return (Comparator> & Serializable)
(c1, c2) -> c1.getValue().compareTo(c2.getValue());
}
@@ -578,10 +603,10 @@ public interface Map {
* {@code defaultValue} if this map contains no mapping for the key
* @throws ClassCastException if the key is of an inappropriate type for
* this map
- * (optional)
+ * (optional)
* @throws NullPointerException if the specified key is null and this map
* does not permit null keys
- * (optional)
+ * (optional)
* @since 1.8
*/
default V getOrDefault(Object key, V defaultValue) {
@@ -660,13 +685,13 @@ public interface Map {
* values
* @throws ClassCastException if a replacement value is of an inappropriate
* type for this map
- * (optional)
+ * (optional)
* @throws NullPointerException if function or a replacement value is null,
* and this map does not permit null keys or values
- * (optional)
+ * (optional)
* @throws IllegalArgumentException if some property of a replacement value
* prevents it from being stored in this map
- * (optional)
+ * (optional)
* @throws ConcurrentModificationException if an entry is found to be
* removed during iteration
* @since 1.8
@@ -727,16 +752,16 @@ public interface Map {
* if the implementation supports null values.)
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
- * (optional)
+ * (optional)
* @throws ClassCastException if the key or value is of an inappropriate
* type for this map
- * (optional)
+ * (optional)
* @throws NullPointerException if the specified key or value is null,
* and this map does not permit null keys or values
- * (optional)
+ * (optional)
* @throws IllegalArgumentException if some property of the specified key
* or value prevents it from being stored in this map
- * (optional)
+ * (optional)
* @since 1.8
*/
default V putIfAbsent(K key, V value) {
@@ -773,13 +798,13 @@ public interface Map {
* @return {@code true} if the value was removed
* @throws UnsupportedOperationException if the {@code remove} operation
* is not supported by this map
- * (optional)
+ * (optional)
* @throws ClassCastException if the key or value is of an inappropriate
* type for this map
- * (optional)
+ * (optional)
* @throws NullPointerException if the specified key or value is null,
* and this map does not permit null keys or values
- * (optional)
+ * (optional)
* @since 1.8
*/
default boolean remove(Object key, Object value) {
@@ -822,14 +847,14 @@ public interface Map {
* @return {@code true} if the value was replaced
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
- * (optional)
+ * (optional)
* @throws ClassCastException if the class of a specified key or value
* prevents it from being stored in this map
* @throws NullPointerException if a specified key or newValue is null,
* and this map does not permit null keys or values
* @throws NullPointerException if oldValue is null and this map does not
* permit null values
- * (optional)
+ * (optional)
* @throws IllegalArgumentException if some property of a specified key
* or value prevents it from being stored in this map
* @since 1.8
@@ -872,10 +897,10 @@ public interface Map {
* if the implementation supports null values.)
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
- * (optional)
+ * (optional)
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
- * (optional)
+ * (optional)
* @throws NullPointerException if the specified key or value is null,
* and this map does not permit null keys or values
* @throws IllegalArgumentException if some property of the specified key
@@ -955,13 +980,13 @@ public interface Map {
* is null
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
- * (optional)
+ * (optional)
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
- * (optional)
+ * (optional)
* @throws IllegalArgumentException if some property of the specified key
* or value prevents it from being stored in this map
- * (optional)
+ * (optional)
* @since 1.8
*/
default V computeIfAbsent(K key,
@@ -1032,13 +1057,13 @@ public interface Map {
* remappingFunction is null
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
- * (optional)
+ * (optional)
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
- * (optional)
+ * (optional)
* @throws IllegalArgumentException if some property of the specified key
* or value prevents it from being stored in this map
- * (optional)
+ * (optional)
* @since 1.8
*/
default V computeIfPresent(K key,
@@ -1084,7 +1109,7 @@ public interface Map {
* {@code
* V oldValue = map.get(key);
* V newValue = remappingFunction.apply(key, oldValue);
- * if (oldValue != null ) {
+ * if (oldValue != null) {
* if (newValue != null)
* map.put(key, newValue);
* else
@@ -1124,13 +1149,13 @@ public interface Map {
* remappingFunction is null
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
- * (optional)
+ * (optional)
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
- * (optional)
+ * (optional)
* @throws IllegalArgumentException if some property of the specified key
* or value prevents it from being stored in this map
- * (optional)
+ * (optional)
* @since 1.8
*/
default V compute(K key,
@@ -1219,16 +1244,16 @@ public interface Map {
* value is associated with the key
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
- * (optional)
+ * (optional)
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
- * (optional)
+ * (optional)
+ * @throws IllegalArgumentException if some property of the specified key
+ * or value prevents it from being stored in this map
+ * (optional)
* @throws NullPointerException if the specified key is null and this map
* does not support null keys or the value or remappingFunction is
* null
- * @throws IllegalArgumentException if some property of the specified key
- * or value prevents it from being stored in this map
- * (optional)
* @since 1.8
*/
default V merge(K key, V value,
@@ -1245,4 +1270,465 @@ public interface Map {
}
return newValue;
}
+
+ /**
+ * Returns an immutable map containing zero mappings.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @return an empty {@code Map}
+ *
+ * @since 9
+ */
+ static Map of() {
+ return Collections.emptyMap();
+ }
+
+ /**
+ * Returns an immutable map containing a single mapping.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param k1 the mapping's key
+ * @param v1 the mapping's value
+ * @return a {@code Map} containing the specified mapping
+ * @throws NullPointerException if the key or the value is {@code null}
+ *
+ * @since 9
+ */
+ static Map of(K k1, V v1) {
+ return Collections.singletonMap(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+ }
+
+ /**
+ * Returns an immutable map containing two mappings.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param k1 the first mapping's key
+ * @param v1 the first mapping's value
+ * @param k2 the second mapping's key
+ * @param v2 the second mapping's value
+ * @return a {@code Map} containing the specified mappings
+ * @throws IllegalArgumentException if the keys are duplicates
+ * @throws NullPointerException if any key or value is {@code null}
+ *
+ * @since 9
+ */
+ static Map of(K k1, V v1, K k2, V v2) {
+ Map map = new HashMap<>(3); // specify number of buckets to avoid resizing
+ map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+ map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
+ if (map.size() != 2) {
+ throw new IllegalArgumentException("duplicate keys");
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Returns an immutable map containing three mappings.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param k1 the first mapping's key
+ * @param v1 the first mapping's value
+ * @param k2 the second mapping's key
+ * @param v2 the second mapping's value
+ * @param k3 the third mapping's key
+ * @param v3 the third mapping's value
+ * @return a {@code Map} containing the specified mappings
+ * @throws IllegalArgumentException if there are any duplicate keys
+ * @throws NullPointerException if any key or value is {@code null}
+ *
+ * @since 9
+ */
+ static Map of(K k1, V v1, K k2, V v2, K k3, V v3) {
+ Map map = new HashMap<>(5); // specify number of buckets to avoid resizing
+ map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+ map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
+ map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
+ if (map.size() != 3) {
+ throw new IllegalArgumentException("duplicate keys");
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Returns an immutable map containing four mappings.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param k1 the first mapping's key
+ * @param v1 the first mapping's value
+ * @param k2 the second mapping's key
+ * @param v2 the second mapping's value
+ * @param k3 the third mapping's key
+ * @param v3 the third mapping's value
+ * @param k4 the fourth mapping's key
+ * @param v4 the fourth mapping's value
+ * @return a {@code Map} containing the specified mappings
+ * @throws IllegalArgumentException if there are any duplicate keys
+ * @throws NullPointerException if any key or value is {@code null}
+ *
+ * @since 9
+ */
+ static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+ Map map = new HashMap<>(6); // specify number of buckets to avoid resizing
+ map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+ map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
+ map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
+ map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
+ if (map.size() != 4) {
+ throw new IllegalArgumentException("duplicate keys");
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Returns an immutable map containing five mappings.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param k1 the first mapping's key
+ * @param v1 the first mapping's value
+ * @param k2 the second mapping's key
+ * @param v2 the second mapping's value
+ * @param k3 the third mapping's key
+ * @param v3 the third mapping's value
+ * @param k4 the fourth mapping's key
+ * @param v4 the fourth mapping's value
+ * @param k5 the fifth mapping's key
+ * @param v5 the fifth mapping's value
+ * @return a {@code Map} containing the specified mappings
+ * @throws IllegalArgumentException if there are any duplicate keys
+ * @throws NullPointerException if any key or value is {@code null}
+ *
+ * @since 9
+ */
+ static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
+ Map map = new HashMap<>(7); // specify number of buckets to avoid resizing
+ map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+ map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
+ map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
+ map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
+ map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
+ if (map.size() != 5) {
+ throw new IllegalArgumentException("duplicate keys");
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Returns an immutable map containing six mappings.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param k1 the first mapping's key
+ * @param v1 the first mapping's value
+ * @param k2 the second mapping's key
+ * @param v2 the second mapping's value
+ * @param k3 the third mapping's key
+ * @param v3 the third mapping's value
+ * @param k4 the fourth mapping's key
+ * @param v4 the fourth mapping's value
+ * @param k5 the fifth mapping's key
+ * @param v5 the fifth mapping's value
+ * @param k6 the sixth mapping's key
+ * @param v6 the sixth mapping's value
+ * @return a {@code Map} containing the specified mappings
+ * @throws IllegalArgumentException if there are any duplicate keys
+ * @throws NullPointerException if any key or value is {@code null}
+ *
+ * @since 9
+ */
+ static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
+ K k6, V v6) {
+ Map map = new HashMap<>(9); // specify number of buckets to avoid resizing
+ map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+ map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
+ map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
+ map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
+ map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
+ map.put(Objects.requireNonNull(k6), Objects.requireNonNull(v6));
+ if (map.size() != 6) {
+ throw new IllegalArgumentException("duplicate keys");
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Returns an immutable map containing seven mappings.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param k1 the first mapping's key
+ * @param v1 the first mapping's value
+ * @param k2 the second mapping's key
+ * @param v2 the second mapping's value
+ * @param k3 the third mapping's key
+ * @param v3 the third mapping's value
+ * @param k4 the fourth mapping's key
+ * @param v4 the fourth mapping's value
+ * @param k5 the fifth mapping's key
+ * @param v5 the fifth mapping's value
+ * @param k6 the sixth mapping's key
+ * @param v6 the sixth mapping's value
+ * @param k7 the seventh mapping's key
+ * @param v7 the seventh mapping's value
+ * @return a {@code Map} containing the specified mappings
+ * @throws IllegalArgumentException if there are any duplicate keys
+ * @throws NullPointerException if any key or value is {@code null}
+ *
+ * @since 9
+ */
+ static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
+ K k6, V v6, K k7, V v7) {
+ Map map = new HashMap<>(10); // specify number of buckets to avoid resizing
+ map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+ map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
+ map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
+ map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
+ map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
+ map.put(Objects.requireNonNull(k6), Objects.requireNonNull(v6));
+ map.put(Objects.requireNonNull(k7), Objects.requireNonNull(v7));
+ if (map.size() != 7) {
+ throw new IllegalArgumentException("duplicate keys");
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Returns an immutable map containing eight mappings.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param k1 the first mapping's key
+ * @param v1 the first mapping's value
+ * @param k2 the second mapping's key
+ * @param v2 the second mapping's value
+ * @param k3 the third mapping's key
+ * @param v3 the third mapping's value
+ * @param k4 the fourth mapping's key
+ * @param v4 the fourth mapping's value
+ * @param k5 the fifth mapping's key
+ * @param v5 the fifth mapping's value
+ * @param k6 the sixth mapping's key
+ * @param v6 the sixth mapping's value
+ * @param k7 the seventh mapping's key
+ * @param v7 the seventh mapping's value
+ * @param k8 the eighth mapping's key
+ * @param v8 the eighth mapping's value
+ * @return a {@code Map} containing the specified mappings
+ * @throws IllegalArgumentException if there are any duplicate keys
+ * @throws NullPointerException if any key or value is {@code null}
+ *
+ * @since 9
+ */
+ static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
+ K k6, V v6, K k7, V v7, K k8, V v8) {
+ Map map = new HashMap<>(11); // specify number of buckets to avoid resizing
+ map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+ map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
+ map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
+ map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
+ map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
+ map.put(Objects.requireNonNull(k6), Objects.requireNonNull(v6));
+ map.put(Objects.requireNonNull(k7), Objects.requireNonNull(v7));
+ map.put(Objects.requireNonNull(k8), Objects.requireNonNull(v8));
+ if (map.size() != 8) {
+ throw new IllegalArgumentException("duplicate keys");
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Returns an immutable map containing nine mappings.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param k1 the first mapping's key
+ * @param v1 the first mapping's value
+ * @param k2 the second mapping's key
+ * @param v2 the second mapping's value
+ * @param k3 the third mapping's key
+ * @param v3 the third mapping's value
+ * @param k4 the fourth mapping's key
+ * @param v4 the fourth mapping's value
+ * @param k5 the fifth mapping's key
+ * @param v5 the fifth mapping's value
+ * @param k6 the sixth mapping's key
+ * @param v6 the sixth mapping's value
+ * @param k7 the seventh mapping's key
+ * @param v7 the seventh mapping's value
+ * @param k8 the eighth mapping's key
+ * @param v8 the eighth mapping's value
+ * @param k9 the ninth mapping's key
+ * @param v9 the ninth mapping's value
+ * @return a {@code Map} containing the specified mappings
+ * @throws IllegalArgumentException if there are any duplicate keys
+ * @throws NullPointerException if any key or value is {@code null}
+ *
+ * @since 9
+ */
+ static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
+ K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
+ Map map = new HashMap<>(13); // specify number of buckets to avoid resizing
+ map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+ map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
+ map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
+ map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
+ map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
+ map.put(Objects.requireNonNull(k6), Objects.requireNonNull(v6));
+ map.put(Objects.requireNonNull(k7), Objects.requireNonNull(v7));
+ map.put(Objects.requireNonNull(k8), Objects.requireNonNull(v8));
+ map.put(Objects.requireNonNull(k9), Objects.requireNonNull(v9));
+ if (map.size() != 9) {
+ throw new IllegalArgumentException("duplicate keys");
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Returns an immutable map containing ten mappings.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param k1 the first mapping's key
+ * @param v1 the first mapping's value
+ * @param k2 the second mapping's key
+ * @param v2 the second mapping's value
+ * @param k3 the third mapping's key
+ * @param v3 the third mapping's value
+ * @param k4 the fourth mapping's key
+ * @param v4 the fourth mapping's value
+ * @param k5 the fifth mapping's key
+ * @param v5 the fifth mapping's value
+ * @param k6 the sixth mapping's key
+ * @param v6 the sixth mapping's value
+ * @param k7 the seventh mapping's key
+ * @param v7 the seventh mapping's value
+ * @param k8 the eighth mapping's key
+ * @param v8 the eighth mapping's value
+ * @param k9 the ninth mapping's key
+ * @param v9 the ninth mapping's value
+ * @param k10 the tenth mapping's key
+ * @param v10 the tenth mapping's value
+ * @return a {@code Map} containing the specified mappings
+ * @throws IllegalArgumentException if there are any duplicate keys
+ * @throws NullPointerException if any key or value is {@code null}
+ *
+ * @since 9
+ */
+ static Map of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
+ K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
+ Map map = new HashMap<>(14); // specify number of buckets to avoid resizing
+ map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+ map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
+ map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
+ map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
+ map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
+ map.put(Objects.requireNonNull(k6), Objects.requireNonNull(v6));
+ map.put(Objects.requireNonNull(k7), Objects.requireNonNull(v7));
+ map.put(Objects.requireNonNull(k8), Objects.requireNonNull(v8));
+ map.put(Objects.requireNonNull(k9), Objects.requireNonNull(v9));
+ map.put(Objects.requireNonNull(k10), Objects.requireNonNull(v10));
+ if (map.size() != 10) {
+ throw new IllegalArgumentException("duplicate keys");
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Returns an immutable map containing keys and values extracted from the given entries.
+ * The entries themselves are not stored in the map.
+ * See Immutable Map Static Factory Methods for details.
+ *
+ * @apiNote
+ * It is convenient to create the map entries using the {@link Map#entry Map.entry()} method.
+ * For example,
+ *
+ * {@code
+ * import static java.util.Map.entry;
+ *
+ * Map map = Map.ofEntries(
+ * entry(1, "a"),
+ * entry(2, "b"),
+ * entry(3, "c"),
+ * ...
+ * entry(26, "z"));
+ * }
+ *
+ * @param the {@code Map}'s key type
+ * @param the {@code Map}'s value type
+ * @param entries {@code Map.Entry}s containing the keys and values from which the map is populated
+ * @return a {@code Map} containing the specified mappings
+ * @throws IllegalArgumentException if there are any duplicate keys
+ * @throws NullPointerException if any entry, key, or value is {@code null}, or if
+ * the {@code entries} array is {@code null}
+ *
+ * @see Map#entry Map.entry()
+ * @since 9
+ */
+ @SafeVarargs
+ @SuppressWarnings("varargs")
+ static Map ofEntries(Entry extends K, ? extends V>... entries) {
+ Map map = new HashMap<>(entries.length * 4 / 3 + 1); // throws NPE if entries is null
+ for (Entry extends K, ? extends V> e : entries) {
+ // next line throws NPE if e is null
+ map.put(Objects.requireNonNull(e.getKey()), Objects.requireNonNull(e.getValue()));
+ }
+ if (map.size() != entries.length) {
+ throw new IllegalArgumentException("duplicate keys");
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * 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:
+ *
+ *
+ * - They disallow {@code null} keys and values. Attempts to create them using a {@code null}
+ * key or value result in {@code NullPointerException}.
+ *
- They are immutable. Calls to {@link Entry#setValue Entry.setValue()}
+ * on a returned {@code Entry} result in {@code UnsupportedOperationException}.
+ *
- They are not serializable.
+ *
- They are value-based.
+ * 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,
+ * identity-sensitive operations on these instances (reference equality ({@code ==}),
+ * identity hash code, and synchronization) are unreliable and should be avoided.
+ *
+ *
+ * @apiNote
+ * For a serializable {@code Entry}, see {@link AbstractMap.SimpleEntry} or
+ * {@link AbstractMap.SimpleImmutableEntry}.
+ *
+ * @param the key's type
+ * @param the value's type
+ * @param k the key
+ * @param v the value
+ * @return an {@code Entry} containing the specified key and value
+ * @throws NullPointerException if the key or value is {@code null}
+ *
+ * @see Map#ofEntries Map.ofEntries()
+ * @since 9
+ */
+ static Entry entry(K k, V v) {
+ // KeyValueHolder checks for nulls
+ return new KeyValueHolder<>(k, v);
+ }
}