< prev index next >

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

Print this page
rev 14011 : Change @since 1.9 to @since 9.
rev 14012 : Add disclaimer about mutable elements.
rev 14013 : Fix typos.

@@ -108,10 +108,29 @@
  * 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 name="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 cannot be modified. Attempts to modify them result in
+ * an {@code UnsupportedOperationException}.
+ * <li>They are truly immutable only if the contained keys and values are themselves
+ * immutable. If a key or value is mutated, the behavior of the map is unspecified.
+ * <li>They disallow null keys and values. Attempts to create them with
+ * null keys or values result in {@code NullPointerException}.
+ * <li>They are serializable if all keys and values are serializable.
+ * <li>They reject duplicate keys at creation time. Duplicate keys
+ * passed to a static factory method result in {@code IllegalArgumentException}.
+ * </ul>
+ *
  * <p>This interface is a member of the
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @param <K> the type of keys maintained by this map

@@ -1231,6 +1250,456 @@
         } else {
             put(key, newValue);
         }
         return newValue;
     }
+
+    /**
+     * Creates an immutable map containing zero mappings.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the map's value type
+     * @return the newly created map
+     *
+     * @since 9
+     */
+    static <K,V> Map<K,V> of() {
+        return Collections.emptyMap();
+    }
+
+    /**
+     * Creates an immutable map containing a single mapping.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the map's value type
+     * @param k1 the mapping's key
+     * @param v1 the mapping's value
+     * @return the newly created map
+     * @throws NullPointerException if the key or the value is null
+     *
+     * @since 9
+     */
+    static <K,V> Map<K,V> of(K k1, V v1) {
+        return Collections.singletonMap(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
+    }
+
+    /**
+     * Creates an immutable map containing two mappings.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the 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 the newly created map
+     * @throws IllegalArgumentException if the keys are duplicates
+     * @throws NullPointerException if any key or value is null
+     *
+     * @since 9
+     */
+    static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2) {
+        Map<K,V> map = new HashMap<>(3);
+        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);
+    }
+
+    /**
+     * Creates an immutable map containing three mappings.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the 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 the newly created map
+     * @throws IllegalArgumentException if any keys are duplicates
+     * @throws NullPointerException if any key or value is null
+     *
+     * @since 9
+     */
+    static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
+        Map<K,V> map = new HashMap<>(5);
+        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);
+    }
+
+    /**
+     * Creates an immutable map containing four mappings.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the 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 the newly created map
+     * @throws IllegalArgumentException if any keys are duplicates
+     * @throws NullPointerException if any key or value is null
+     *
+     * @since 9
+     */
+    static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
+        Map<K,V> map = new HashMap<>(6);
+        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);
+    }
+
+    /**
+     * Creates an immutable map containing five mappings.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the 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 the newly created map
+     * @throws IllegalArgumentException if any keys are duplicates
+     * @throws NullPointerException if any key or value is null
+     *
+     * @since 9
+     */
+    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) {
+        Map<K,V> map = new HashMap<>(7);
+        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);
+    }
+
+    /**
+     * Creates an immutable map containing six mappings.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the 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 the newly created map
+     * @throws IllegalArgumentException if any keys are duplicates
+     * @throws NullPointerException if any key or value is null
+     *
+     * @since 9
+     */
+    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,
+                             K k6, V v6) {
+        Map<K,V> map = new HashMap<>(9);
+        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);
+    }
+
+    /**
+     * Creates an immutable map containing seven mappings.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the 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 the newly created map
+     * @throws IllegalArgumentException if any keys are duplicates
+     * @throws NullPointerException if any key or value is null
+     *
+     * @since 9
+     */
+    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,
+                             K k6, V v6, K k7, V v7) {
+        Map<K,V> map = new HashMap<>(10);
+        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);
+    }
+
+    /**
+     * Creates an immutable map containing eight mappings.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the 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 the newly created map
+     * @throws IllegalArgumentException if any keys are duplicates
+     * @throws NullPointerException if any key or value is null
+     *
+     * @since 9
+     */
+    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,
+                             K k6, V v6, K k7, V v7, K k8, V v8) {
+        Map<K,V> map = new HashMap<>(11);
+        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);
+    }
+
+    /**
+     * Creates an immutable map containing nine mappings.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the 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 the newly created map
+     * @throws IllegalArgumentException if any keys are duplicates
+     * @throws NullPointerException if any key or value is null
+     *
+     * @since 9
+     */
+    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,
+                             K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
+        Map<K,V> map = new HashMap<>(13);
+        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);
+    }
+
+    /**
+     * Creates an immutable map containing ten mappings.
+     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     *
+     * @param <K> the map's key type
+     * @param <V> the 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 the newly created map
+     * @throws IllegalArgumentException if any keys are duplicates
+     * @throws NullPointerException if any key or value is null
+     *
+     * @since 9
+     */
+    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,
+                             K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
+        Map<K,V> map = new HashMap<>(14);
+        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);
+    }
+
+    /**
+     * Creates an immutable map containing keys and values from the given entries.
+     * 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,
+     * 
+     * <pre>{@code
+     *     import static java.util.Map.entry;
+     * 
+     *     Map<Integer,String> map = Map.ofEntries(
+     *         entry(1, "a"),
+     *         entry(2, "b"),
+     *         entry(3, "c"),
+     *         ...
+     *         entry(26, "z"));
+     * }</pre>
+     *
+     * @param <K> the map's key type
+     * @param <V> the map's value type
+     * @param entries the keys and values with which the map is populated
+     * @return the newly created {@code Map}
+     * @throws IllegalArgumentException if any keys are duplicates
+     * @throws NullPointerException if any entry, key, or value is null, or if
+     *         the {@code entries} array is null
+     *
+     * @see Map#entry Map.entry()
+     * @since 9
+     */
+    @SafeVarargs
+    @SuppressWarnings("varargs")
+    static <K,V> Map<K,V> ofEntries(Entry<K,V>... entries) {
+        Map<K,V> map = new HashMap<>(entries.length * 4 / 3 + 1); // throws NPE if entries is null
+        for (Entry<K,V> e : entries) {
+            Objects.requireNonNull(e);
+            map.put(Objects.requireNonNull(e.getKey()), Objects.requireNonNull(e.getValue()));
+        }
+        if (map.size() != entries.length) {
+            throw new IllegalArgumentException("duplicate elements");
+        }
+        return Collections.unmodifiableMap(map);
+    }
+
+    /**
+     * Creates 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 key and the value must not be null. Calling {@link Entry#setValue Entry.setValue()}
+     * on the returned {@code Entry} results in an {@code UnsupportedOperationException}
+     * being thrown. The returned {@code Entry} is not guaranteed to be serializable.
+     *
+     * <p>The returned {@code Entry} is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
+     * class; use of identity-sensitive operations (including reference equality
+     * ({@code ==}), identity hash code, or synchronization) on any returned values
+     * may have unpredictable results and should be avoided.
+     *
+     * @param <K> the key's type
+     * @param <V> the value's type
+     * @param k the key
+     * @param v the value
+     * @return the new {@code Entry}
+     * @throws NullPointerException if the key or value is null
+     *
+     * @see Map#ofEntries Map.ofEntries()
+     * @since 9
+     */
+    static <K,V> Entry<K,V> entry(K k, V v) {
+        // KeyValueHolder checks for nulls
+        return new KeyValueHolder<>(k, v);
+    }
 }
< prev index next >