/** Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************/package java.util;import java.io.IOException;import java.io.InvalidObjectException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.ObjectStreamException;import java.io.Serializable;import java.util.function.BiFunction;import java.util.function.Function;import java.util.function.Predicate;import java.util.function.UnaryOperator;import jdk.internal.misc.SharedSecrets;import jdk.internal.vm.annotation.Stable;/*** Container class for immutable collections. Not part of the public API.* Mainly for namespace management and shared infrastructure.** Serial warnings are suppressed throughout because all implementation* classes use a serial proxy and thus have no need to declare serialVersionUID.*/@SuppressWarnings("serial")class ImmutableCollections {/*** A "salt" value used for randomizing iteration order. This is initialized once* and stays constant for the lifetime of the JVM. It need not be truly random, but* it needs to vary sufficiently from one run to the next so that iteration order* will vary between JVM runs.*/static final int SALT;static {long nt = System.nanoTime();SALT = (int)((nt >>> 32) ^ nt);}/** No instances. */private ImmutableCollections() { }/*** The reciprocal of load factor. Given a number of elements* to store, multiply by this factor to get the table size.*/static final int EXPAND_FACTOR = 2;static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); }static abstract class AbstractImmutableCollection<E> extends AbstractCollection<E> {// all mutating methods throw UnsupportedOperationException@Override public boolean add(E e) { throw uoe(); }@Override public boolean addAll(Collection<? extends E> c) { throw uoe(); }@Override public void clear() { throw uoe(); }@Override public boolean remove(Object o) { throw uoe(); }@Override public boolean removeAll(Collection<?> c) { throw uoe(); }@Override public boolean removeIf(Predicate<? super E> filter) { throw uoe(); }@Override public boolean retainAll(Collection<?> c) { throw uoe(); }}// ---------- List Implementations ----------// make a copy, short-circuiting based on implementation class@SuppressWarnings("unchecked")static <E> List<E> listCopy(Collection<? extends E> coll) {if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {return (List<E>)coll;} else {return (List<E>)List.of(coll.toArray());}}@SuppressWarnings("unchecked")static <E> List<E> emptyList() {return (List<E>) ListN.EMPTY_LIST;}static abstract class AbstractImmutableList<E> extends AbstractImmutableCollection<E>implements List<E>, RandomAccess {// all mutating methods throw UnsupportedOperationException@Override public void add(int index, E element) { throw uoe(); }@Override public boolean addAll(int index, Collection<? extends E> c) { throw uoe(); }@Override public E remove(int index) { throw uoe(); }@Override public void replaceAll(UnaryOperator<E> operator) { throw uoe(); }@Override public E set(int index, E element) { throw uoe(); }@Override public void sort(Comparator<? super E> c) { throw uoe(); }@Overridepublic List<E> subList(int fromIndex, int toIndex) {int size = size();subListRangeCheck(fromIndex, toIndex, size);return SubList.fromList(this, fromIndex, toIndex);}static void subListRangeCheck(int fromIndex, int toIndex, int size) {if (fromIndex < 0)throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);if (toIndex > size)throw new IndexOutOfBoundsException("toIndex = " + toIndex);if (fromIndex > toIndex)throw new IllegalArgumentException("fromIndex(" + fromIndex +") > toIndex(" + toIndex + ")");}@Overridepublic Iterator<E> iterator() {return new ListItr<E>(this, size());}@Overridepublic ListIterator<E> listIterator() {return listIterator(0);}@Overridepublic ListIterator<E> listIterator(final int index) {int size = size();if (index < 0 || index > size) {throw outOfBounds(index);}return new ListItr<E>(this, size, index);}@Overridepublic boolean equals(Object o) {if (o == this) {return true;}if (!(o instanceof List)) {return false;}Iterator<?> oit = ((List<?>) o).iterator();for (int i = 0, s = size(); i < s; i++) {if (!oit.hasNext() || !get(i).equals(oit.next())) {return false;}}return !oit.hasNext();}@Overridepublic int indexOf(Object o) {Objects.requireNonNull(o);for (int i = 0, s = size(); i < s; i++) {if (o.equals(get(i))) {return i;}}return -1;}@Overridepublic int lastIndexOf(Object o) {Objects.requireNonNull(o);for (int i = size() - 1; i >= 0; i--) {if (o.equals(get(i))) {return i;}}return -1;}@Overridepublic int hashCode() {int hash = 1;for (int i = 0, s = size(); i < s; i++) {hash = 31 * hash + get(i).hashCode();}return hash;}@Overridepublic boolean contains(Object o) {return indexOf(o) >= 0;}IndexOutOfBoundsException outOfBounds(int index) {return new IndexOutOfBoundsException("Index: " + index + " Size: " + size());}}static final class ListItr<E> implements ListIterator<E> {@Stableprivate final List<E> list;@Stableprivate final int size;@Stableprivate final boolean isListIterator;private int cursor;ListItr(List<E> list, int size) {this.list = list;this.size = size;this.cursor = 0;isListIterator = false;}ListItr(List<E> list, int size, int index) {this.list = list;this.size = size;this.cursor = index;isListIterator = true;}public boolean hasNext() {return cursor != size;}public E next() {try {int i = cursor;E next = list.get(i);cursor = i + 1;return next;} catch (IndexOutOfBoundsException e) {throw new NoSuchElementException();}}public void remove() {throw uoe();}public boolean hasPrevious() {if (!isListIterator) {throw uoe();}return cursor != 0;}public E previous() {if (!isListIterator) {throw uoe();}try {int i = cursor - 1;E previous = list.get(i);cursor = i;return previous;} catch (IndexOutOfBoundsException e) {throw new NoSuchElementException();}}public int nextIndex() {if (!isListIterator) {throw uoe();}return cursor;}public int previousIndex() {if (!isListIterator) {throw uoe();}return cursor - 1;}public void set(E e) {throw uoe();}public void add(E e) {throw uoe();}}static final class SubList<E> extends AbstractImmutableList<E>implements RandomAccess {@Stableprivate final List<E> root;@Stableprivate final int offset;@Stableprivate final int size;private SubList(List<E> root, int offset, int size) {this.root = root;this.offset = offset;this.size = size;}/*** Constructs a sublist of another SubList.*/static <E> SubList<E> fromSubList(SubList<E> parent, int fromIndex, int toIndex) {return new SubList<>(parent.root, parent.offset + fromIndex, toIndex - fromIndex);}/*** Constructs a sublist of an arbitrary AbstractImmutableList, which is* not a SubList itself.*/static <E> SubList<E> fromList(List<E> list, int fromIndex, int toIndex) {return new SubList<>(list, fromIndex, toIndex - fromIndex);}public E get(int index) {Objects.checkIndex(index, size);return root.get(offset + index);}public int size() {return size;}public Iterator<E> iterator() {return new ListItr<>(this, size());}public ListIterator<E> listIterator(int index) {rangeCheck(index);return new ListItr<>(this, size(), index);}public List<E> subList(int fromIndex, int toIndex) {subListRangeCheck(fromIndex, toIndex, size);return SubList.fromSubList(this, fromIndex, toIndex);}private void rangeCheck(int index) {if (index < 0 || index > size) {throw outOfBounds(index);}}}static final class List12<E> extends AbstractImmutableList<E>implements Serializable {@Stableprivate final E e0;@Stableprivate final E e1;List12(E e0) {this.e0 = Objects.requireNonNull(e0);this.e1 = null;}List12(E e0, E e1) {this.e0 = Objects.requireNonNull(e0);this.e1 = Objects.requireNonNull(e1);}@Overridepublic int size() {return e1 != null ? 2 : 1;}@Overridepublic E get(int index) {if (index == 0) {return e0;} else if (index == 1 && e1 != null) {return e1;}throw outOfBounds(index);}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {throw new InvalidObjectException("not serial proxy");}private Object writeReplace() {if (e1 == null) {return new CollSer(CollSer.IMM_LIST, e0);} else {return new CollSer(CollSer.IMM_LIST, e0, e1);}}}static final class ListN<E> extends AbstractImmutableList<E>implements Serializable {static final List<?> EMPTY_LIST = new ListN<>();@Stableprivate final E[] elements;@SafeVarargsListN(E... input) {// copy and check manually to avoid TOCTOU@SuppressWarnings("unchecked")E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of inputfor (int i = 0; i < input.length; i++) {tmp[i] = Objects.requireNonNull(input[i]);}elements = tmp;}@Overridepublic boolean isEmpty() {return size() == 0;}@Overridepublic int size() {return elements.length;}@Overridepublic E get(int index) {return elements[index];}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {throw new InvalidObjectException("not serial proxy");}private Object writeReplace() {return new CollSer(CollSer.IMM_LIST, elements);}}// ---------- Set Implementations ----------static abstract class AbstractImmutableSet<E> extends AbstractImmutableCollection<E>implements Set<E> {@Overridepublic boolean equals(Object o) {if (o == this) {return true;} else if (!(o instanceof Set)) {return false;}Collection<?> c = (Collection<?>) o;if (c.size() != size()) {return false;}for (Object e : c) {if (e == null || !contains(e)) {return false;}}return true;}@Overridepublic abstract int hashCode();}@SuppressWarnings("unchecked")static <E> Set<E> emptySet() {return (Set<E>) SetN.EMPTY_SET;}static final class Set12<E> extends AbstractImmutableSet<E>implements Serializable {@Stablefinal E e0;@Stablefinal E e1;Set12(E e0) {this.e0 = Objects.requireNonNull(e0);this.e1 = null;}Set12(E e0, E e1) {if (e0.equals(Objects.requireNonNull(e1))) { // implicit nullcheck of e0throw new IllegalArgumentException("duplicate element: " + e0);}this.e0 = e0;this.e1 = e1;}@Overridepublic int size() {return (e1 == null) ? 1 : 2;}@Overridepublic boolean contains(Object o) {return o.equals(e0) || o.equals(e1); // implicit nullcheck of o}@Overridepublic int hashCode() {return e0.hashCode() + (e1 == null ? 0 : e1.hashCode());}@Overridepublic Iterator<E> iterator() {return new Iterator<>() {private int idx = size();@Overridepublic boolean hasNext() {return idx > 0;}@Overridepublic E next() {if (idx == 1) {idx = 0;return SALT >= 0 || e1 == null ? e0 : e1;} else if (idx == 2) {idx = 1;return SALT >= 0 ? e1 : e0;} else {throw new NoSuchElementException();}}};}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {throw new InvalidObjectException("not serial proxy");}private Object writeReplace() {if (e1 == null) {return new CollSer(CollSer.IMM_SET, e0);} else {return new CollSer(CollSer.IMM_SET, e0, e1);}}}/*** An array-based Set implementation. The element array must be strictly* larger than the size (the number of contained elements) so that at* least one null is always present.* @param <E> the element type*/static final class SetN<E> extends AbstractImmutableSet<E>implements Serializable {static final Set<?> EMPTY_SET = new SetN<>();@Stablefinal E[] elements;@Stablefinal int size;@SafeVarargs@SuppressWarnings("unchecked")SetN(E... input) {size = input.length; // implicit nullcheck of inputelements = (E[])new Object[EXPAND_FACTOR * input.length];for (int i = 0; i < input.length; i++) {E e = input[i];int idx = probe(e); // implicit nullcheck of eif (idx >= 0) {throw new IllegalArgumentException("duplicate element: " + e);} else {elements[-(idx + 1)] = e;}}}@Overridepublic int size() {return size;}@Overridepublic boolean contains(Object o) {Objects.requireNonNull(o);return size > 0 && probe(o) >= 0;}private final class SetNIterator implements Iterator<E> {private int remaining;private int idx;SetNIterator() {remaining = size();if (remaining > 0) {idx = Math.floorMod(SALT, elements.length);}}@Overridepublic boolean hasNext() {return remaining > 0;}private int nextIndex() {int idx = this.idx;if (SALT >= 0) {if (++idx >= elements.length) {idx = 0;}} else {if (--idx < 0) {idx = elements.length - 1;}}return this.idx = idx;}@Overridepublic E next() {if (hasNext()) {E element;// skip null elementswhile ((element = elements[nextIndex()]) == null) {}remaining--;return element;} else {throw new NoSuchElementException();}}}@Overridepublic Iterator<E> iterator() {return new SetNIterator();}@Overridepublic int hashCode() {int h = 0;for (E e : elements) {if (e != null) {h += e.hashCode();}}return h;}// returns index at which element is present; or if absent,// (-i - 1) where i is location where element should be inserted.// Callers are relying on this method to perform an implicit nullcheck// of peprivate int probe(Object pe) {int idx = Math.floorMod(pe.hashCode(), elements.length);while (true) {E ee = elements[idx];if (ee == null) {return -idx - 1;} else if (pe.equals(ee)) {return idx;} else if (++idx == elements.length) {idx = 0;}}}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {throw new InvalidObjectException("not serial proxy");}private Object writeReplace() {Object[] array = new Object[size];int dest = 0;for (Object o : elements) {if (o != null) {array[dest++] = o;}}return new CollSer(CollSer.IMM_SET, array);}}// ---------- Map Implementations ----------@SuppressWarnings("unchecked")static <K,V> Map<K,V> emptyMap() {return (Map<K,V>) MapN.EMPTY_MAP;}abstract static class AbstractImmutableMap<K,V> extends AbstractMap<K,V> implements Serializable {@Override public void clear() { throw uoe(); }@Override public V compute(K key, BiFunction<? super K,? super V,? extends V> rf) { throw uoe(); }@Override public V computeIfAbsent(K key, Function<? super K,? extends V> mf) { throw uoe(); }@Override public V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> rf) { throw uoe(); }@Override public V merge(K key, V value, BiFunction<? super V,? super V,? extends V> rf) { throw uoe(); }@Override public V put(K key, V value) { throw uoe(); }@Override public void putAll(Map<? extends K,? extends V> m) { throw uoe(); }@Override public V putIfAbsent(K key, V value) { throw uoe(); }@Override public V remove(Object key) { throw uoe(); }@Override public boolean remove(Object key, Object value) { throw uoe(); }@Override public V replace(K key, V value) { throw uoe(); }@Override public boolean replace(K key, V oldValue, V newValue) { throw uoe(); }@Override public void replaceAll(BiFunction<? super K,? super V,? extends V> f) { throw uoe(); }}static final class Map1<K,V> extends AbstractImmutableMap<K,V> {@Stableprivate final K k0;@Stableprivate final V v0;Map1(K k0, V v0) {this.k0 = Objects.requireNonNull(k0);this.v0 = Objects.requireNonNull(v0);}@Overridepublic Set<Map.Entry<K,V>> entrySet() {return Set.of(new KeyValueHolder<>(k0, v0));}@Overridepublic boolean containsKey(Object o) {return o.equals(k0); // implicit nullcheck of o}@Overridepublic boolean containsValue(Object o) {return o.equals(v0); // implicit nullcheck of o}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {throw new InvalidObjectException("not serial proxy");}private Object writeReplace() {return new CollSer(CollSer.IMM_MAP, k0, v0);}@Overridepublic int hashCode() {return k0.hashCode() ^ v0.hashCode();}}/*** An array-based Map implementation. There is a single array "table" that* contains keys and values interleaved: table[0] is kA, table[1] is vA,* table[2] is kB, table[3] is vB, etc. The table size must be even. It must* also be strictly larger than the size (the number of key-value pairs contained* in the map) so that at least one null key is always present.* @param <K> the key type* @param <V> the value type*/static final class MapN<K,V> extends AbstractImmutableMap<K,V> {static final Map<?,?> EMPTY_MAP = new MapN<>();@Stablefinal Object[] table; // pairs of key, value@Stablefinal int size; // number of pairsMapN(Object... input) {if ((input.length & 1) != 0) { // implicit nullcheck of inputthrow new InternalError("length is odd");}size = input.length >> 1;int len = EXPAND_FACTOR * input.length;len = (len + 1) & ~1; // ensure table is even lengthtable = new Object[len];for (int i = 0; i < input.length; i += 2) {@SuppressWarnings("unchecked")K k = Objects.requireNonNull((K)input[i]);@SuppressWarnings("unchecked")V v = Objects.requireNonNull((V)input[i+1]);int idx = probe(k);if (idx >= 0) {throw new IllegalArgumentException("duplicate key: " + k);} else {int dest = -(idx + 1);table[dest] = k;table[dest+1] = v;}}}@Overridepublic boolean containsKey(Object o) {Objects.requireNonNull(o);return size > 0 && probe(o) >= 0;}@Overridepublic boolean containsValue(Object o) {Objects.requireNonNull(o);for (int i = 1; i < table.length; i += 2) {Object v = table[i];if (v != null && o.equals(v)) {return true;}}return false;}@Overridepublic int hashCode() {int hash = 0;for (int i = 0; i < table.length; i += 2) {Object k = table[i];if (k != null) {hash += k.hashCode() ^ table[i + 1].hashCode();}}return hash;}@Override@SuppressWarnings("unchecked")public V get(Object o) {if (size == 0) {Objects.requireNonNull(o);return null;}int i = probe(o);if (i >= 0) {return (V)table[i+1];} else {return null;}}@Overridepublic int size() {return size;}class MapNIterator implements Iterator<Map.Entry<K,V>> {private int remaining;private int idx;MapNIterator() {remaining = size();if (remaining > 0) {idx = Math.floorMod(SALT, table.length >> 1) << 1;}}@Overridepublic boolean hasNext() {return remaining > 0;}private int nextIndex() {int idx = this.idx;if (SALT >= 0) {if ((idx += 2) >= table.length) {idx = 0;}} else {if ((idx -= 2) < 0) {idx = table.length - 2;}}return this.idx = idx;}@Overridepublic Map.Entry<K,V> next() {if (hasNext()) {while (table[nextIndex()] == null) {}@SuppressWarnings("unchecked")Map.Entry<K,V> e =new KeyValueHolder<>((K)table[idx], (V)table[idx+1]);remaining--;return e;} else {throw new NoSuchElementException();}}}@Overridepublic Set<Map.Entry<K,V>> entrySet() {return new AbstractSet<>() {@Overridepublic int size() {return MapN.this.size;}@Overridepublic Iterator<Map.Entry<K,V>> iterator() {return new MapNIterator();}};}// returns index at which the probe key is present; or if absent,// (-i - 1) where i is location where element should be inserted.// Callers are relying on this method to perform an implicit nullcheck// of pk.private int probe(Object pk) {int idx = Math.floorMod(pk.hashCode(), table.length >> 1) << 1;while (true) {@SuppressWarnings("unchecked")K ek = (K)table[idx];if (ek == null) {return -idx - 1;} else if (pk.equals(ek)) {return idx;} else if ((idx += 2) == table.length) {idx = 0;}}}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {throw new InvalidObjectException("not serial proxy");}private Object writeReplace() {Object[] array = new Object[2 * size];int len = table.length;int dest = 0;for (int i = 0; i < len; i += 2) {if (table[i] != null) {array[dest++] = table[i];array[dest++] = table[i+1];}}return new CollSer(CollSer.IMM_MAP, array);}}}// ---------- Serialization Proxy ----------/*** A unified serialization proxy class for the immutable collections.** @serial* @since 9*/final class CollSer implements Serializable {private static final long serialVersionUID = 6309168927139932177L;static final int IMM_LIST = 1;static final int IMM_SET = 2;static final int IMM_MAP = 3;/*** Indicates the type of collection that is serialized.* The low order 8 bits have the value 1 for an immutable* {@code List}, 2 for an immutable {@code Set}, and 3 for* an immutable {@code Map}. Any other value causes an* {@link InvalidObjectException} to be thrown. The high* order 24 bits are zero when an instance is serialized,* and they are ignored when an instance is deserialized.* They can thus be used by future implementations without* causing compatibility issues.** <p>The tag value also determines the interpretation of the* transient {@code Object[] array} field.* For {@code List} and {@code Set}, the array's length is the size* of the collection, and the array contains the elements of the collection.* Null elements are not allowed. For {@code Set}, duplicate elements* are not allowed.** <p>For {@code Map}, the array's length is twice the number of mappings* present in the map. The array length is necessarily even.* The array contains a succession of key and value pairs:* {@code k1, v1, k2, v2, ..., kN, vN.} Nulls are not allowed,* and duplicate keys are not allowed.** @serial* @since 9*/private final int tag;/*** @serial* @since 9*/private transient Object[] array;CollSer(int t, Object... a) {tag = t;array = a;}/*** Reads objects from the stream and stores them* in the transient {@code Object[] array} field.** @serialData* A nonnegative int, indicating the count of objects,* followed by that many objects.** @param ois the ObjectInputStream from which data is read* @throws IOException if an I/O error occurs* @throws ClassNotFoundException if a serialized class cannot be loaded* @throws InvalidObjectException if the count is negative* @since 9*/private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {ois.defaultReadObject();int len = ois.readInt();if (len < 0) {throw new InvalidObjectException("negative length " + len);}SharedSecrets.getJavaObjectInputStreamAccess().checkArray(ois, Object[].class, len);Object[] a = new Object[len];for (int i = 0; i < len; i++) {a[i] = ois.readObject();}array = a;}/*** Writes objects to the stream from* the transient {@code Object[] array} field.** @serialData* A nonnegative int, indicating the count of objects,* followed by that many objects.** @param oos the ObjectOutputStream to which data is written* @throws IOException if an I/O error occurs* @since 9*/private void writeObject(ObjectOutputStream oos) throws IOException {oos.defaultWriteObject();oos.writeInt(array.length);for (int i = 0; i < array.length; i++) {oos.writeObject(array[i]);}}/*** Creates and returns an immutable collection from this proxy class.* The instance returned is created as if by calling one of the* static factory methods for* <a href="List.html#immutable">List</a>,* <a href="Map.html#immutable">Map</a>, or* <a href="Set.html#immutable">Set</a>.* This proxy class is the serial form for all immutable collection instances,* regardless of implementation type. This is necessary to ensure that the* existence of any particular implementation type is kept out of the* serialized form.** @return a collection created from this proxy object* @throws InvalidObjectException if the tag value is illegal or if an exception* is thrown during creation of the collection* @throws ObjectStreamException if another serialization error has occurred* @since 9*/private Object readResolve() throws ObjectStreamException {try {if (array == null) {throw new InvalidObjectException("null array");}// use low order 8 bits to indicate "kind"// ignore high order 24 bitsswitch (tag & 0xff) {case IMM_LIST:return List.of(array);case IMM_SET:return Set.of(array);case IMM_MAP:if (array.length == 0) {return ImmutableCollections.emptyMap();} else if (array.length == 2) {return new ImmutableCollections.Map1<>(array[0], array[1]);} else {return new ImmutableCollections.MapN<>(array);}default:throw new InvalidObjectException(String.format("invalid flags 0x%x", tag));}} catch (NullPointerException|IllegalArgumentException ex) {InvalidObjectException ioe = new InvalidObjectException("invalid object");ioe.initCause(ex);throw ioe;}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。