8139232: JEP-269 initial API and skeleton implementations

Reviewed-by: psandoz, rriggs
This commit is contained in:
Stuart Marks 2015-12-08 13:48:22 -08:00
parent b0e22f9603
commit d42e70fc3c
8 changed files with 2315 additions and 15 deletions

View File

@ -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;
}
}

View File

@ -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 @@ import java.util.function.UnaryOperator;
* 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 @@ public interface List<E> extends Collection<E> {
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));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -110,6 +110,31 @@ import java.io.Serializable;
* Implementations may optionally handle the self-referential scenario, however
* most current implementations do not do so.
*
* <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 @@ import java.io.Serializable;
* @see Set
* @since 1.2
*/
public interface Map<K,V> {
public interface Map<K, V> {
// Query Operations
/**
@ -373,7 +398,7 @@ public interface Map<K,V> {
* @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 @@ public interface Map<K,V> {
* @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 @@ public interface Map<K,V> {
* @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 @@ public interface Map<K,V> {
}
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);
}
}

View File

@ -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 @@ package java.util;
* 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 @@ public interface Set<E> extends Collection<E> {
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);
}
}

View File

@ -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 static java.util.Collections.*;
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 @@ public class MOAT {
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 @@ public class MOAT {
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 @@ public class MOAT {
}
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 @@ public class MOAT {
checkContainsSelf(c);
checkContainsEmpty(c);
check(c.size() != 0 ^ c.isEmpty());
check(! c.contains(ABSENT_VALUE));
{
int size = 0;
@ -366,6 +457,10 @@ public class MOAT {
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 @@ public class MOAT {
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 @@ public class MOAT {
// 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;
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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());
}
}