8139232: JEP-269 initial API and skeleton implementations
Reviewed-by: psandoz, rriggs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java Tue Dec 08 13:48:22 2015 -0800
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util;
+
+/**
+ * An immutable container for a key and a value, suitable for use
+ * in creating and populating {@code Map} instances.
+ *
+ * <p>This 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 instances of
+ * {@code KeyValueHolder} may have unpredictable results and should be avoided.
+ *
+ * @apiNote
+ * This class is not public. Instances can be created using the
+ * {@link Map#entry Map.entry(k, v)} factory method, which is public.
+ *
+ * <p>This class differs from AbstractMap.SimpleImmutableEntry in the following ways:
+ * it is not serializable, it is final, and its key and value must be non-null.
+ *
+ * @param <K> the key type
+ * @param <V> the value type
+ *
+ * @see Map#ofEntries Map.ofEntries()
+ * @since 9
+ */
+final class KeyValueHolder<K,V> implements Map.Entry<K,V> {
+ final K key;
+ final V value;
+
+ KeyValueHolder(K k, V v) {
+ key = Objects.requireNonNull(k);
+ value = Objects.requireNonNull(v);
+ }
+
+ /**
+ * Gets the key from this holder.
+ *
+ * @return the key
+ */
+ @Override
+ public K getKey() {
+ return key;
+ }
+
+ /**
+ * Gets the value from this holder.
+ *
+ * @return the value
+ */
+ @Override
+ public V getValue() {
+ return value;
+ }
+
+ /**
+ * Throws {@link UnsupportedOperationException}.
+ *
+ * @param value ignored
+ * @return never returns normally
+ */
+ @Override
+ public V setValue(V value) {
+ throw new UnsupportedOperationException("not supported");
+ }
+
+ /**
+ * Compares the specified object with this entry for equality.
+ * Returns {@code true} if the given object is also a map entry and
+ * the two entries' keys and values are equal. Note that key and
+ * value are non-null, so equals() can be called safely on them.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
+ return key.equals(e.getKey()) && value.equals(e.getValue());
+ }
+
+ /**
+ * Returns the hash code value for this map entry. The hash code
+ * is {@code key.hashCode() ^ value.hashCode()}. Note that key and
+ * value are non-null, so hashCode() can be called safely on them.
+ */
+ @Override
+ public int hashCode() {
+ return key.hashCode() ^ value.hashCode();
+ }
+
+ /**
+ * Returns a String representation of this map entry. This
+ * implementation returns the string representation of this
+ * entry's key followed by the equals character ("{@code =}")
+ * followed by the string representation of this entry's value.
+ *
+ * @return a String representation of this map entry
+ */
+ @Override
+ public String toString() {
+ return key + "=" + value;
+ }
+}
--- a/jdk/src/java.base/share/classes/java/util/List.java Tue Dec 08 16:43:58 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/List.java Tue Dec 08 13:48:22 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, 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
@@ -87,6 +87,28 @@
* Such exceptions are marked as "optional" in the specification for this
* interface.
*
+ * <h2><a name="immutable">Immutable List Static Factory Methods</a></h2>
+ * <p>The {@link List#of(Object...) List.of()} static factory methods
+ * provide a convenient way to create immutable lists. The {@code List}
+ * instances created by these methods have the following characteristics:
+ *
+ * <ul>
+ * <li>They are <em>structurally immutable</em>. Elements cannot be added, removed,
+ * or replaced. Attempts to do so result in {@code UnsupportedOperationException}.
+ * However, if the contained elements are themselves mutable,
+ * this may cause the List's contents to appear to change.
+ * <li>They disallow {@code null} elements. Attempts to create them with
+ * {@code null} elements result in {@code NullPointerException}.
+ * <li>They are serializable if all elements are serializable.
+ * <li>The order of elements in the list is the same as the order of the
+ * provided arguments, or of the elements in the provided array.
+ * <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.
+ * 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.
+ * </ul>
+ *
* <p>This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
@@ -731,4 +753,312 @@
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.ORDERED);
}
+
+ /**
+ * Returns an immutable list containing zero elements.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @return an empty {@code List}
+ *
+ * @since 9
+ */
+ static <E> List<E> of() {
+ return Collections.emptyList();
+ }
+
+ /**
+ * Returns an immutable list containing one element.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param e1 the single element
+ * @return a {@code List} containing the specified element
+ * @throws NullPointerException if the element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> List<E> of(E e1) {
+ return Collections.singletonList(Objects.requireNonNull(e1));
+ }
+
+ /**
+ * Returns an immutable list containing two elements.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @return a {@code List} containing the specified elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> List<E> of(E e1, E e2) {
+ return Collections.unmodifiableList(
+ Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2)));
+ }
+
+ /**
+ * Returns an immutable list containing three elements.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @return a {@code List} containing the specified elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> List<E> of(E e1, E e2, E e3) {
+ return Collections.unmodifiableList(
+ Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3)));
+ }
+
+ /**
+ * Returns an immutable list containing four elements.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @return a {@code List} containing the specified elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> List<E> of(E e1, E e2, E e3, E e4) {
+ return Collections.unmodifiableList(
+ Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4)));
+ }
+
+ /**
+ * Returns an immutable list containing five elements.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @return a {@code List} containing the specified elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) {
+ return Collections.unmodifiableList(
+ Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5)));
+ }
+
+ /**
+ * Returns an immutable list containing six elements.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @param e6 the sixth element
+ * @return a {@code List} containing the specified elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
+ return Collections.unmodifiableList(
+ Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5),
+ Objects.requireNonNull(e6)));
+ }
+
+ /**
+ * Returns an immutable list containing seven elements.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @param e6 the sixth element
+ * @param e7 the seventh element
+ * @return a {@code List} containing the specified elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
+ return Collections.unmodifiableList(
+ Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5),
+ Objects.requireNonNull(e6),
+ Objects.requireNonNull(e7)));
+ }
+
+ /**
+ * Returns an immutable list containing eight elements.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @param e6 the sixth element
+ * @param e7 the seventh element
+ * @param e8 the eighth element
+ * @return a {@code List} containing the specified elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
+ return Collections.unmodifiableList(
+ Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5),
+ Objects.requireNonNull(e6),
+ Objects.requireNonNull(e7),
+ Objects.requireNonNull(e8)));
+ }
+
+ /**
+ * Returns an immutable list containing nine elements.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @param e6 the sixth element
+ * @param e7 the seventh element
+ * @param e8 the eighth element
+ * @param e9 the ninth element
+ * @return a {@code List} containing the specified elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
+ return Collections.unmodifiableList(
+ Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5),
+ Objects.requireNonNull(e6),
+ Objects.requireNonNull(e7),
+ Objects.requireNonNull(e8),
+ Objects.requireNonNull(e9)));
+ }
+
+ /**
+ * Returns an immutable list containing ten elements.
+ *
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @param e6 the sixth element
+ * @param e7 the seventh element
+ * @param e8 the eighth element
+ * @param e9 the ninth element
+ * @param e10 the tenth element
+ * @return a {@code List} containing the specified elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
+ return Collections.unmodifiableList(
+ Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5),
+ Objects.requireNonNull(e6),
+ Objects.requireNonNull(e7),
+ Objects.requireNonNull(e8),
+ Objects.requireNonNull(e9),
+ Objects.requireNonNull(e10)));
+ }
+
+ /**
+ * Returns an immutable list containing an arbitrary number of elements.
+ * See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
+ *
+ * @apiNote
+ * This method also accepts a single array as an argument. The element type of
+ * the resulting list will be the component type of the array, and the size of
+ * the list will be equal to the length of the array. To create a list with
+ * a single element that is an array, do the following:
+ *
+ * <pre>{@code
+ * String[] array = ... ;
+ * List<String[]> list = List.<String[]>of(array);
+ * }</pre>
+ *
+ * This will cause the {@link List#of(Object) List.of(E)} method
+ * to be invoked instead.
+ *
+ * @param <E> the {@code List}'s element type
+ * @param elements the elements to be contained in the list
+ * @return a {@code List} containing the specified elements
+ * @throws NullPointerException if an element is {@code null} or if the array is {@code null}
+ *
+ * @since 9
+ */
+ @SafeVarargs
+ @SuppressWarnings("varargs")
+ static <E> List<E> of(E... elements) {
+ elements = elements.clone(); // throws NPE if es is null
+ for (E e : elements) {
+ Objects.requireNonNull(e);
+ }
+ return Collections.unmodifiableList(Arrays.asList(elements));
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/Map.java Tue Dec 08 16:43:58 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Map.java Tue Dec 08 13:48:22 2015 -0800
@@ -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 @@
* 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 are <em>structurally immutable</em>. 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.
+ * <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.
+ * <li>They reject duplicate keys at creation time. Duplicate keys
+ * passed to a static factory method result in {@code IllegalArgumentException}.
+ * <li>The iteration order of mappings is unspecified and is subject to change.
+ * <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.
+ * 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.
+ * </ul>
+ *
* <p>This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
@@ -126,7 +151,7 @@
* @see Set
* @since 1.2
*/
-public interface Map<K,V> {
+public interface Map<K, V> {
// Query Operations
/**
@@ -373,7 +398,7 @@
* @see Map#entrySet()
* @since 1.2
*/
- interface Entry<K,V> {
+ interface Entry<K, V> {
/**
* Returns the key corresponding to this entry.
*
@@ -468,7 +493,7 @@
* @see Comparable
* @since 1.8
*/
- public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
+ public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparingByKey() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getKey().compareTo(c2.getKey());
}
@@ -485,7 +510,7 @@
* @see Comparable
* @since 1.8
*/
- public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
+ public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K, V>> comparingByValue() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getValue().compareTo(c2.getValue());
}
@@ -1233,4 +1258,465 @@
}
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}
+ *
+ * @since 9
+ */
+ static <K, V> Map<K, V> of() {
+ return Collections.emptyMap();
+ }
+
+ /**
+ * 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
+ * @return a {@code Map} containing the specified mapping
+ * @throws NullPointerException if the key or the value is {@code null}
+ *
+ * @since 9
+ */
+ static <K, V> Map<K, V> of(K k1, V v1) {
+ return Collections.singletonMap(Objects.requireNonNull(k1), Objects.requireNonNull(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
+ * @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 <K, V> Map<K, V> of(K k1, V v1, K k2, V v2) {
+ Map<K, V> 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 <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
+ * @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 <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); // 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 <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
+ * @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 <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); // 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 <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
+ * @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 <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); // 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 <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
+ * @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 <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); // 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 <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
+ * @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 <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); // 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 <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
+ * @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 <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); // 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 <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
+ * @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 <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); // 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 <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
+ * @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 <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); // 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 <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 {@code Map}'s key type
+ * @param <V> 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 <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) {
+ // 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:
+ *
+ * <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,
+ * identity-sensitive operations on these instances (reference equality ({@code ==}),
+ * identity hash code, and synchronization) are unreliable and should be avoided.
+ * </ul>
+ *
+ * @apiNote
+ * For a serializable {@code Entry}, see {@link AbstractMap.SimpleEntry} or
+ * {@link AbstractMap.SimpleImmutableEntry}.
+ *
+ * @param <K> the key's type
+ * @param <V> 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 <K, V> Entry<K, V> entry(K k, V v) {
+ // KeyValueHolder checks for nulls
+ return new KeyValueHolder<>(k, v);
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/Set.java Tue Dec 08 16:43:58 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Set.java Tue Dec 08 13:48:22 2015 -0800
@@ -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
@@ -63,6 +63,29 @@
* Such exceptions are marked as "optional" in the specification for this
* interface.
*
+ * <h2><a name="immutable">Immutable Set Static Factory Methods</a></h2>
+ * <p>The {@link Set#of(Object...) Set.of()} static factory methods
+ * provide a convenient way to create immutable sets. The {@code Set}
+ * instances created by these methods have the following characteristics:
+ *
+ * <ul>
+ * <li>They are <em>structurally immutable</em>. Elements cannot be added or
+ * removed. Attempts to do so result in {@code UnsupportedOperationException}.
+ * However, if the contained elements are themselves mutable, this may cause the
+ * Set to behave inconsistently or its contents to appear to change.
+ * <li>They disallow {@code null} elements. Attempts to create them with
+ * {@code null} elements result in {@code NullPointerException}.
+ * <li>They are serializable if all elements are serializable.
+ * <li>They reject duplicate elements at creation time. Duplicate elements
+ * passed to a static factory method result in {@code IllegalArgumentException}.
+ * <li>The iteration order of set elements is unspecified and is subject to change.
+ * <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.
+ * 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.
+ * </ul>
+ *
* <p>This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
@@ -410,4 +433,341 @@
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT);
}
+
+ /**
+ * Returns an immutable set containing zero elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @return an empty {@code Set}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of() {
+ return Collections.emptySet();
+ }
+
+ /**
+ * Returns an immutable set containing one element.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param e1 the single element
+ * @return a {@code Set} containing the specified element
+ * @throws NullPointerException if the element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of(E e1) {
+ return Collections.singleton(Objects.requireNonNull(e1));
+ }
+
+ /**
+ * Returns an immutable set containing two elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @return a {@code Set} containing the specified elements
+ * @throws IllegalArgumentException if the elements are duplicates
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of(E e1, E e2) {
+ Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2)));
+ if (set.size() != 2) {
+ throw new IllegalArgumentException("duplicate elements");
+ }
+ return Collections.unmodifiableSet(set);
+ }
+
+ /**
+ * Returns an immutable set containing three elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @return a {@code Set} containing the specified elements
+ * @throws IllegalArgumentException if there are any duplicate elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of(E e1, E e2, E e3) {
+ Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3)));
+ if (set.size() != 3) {
+ throw new IllegalArgumentException("duplicate elements");
+ }
+ return Collections.unmodifiableSet(set);
+ }
+
+ /**
+ * Returns an immutable set containing four elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @return a {@code Set} containing the specified elements
+ * @throws IllegalArgumentException if there are any duplicate elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of(E e1, E e2, E e3, E e4) {
+ Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4)));
+ if (set.size() != 4) {
+ throw new IllegalArgumentException("duplicate elements");
+ }
+ return Collections.unmodifiableSet(set);
+ }
+
+ /**
+ * Returns an immutable set containing five elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @return a {@code Set} containing the specified elements
+ * @throws IllegalArgumentException if there are any duplicate elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5) {
+ Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5)));
+ if (set.size() != 5) {
+ throw new IllegalArgumentException("duplicate elements");
+ }
+ return Collections.unmodifiableSet(set);
+ }
+
+ /**
+ * Returns an immutable set containing six elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @param e6 the sixth element
+ * @return a {@code Set} containing the specified elements
+ * @throws IllegalArgumentException if there are any duplicate elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
+ Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5),
+ Objects.requireNonNull(e6)));
+ if (set.size() != 6) {
+ throw new IllegalArgumentException("duplicate elements");
+ }
+ return Collections.unmodifiableSet(set);
+ }
+
+ /**
+ * Returns an immutable set containing seven elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @param e6 the sixth element
+ * @param e7 the seventh element
+ * @return a {@code Set} containing the specified elements
+ * @throws IllegalArgumentException if there are any duplicate elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
+ Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5),
+ Objects.requireNonNull(e6),
+ Objects.requireNonNull(e7)));
+ if (set.size() != 7) {
+ throw new IllegalArgumentException("duplicate elements");
+ }
+ return Collections.unmodifiableSet(set);
+ }
+
+ /**
+ * Returns an immutable set containing eight elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @param e6 the sixth element
+ * @param e7 the seventh element
+ * @param e8 the eighth element
+ * @return a {@code Set} containing the specified elements
+ * @throws IllegalArgumentException if there are any duplicate elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
+ Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5),
+ Objects.requireNonNull(e6),
+ Objects.requireNonNull(e7),
+ Objects.requireNonNull(e8)));
+ if (set.size() != 8) {
+ throw new IllegalArgumentException("duplicate elements");
+ }
+ return Collections.unmodifiableSet(set);
+ }
+
+ /**
+ * Returns an immutable set containing nine elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @param e6 the sixth element
+ * @param e7 the seventh element
+ * @param e8 the eighth element
+ * @param e9 the ninth element
+ * @return a {@code Set} containing the specified elements
+ * @throws IllegalArgumentException if there are any duplicate elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
+ Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5),
+ Objects.requireNonNull(e6),
+ Objects.requireNonNull(e7),
+ Objects.requireNonNull(e8),
+ Objects.requireNonNull(e9)));
+ if (set.size() != 9) {
+ throw new IllegalArgumentException("duplicate elements");
+ }
+ return Collections.unmodifiableSet(set);
+ }
+
+ /**
+ * Returns an immutable set containing ten elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param e1 the first element
+ * @param e2 the second element
+ * @param e3 the third element
+ * @param e4 the fourth element
+ * @param e5 the fifth element
+ * @param e6 the sixth element
+ * @param e7 the seventh element
+ * @param e8 the eighth element
+ * @param e9 the ninth element
+ * @param e10 the tenth element
+ * @return a {@code Set} containing the specified elements
+ * @throws IllegalArgumentException if there are any duplicate elements
+ * @throws NullPointerException if an element is {@code null}
+ *
+ * @since 9
+ */
+ static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
+ Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
+ Objects.requireNonNull(e2),
+ Objects.requireNonNull(e3),
+ Objects.requireNonNull(e4),
+ Objects.requireNonNull(e5),
+ Objects.requireNonNull(e6),
+ Objects.requireNonNull(e7),
+ Objects.requireNonNull(e8),
+ Objects.requireNonNull(e9),
+ Objects.requireNonNull(e10)));
+ if (set.size() != 10) {
+ throw new IllegalArgumentException("duplicate elements");
+ }
+ return Collections.unmodifiableSet(set);
+ }
+
+ /**
+ * Returns an immutable set containing an arbitrary number of elements.
+ * See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
+ *
+ * @apiNote
+ * This method also accepts a single array as an argument. The element type of
+ * the resulting set will be the component type of the array, and the size of
+ * the set will be equal to the length of the array. To create a set with
+ * a single element that is an array, do the following:
+ *
+ * <pre>{@code
+ * String[] array = ... ;
+ * Set<String[]> list = Set.<String[]>of(array);
+ * }</pre>
+ *
+ * This will cause the {@link Set#of(Object) Set.of(E)} method
+ * to be invoked instead.
+ *
+ * @param <E> the {@code Set}'s element type
+ * @param elements the elements to be contained in the set
+ * @return a {@code Set} containing the specified elements
+ * @throws IllegalArgumentException if there are any duplicate elements
+ * @throws NullPointerException if an element is {@code null} or if the array is {@code null}
+ *
+ * @since 9
+ */
+ @SafeVarargs
+ static <E> Set<E> of(E... elements) {
+ for (E e : elements) { // throws NPE if es is null
+ Objects.requireNonNull(e);
+ }
+ @SuppressWarnings("varargs")
+ Set<E> set = new HashSet<>(Arrays.asList(elements));
+ if (set.size() != elements.length) {
+ throw new IllegalArgumentException("duplicate elements");
+ }
+ return Collections.unmodifiableSet(set);
+ }
}
--- a/jdk/test/java/util/Collection/MOAT.java Tue Dec 08 16:43:58 2015 -0800
+++ b/jdk/test/java/util/Collection/MOAT.java Tue Dec 08 13:48:22 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -58,6 +58,21 @@
import java.lang.reflect.*;
public class MOAT {
+ // Collections under test must not be initialized to contain this value,
+ // and maps under test must not contain this value as a key.
+ // It's used as a sentinel for absent-element testing.
+ static final int ABSENT_VALUE = 778347983;
+
+ static final Integer[] integerArray;
+ static {
+ Integer[] ia = new Integer[20];
+ // fill with 1..20 inclusive
+ for (int i = 0; i < ia.length; i++) {
+ ia[i] = i + 1;
+ }
+ integerArray = ia;
+ }
+
public static void realMain(String[] args) {
testCollection(new NewAbstractCollection<Integer>());
@@ -178,6 +193,70 @@
equal(singletonMap.size(), 1);
testMap(singletonMap);
testImmutableMap(singletonMap);
+
+ // Immutable List
+ testEmptyList(List.of());
+ for (List<Integer> list : Arrays.asList(
+ List.<Integer>of(),
+ List.of(1),
+ List.of(1, 2),
+ List.of(1, 2, 3),
+ List.of(1, 2, 3, 4),
+ List.of(1, 2, 3, 4, 5),
+ List.of(1, 2, 3, 4, 5, 6),
+ List.of(1, 2, 3, 4, 5, 6, 7),
+ List.of(1, 2, 3, 4, 5, 6, 7, 8),
+ List.of(1, 2, 3, 4, 5, 6, 7, 8, 9),
+ List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
+ List.of(integerArray))) {
+ testCollection(list);
+ testImmutableList(list);
+ }
+
+ // Immutable Set
+ testEmptySet(Set.of());
+ for (Set<Integer> set : Arrays.asList(
+ Set.<Integer>of(),
+ Set.of(1),
+ Set.of(1, 2),
+ Set.of(1, 2, 3),
+ Set.of(1, 2, 3, 4),
+ Set.of(1, 2, 3, 4, 5),
+ Set.of(1, 2, 3, 4, 5, 6),
+ Set.of(1, 2, 3, 4, 5, 6, 7),
+ Set.of(1, 2, 3, 4, 5, 6, 7, 8),
+ Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9),
+ Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
+ Set.of(integerArray))) {
+ testCollection(set);
+ testImmutableSet(set);
+ }
+
+ // Immutable Map
+
+ @SuppressWarnings("unchecked")
+ Map.Entry<Integer,Integer>[] ea = (Map.Entry<Integer,Integer>[])new Map.Entry<?,?>[20];
+ for (int i = 0; i < ea.length; i++) {
+ ea[i] = Map.entry(i+1, i+101);
+ }
+
+ testEmptyMap(Map.of());
+ for (Map<Integer,Integer> map : Arrays.asList(
+ Map.<Integer,Integer>of(),
+ Map.of(1, 101),
+ Map.of(1, 101, 2, 202),
+ Map.of(1, 101, 2, 202, 3, 303),
+ Map.of(1, 101, 2, 202, 3, 303, 4, 404),
+ Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505),
+ Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606),
+ Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707),
+ Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808),
+ Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909),
+ Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909, 10, 1010),
+ Map.ofEntries(ea))) {
+ testMap(map);
+ testImmutableMap(map);
+ }
}
private static void checkContainsSelf(Collection<Integer> c) {
@@ -190,6 +269,17 @@
check(c.containsAll(new ArrayList<Integer>()));
}
+ private static void checkUnique(Set<Integer> s) {
+ for (Integer i : s) {
+ int count = 0;
+ for (Integer j : s) {
+ if (Objects.equals(i,j))
+ ++count;
+ }
+ check(count == 1);
+ }
+ }
+
private static <T> void testEmptyCollection(Collection<T> c) {
check(c.isEmpty());
equal(c.size(), 0);
@@ -330,19 +420,19 @@
}
private static boolean supportsAdd(Collection<Integer> c) {
- try { check(c.add(778347983)); }
+ try { check(c.add(ABSENT_VALUE)); }
catch (UnsupportedOperationException t) { return false; }
catch (Throwable t) { unexpected(t); }
try {
- check(c.contains(778347983));
- check(c.remove(778347983));
+ check(c.contains(ABSENT_VALUE));
+ check(c.remove(ABSENT_VALUE));
} catch (Throwable t) { unexpected(t); }
return true;
}
private static boolean supportsRemove(Collection<Integer> c) {
- try { check(! c.remove(19134032)); }
+ try { check(! c.remove(ABSENT_VALUE)); }
catch (UnsupportedOperationException t) { return false; }
catch (Throwable t) { unexpected(t); }
return true;
@@ -359,6 +449,7 @@
checkContainsSelf(c);
checkContainsEmpty(c);
check(c.size() != 0 ^ c.isEmpty());
+ check(! c.contains(ABSENT_VALUE));
{
int size = 0;
@@ -366,6 +457,10 @@
check(c.size() == size);
}
+ if (c instanceof Set) {
+ checkUnique((Set<Integer>)c);
+ }
+
check(c.toArray().length == c.size());
check(c.toArray().getClass() == Object[].class
||
@@ -861,6 +956,20 @@
checkFunctionalInvariants(m.keySet());
checkFunctionalInvariants(m.values());
check(m.size() != 0 ^ m.isEmpty());
+ check(! m.containsKey(ABSENT_VALUE));
+
+ if (m instanceof Serializable) {
+ //System.out.printf("Serializing %s%n", m.getClass().getName());
+ try {
+ Object clone = serialClone(m);
+ equal(m instanceof Serializable,
+ clone instanceof Serializable);
+ equal(m, clone);
+ } catch (Error xxx) {
+ if (! (xxx.getCause() instanceof NotSerializableException))
+ throw xxx;
+ }
+ }
}
private static void testMap(Map<Integer,Integer> m) {
@@ -910,13 +1019,13 @@
// We're asking for .equals(...) semantics
if (m instanceof IdentityHashMap) return false;
- try { check(m.put(778347983,12735) == null); }
+ try { check(m.put(ABSENT_VALUE,12735) == null); }
catch (UnsupportedOperationException t) { return false; }
catch (Throwable t) { unexpected(t); }
try {
- check(m.containsKey(778347983));
- check(m.remove(778347983) != null);
+ check(m.containsKey(ABSENT_VALUE));
+ check(m.remove(ABSENT_VALUE) != null);
} catch (Throwable t) { unexpected(t); }
return true;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Collection/SetFactories.java Tue Dec 08 13:48:22 2015 -0800
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/*
+ * @test
+ * @bug 8048330
+ * @summary Test convenience static factory methods on Set.
+ * @run testng SetFactories
+ */
+
+
+public class SetFactories {
+
+ static final int NUM_STRINGS = 20; // should be larger than the largest fixed-arg overload
+ static final String[] stringArray;
+ static {
+ String[] sa = new String[NUM_STRINGS];
+ for (int i = 0; i < NUM_STRINGS; i++) {
+ sa[i] = String.valueOf((char)('a' + i));
+ }
+ stringArray = sa;
+ }
+
+ static Object[] a(Set<String> act, Set<String> exp) {
+ return new Object[] { act, exp };
+ }
+
+ static Set<String> hashSetOf(String... args) {
+ return new HashSet<>(Arrays.asList(args));
+ }
+
+ @DataProvider(name="empty")
+ public Iterator<Object[]> empty() {
+ return Collections.singletonList(
+ // actual, expected
+ a(Set.of(), Collections.emptySet())
+ ).iterator();
+ }
+
+ @DataProvider(name="nonempty")
+ public Iterator<Object[]> nonempty() {
+ return Arrays.asList(
+ // actual, expected
+ a( Set.of("a"),
+ hashSetOf("a")),
+ a( Set.of("a", "b"),
+ hashSetOf("a", "b")),
+ a( Set.of("a", "b", "c"),
+ hashSetOf("a", "b", "c")),
+ a( Set.of("a", "b", "c", "d"),
+ hashSetOf("a", "b", "c", "d")),
+ a( Set.of("a", "b", "c", "d", "e"),
+ hashSetOf("a", "b", "c", "d", "e")),
+ a( Set.of("a", "b", "c", "d", "e", "f"),
+ hashSetOf("a", "b", "c", "d", "e", "f")),
+ a( Set.of("a", "b", "c", "d", "e", "f", "g"),
+ hashSetOf("a", "b", "c", "d", "e", "f", "g")),
+ a( Set.of("a", "b", "c", "d", "e", "f", "g", "h"),
+ hashSetOf("a", "b", "c", "d", "e", "f", "g", "h")),
+ a( Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i"),
+ hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i")),
+ a( Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
+ hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")),
+ a( Set.of(stringArray),
+ hashSetOf(stringArray))
+ ).iterator();
+ }
+
+ @DataProvider(name="all")
+ public Iterator<Object[]> all() {
+ List<Object[]> all = new ArrayList<>();
+ empty().forEachRemaining(all::add);
+ nonempty().forEachRemaining(all::add);
+ return all.iterator();
+ }
+
+ @Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
+ public void cannotAdd(Set<String> act, Set<String> exp) {
+ act.add("x");
+ }
+
+ @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
+ public void cannotRemove(Set<String> act, Set<String> exp) {
+ act.remove(act.iterator().next());
+ }
+
+ @Test(dataProvider="all")
+ public void contentsMatch(Set<String> act, Set<String> exp) {
+ assertEquals(act, exp);
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupsDisallowed2() {
+ Set<String> set = Set.of("a", "a");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupsDisallowed3() {
+ Set<String> set = Set.of("a", "b", "a");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupsDisallowed4() {
+ Set<String> set = Set.of("a", "b", "c", "a");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupsDisallowed5() {
+ Set<String> set = Set.of("a", "b", "c", "d", "a");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupsDisallowed6() {
+ Set<String> set = Set.of("a", "b", "c", "d", "e", "a");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupsDisallowed7() {
+ Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "a");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupsDisallowed8() {
+ Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "a");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupsDisallowed9() {
+ Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "h", "a");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupsDisallowed10() {
+ Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "a");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupsDisallowedN() {
+ String[] array = stringArray.clone();
+ array[0] = array[1];
+ Set<String> set = Set.of(array);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed1() {
+ Set.of((String)null); // force one-arg overload
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed2a() {
+ Set.of("a", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed2b() {
+ Set.of(null, "b");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed3() {
+ Set.of("a", "b", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed4() {
+ Set.of("a", "b", "c", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed5() {
+ Set.of("a", "b", "c", "d", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed6() {
+ Set.of("a", "b", "c", "d", "e", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed7() {
+ Set.of("a", "b", "c", "d", "e", "f", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed8() {
+ Set.of("a", "b", "c", "d", "e", "f", "g", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed9() {
+ Set.of("a", "b", "c", "d", "e", "f", "g", "h", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed10() {
+ Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowedN() {
+ String[] array = stringArray.clone();
+ array[0] = null;
+ Set.of(array);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullArrayDisallowed() {
+ Set.of((Object[])null);
+ }
+
+ @Test(dataProvider="all")
+ public void serialEquality(Set<String> act, Set<String> exp) {
+ // assume that act.equals(exp) tested elsewhere
+ Set<String> copy = serialClone(act);
+ assertEquals(act, copy);
+ assertEquals(copy, exp);
+ }
+
+ @SuppressWarnings("unchecked")
+ static <T> T serialClone(T obj) {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(obj);
+ oos.close();
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ return (T) ois.readObject();
+ } catch (IOException | ClassNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/List/ListFactories.java Tue Dec 08 13:48:22 2015 -0800
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static java.util.Arrays.asList;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/*
+ * @test
+ * @bug 8048330
+ * @summary Test convenience static factory methods on List.
+ * @run testng ListFactories
+ */
+
+public class ListFactories {
+
+ static final int NUM_STRINGS = 20; // should be larger than the largest fixed-arg overload
+ static final String[] stringArray;
+ static {
+ String[] sa = new String[NUM_STRINGS];
+ for (int i = 0; i < NUM_STRINGS; i++) {
+ sa[i] = String.valueOf((char)('a' + i));
+ }
+ stringArray = sa;
+ }
+
+ // returns array of [actual, expected]
+ static Object[] a(List<String> act, List<String> exp) {
+ return new Object[] { act, exp };
+ }
+
+ @DataProvider(name="empty")
+ public Iterator<Object[]> empty() {
+ return Collections.singletonList(
+ a(List.of(), Collections.emptyList())
+ ).iterator();
+ }
+
+ @DataProvider(name="nonempty")
+ public Iterator<Object[]> nonempty() {
+ return asList(
+ a(List.of("a"),
+ asList("a")),
+ a(List.of("a", "b"),
+ asList("a", "b")),
+ a(List.of("a", "b", "c"),
+ asList("a", "b", "c")),
+ a(List.of("a", "b", "c", "d"),
+ asList("a", "b", "c", "d")),
+ a(List.of("a", "b", "c", "d", "e"),
+ asList("a", "b", "c", "d", "e")),
+ a(List.of("a", "b", "c", "d", "e", "f"),
+ asList("a", "b", "c", "d", "e", "f")),
+ a(List.of("a", "b", "c", "d", "e", "f", "g"),
+ asList("a", "b", "c", "d", "e", "f", "g")),
+ a(List.of("a", "b", "c", "d", "e", "f", "g", "h"),
+ asList("a", "b", "c", "d", "e", "f", "g", "h")),
+ a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i"),
+ asList("a", "b", "c", "d", "e", "f", "g", "h", "i")),
+ a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
+ asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")),
+ a(List.of(stringArray),
+ asList(stringArray))
+ ).iterator();
+ }
+
+ @DataProvider(name="all")
+ public Iterator<Object[]> all() {
+ List<Object[]> all = new ArrayList<>();
+ empty().forEachRemaining(all::add);
+ nonempty().forEachRemaining(all::add);
+ return all.iterator();
+ }
+
+ @Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
+ public void cannotAddLast(List<String> act, List<String> exp) {
+ act.add("x");
+ }
+
+ @Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
+ public void cannotAddFirst(List<String> act, List<String> exp) {
+ act.add(0, "x");
+ }
+
+ @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
+ public void cannotRemove(List<String> act, List<String> exp) {
+ act.remove(0);
+ }
+
+ @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
+ public void cannotSet(List<String> act, List<String> exp) {
+ act.set(0, "x");
+ }
+
+ @Test(dataProvider="all")
+ public void contentsMatch(List<String> act, List<String> exp) {
+ assertEquals(act, exp);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed1() {
+ List.of((Object)null); // force one-arg overload
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed2a() {
+ List.of("a", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed2b() {
+ List.of(null, "b");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed3() {
+ List.of("a", "b", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed4() {
+ List.of("a", "b", "c", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed5() {
+ List.of("a", "b", "c", "d", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed6() {
+ List.of("a", "b", "c", "d", "e", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed7() {
+ List.of("a", "b", "c", "d", "e", "f", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed8() {
+ List.of("a", "b", "c", "d", "e", "f", "g", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed9() {
+ List.of("a", "b", "c", "d", "e", "f", "g", "h", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowed10() {
+ List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullDisallowedN() {
+ String[] array = stringArray.clone();
+ array[0] = null;
+ List.of(array);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullArrayDisallowed() {
+ List.of((Object[])null);
+ }
+
+ @Test
+ public void ensureArrayCannotModifyList() {
+ String[] array = stringArray.clone();
+ List<String> list = List.of(array);
+ array[0] = "xyzzy";
+ assertEquals(list, Arrays.asList(stringArray));
+ }
+
+ @Test(dataProvider="all")
+ public void serialEquality(List<String> act, List<String> exp) {
+ // assume that act.equals(exp) tested elsewhere
+ List<String> copy = serialClone(act);
+ assertEquals(act, copy);
+ assertEquals(copy, exp);
+ }
+
+ @SuppressWarnings("unchecked")
+ static <T> T serialClone(T obj) {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(obj);
+ oos.close();
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ return (T) ois.readObject();
+ } catch (IOException | ClassNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Map/MapFactories.java Tue Dec 08 13:48:22 2015 -0800
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/*
+ * @test
+ * @bug 8048330
+ * @summary Test convenience static factory methods on Map.
+ * @run testng MapFactories
+ */
+
+public class MapFactories {
+
+ static final int MAX_ENTRIES = 20; // should be larger than the largest fixed-arg overload
+ static String valueFor(int i) {
+ // the String literal below should be of length MAX_ENTRIES
+ return "abcdefghijklmnopqrst".substring(i, i+1);
+ }
+
+ // for "expected" values
+ Map<Integer,String> genMap(int n) {
+ Map<Integer,String> result = new HashMap<>();
+ for (int i = 0; i < n; i++) {
+ result.put(i, valueFor(i));
+ }
+ return result;
+ }
+
+ // for varargs Map.Entry methods
+ @SuppressWarnings("unchecked")
+ Map.Entry<Integer,String>[] genEntries(int n) {
+ return IntStream.range(0, n)
+ .mapToObj(i -> Map.entry(i, valueFor(i)))
+ .toArray(Map.Entry[]::new);
+ }
+
+ // returns array of [actual, expected]
+ static Object[] a(Map<Integer,String> act, Map<Integer,String> exp) {
+ return new Object[] { act, exp };
+ }
+
+ @DataProvider(name="empty")
+ public Iterator<Object[]> empty() {
+ return Collections.singletonList(
+ a(Map.of(), genMap(0))
+ ).iterator();
+ }
+
+ @DataProvider(name="nonempty")
+ @SuppressWarnings("unchecked")
+ public Iterator<Object[]> nonempty() {
+ return Arrays.asList(
+ a(Map.of(0, "a"), genMap(1)),
+ a(Map.of(0, "a", 1, "b"), genMap(2)),
+ a(Map.of(0, "a", 1, "b", 2, "c"), genMap(3)),
+ a(Map.of(0, "a", 1, "b", 2, "c", 3, "d"), genMap(4)),
+ a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e"), genMap(5)),
+ a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f"), genMap(6)),
+ a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g"), genMap(7)),
+ a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h"), genMap(8)),
+ a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i"), genMap(9)),
+ a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j"), genMap(10)),
+ a(Map.ofEntries(genEntries(MAX_ENTRIES)), genMap(MAX_ENTRIES))
+ ).iterator();
+ }
+
+ @DataProvider(name="all")
+ public Iterator<Object[]> all() {
+ List<Object[]> all = new ArrayList<>();
+ empty().forEachRemaining(all::add);
+ nonempty().forEachRemaining(all::add);
+ return all.iterator();
+ }
+
+ @Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
+ public void cannotPutNew(Map<Integer,String> act, Map<Integer,String> exp) {
+ act.put(-1, "xyzzy");
+ }
+
+ @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
+ public void cannotPutOld(Map<Integer,String> act, Map<Integer,String> exp) {
+ act.put(0, "a");
+ }
+
+ @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
+ public void cannotRemove(Map<Integer,String> act, Map<Integer,String> exp) {
+ act.remove(act.keySet().iterator().next());
+ }
+
+ @Test(dataProvider="all")
+ public void contentsMatch(Map<Integer,String> act, Map<Integer,String> exp) {
+ assertEquals(act, exp);
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupKeysDisallowed2() {
+ Map<Integer, String> map = Map.of(0, "a", 0, "b");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupKeysDisallowed3() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 0, "c");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupKeysDisallowed4() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 0, "d");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupKeysDisallowed5() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 0, "e");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupKeysDisallowed6() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 0, "f");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupKeysDisallowed7() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 0, "g");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupKeysDisallowed8() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 6, "g", 0, "h");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupKeysDisallowed9() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 6, "g", 7, "h", 0, "i");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupKeysDisallowed10() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 6, "g", 7, "h", 8, "i", 0, "j");
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void dupKeysDisallowedN() {
+ Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES);
+ entries[MAX_ENTRIES-1] = Map.entry(0, "xxx");
+ Map<Integer, String> map = Map.ofEntries(entries);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowed1() {
+ Map<Integer, String> map = Map.of(null, "a");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowed1() {
+ Map<Integer, String> map = Map.of(0, null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowed2() {
+ Map<Integer, String> map = Map.of(0, "a", null, "b");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowed2() {
+ Map<Integer, String> map = Map.of(0, "a", 1, null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowed3() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", null, "c");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowed3() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowed4() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", null, "d");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowed4() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowed5() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", null, "e");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowed5() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowed6() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ null, "f");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowed6() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowed7() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", null, "g");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowed7() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 6, null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowed8() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 6, "g", null, "h");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowed8() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 6, "g", 7, null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowed9() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 6, "g", 7, "h", null, "i");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowed9() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 6, "g", 7, "h", 8, null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowed10() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 6, "g", 7, "h", 8, "i", null, "j");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowed10() {
+ Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
+ 5, "f", 6, "g", 7, "h", 8, "i", 9, null);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullKeyDisallowedN() {
+ Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES);
+ entries[0] = new AbstractMap.SimpleImmutableEntry(null, "a");
+ Map<Integer, String> map = Map.ofEntries(entries);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullValueDisallowedN() {
+ Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES);
+ entries[0] = new AbstractMap.SimpleImmutableEntry(0, null);
+ Map<Integer, String> map = Map.ofEntries(entries);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullEntryDisallowedN() {
+ Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES);
+ entries[5] = null;
+ Map<Integer, String> map = Map.ofEntries(entries);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void nullArrayDisallowed() {
+ Map.ofEntries(null);
+ }
+
+ @Test(dataProvider="all")
+ public void serialEquality(Map<Integer, String> act, Map<Integer, String> exp) {
+ // assume that act.equals(exp) tested elsewhere
+ Map<Integer, String> copy = serialClone(act);
+ assertEquals(act, copy);
+ assertEquals(copy, exp);
+ }
+
+ @SuppressWarnings("unchecked")
+ static <T> T serialClone(T obj) {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(obj);
+ oos.close();
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ return (T) ois.readObject();
+ } catch (IOException | ClassNotFoundException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ // Map.entry() tests
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void entryWithNullKeyDisallowed() {
+ Map.Entry<Integer,String> e = Map.entry(null, "x");
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void entryWithNullValueDisallowed() {
+ Map.Entry<Integer,String> e = Map.entry(0, null);
+ }
+
+ @Test
+ public void entryBasicTests() {
+ Map.Entry<String,String> kvh1 = Map.entry("xyzzy", "plugh");
+ Map.Entry<String,String> kvh2 = Map.entry("foobar", "blurfl");
+ Map.Entry<String,String> sie = new AbstractMap.SimpleImmutableEntry("xyzzy", "plugh");
+
+ assertTrue(kvh1.equals(sie));
+ assertTrue(sie.equals(kvh1));
+ assertFalse(kvh2.equals(sie));
+ assertFalse(sie.equals(kvh2));
+ assertEquals(sie.hashCode(), kvh1.hashCode());
+ assertEquals(sie.toString(), kvh1.toString());
+ }
+
+}