8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,480 @@
/*
* Copyright (c) 1997, 2013, 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;
/**
* This class provides a skeletal implementation of the {@code Collection}
* interface, to minimize the effort required to implement this interface. <p>
*
* To implement an unmodifiable collection, the programmer needs only to
* extend this class and provide implementations for the {@code iterator} and
* {@code size} methods. (The iterator returned by the {@code iterator}
* method must implement {@code hasNext} and {@code next}.)<p>
*
* To implement a modifiable collection, the programmer must additionally
* override this class's {@code add} method (which otherwise throws an
* {@code UnsupportedOperationException}), and the iterator returned by the
* {@code iterator} method must additionally implement its {@code remove}
* method.<p>
*
* The programmer should generally provide a void (no argument) and
* {@code Collection} constructor, as per the recommendation in the
* {@code Collection} interface specification.<p>
*
* The documentation for each non-abstract method in this class describes its
* implementation in detail. Each of these methods may be overridden if
* the collection being implemented admits a more efficient implementation.<p>
*
* This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch
* @author Neal Gafter
* @see Collection
* @since 1.2
*/
public abstract class AbstractCollection<E> implements Collection<E> {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected AbstractCollection() {
}
// Query Operations
/**
* Returns an iterator over the elements contained in this collection.
*
* @return an iterator over the elements contained in this collection
*/
public abstract Iterator<E> iterator();
public abstract int size();
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns {@code size() == 0}.
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over the elements in the collection,
* checking each element in turn for equality with the specified element.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public boolean contains(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return true;
} else {
while (it.hasNext())
if (o.equals(it.next()))
return true;
}
return false;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns an array containing all the elements
* returned by this collection's iterator, in the same order, stored in
* consecutive elements of the array, starting with index {@code 0}.
* The length of the returned array is equal to the number of elements
* returned by the iterator, even if the size of this collection changes
* during iteration, as might happen if the collection permits
* concurrent modification during iteration. The {@code size} method is
* called only as an optimization hint; the correct result is returned
* even if the iterator returns a different number of elements.
*
* <p>This method is equivalent to:
*
* <pre> {@code
* List<E> list = new ArrayList<E>(size());
* for (E e : this)
* list.add(e);
* return list.toArray();
* }</pre>
*/
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns an array containing all the elements
* returned by this collection's iterator in the same order, stored in
* consecutive elements of the array, starting with index {@code 0}.
* If the number of elements returned by the iterator is too large to
* fit into the specified array, then the elements are returned in a
* newly allocated array with length equal to the number of elements
* returned by the iterator, even if the size of this collection
* changes during iteration, as might happen if the collection permits
* concurrent modification during iteration. The {@code size} method is
* called only as an optimization hint; the correct result is returned
* even if the iterator returns a different number of elements.
*
* <p>This method is equivalent to:
*
* <pre> {@code
* List<E> list = new ArrayList<E>(size());
* for (E e : this)
* list.add(e);
* return list.toArray(a);
* }</pre>
*
* @throws ArrayStoreException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
// Estimate size of array; be prepared to see more or fewer elements
int size = size();
T[] r = a.length >= size ? a :
(T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) { // fewer elements than expected
if (a == r) {
r[i] = null; // null-terminate
} else if (a.length < i) {
return Arrays.copyOf(r, i);
} else {
System.arraycopy(r, 0, a, 0, i);
if (a.length > i) {
a[i] = null;
}
}
return a;
}
r[i] = (T)it.next();
}
// more elements than expected
return it.hasNext() ? finishToArray(r, it) : r;
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Reallocates the array being used within toArray when the iterator
* returned more elements than expected, and finishes filling it from
* the iterator.
*
* @param r the array, replete with previously stored elements
* @param it the in-progress iterator over this collection
* @return array containing the elements in the given array, plus any
* further elements returned by the iterator, trimmed to size
*/
@SuppressWarnings("unchecked")
private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
int i = r.length;
while (it.hasNext()) {
int cap = r.length;
if (i == cap) {
int newCap = cap + (cap >> 1) + 1;
// overflow-conscious code
if (newCap - MAX_ARRAY_SIZE > 0)
newCap = hugeCapacity(cap + 1);
r = Arrays.copyOf(r, newCap);
}
r[i++] = (T)it.next();
}
// trim if overallocated
return (i == r.length) ? r : Arrays.copyOf(r, i);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError
("Required array size too large");
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
// Modification Operations
/**
* {@inheritDoc}
*
* @implSpec
* This implementation always throws an
* {@code UnsupportedOperationException}.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IllegalStateException {@inheritDoc}
*/
public boolean add(E e) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over the collection looking for the
* specified element. If it finds the element, it removes the element
* from the collection using the iterator's remove method.
*
* <p>Note that this implementation throws an
* {@code UnsupportedOperationException} if the iterator returned by this
* collection's iterator method does not implement the {@code remove}
* method and this collection contains the specified object.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public boolean remove(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext()) {
if (it.next()==null) {
it.remove();
return true;
}
}
} else {
while (it.hasNext()) {
if (o.equals(it.next())) {
it.remove();
return true;
}
}
}
return false;
}
// Bulk Operations
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over the specified collection,
* checking each element returned by the iterator in turn to see
* if it's contained in this collection. If all elements are so
* contained {@code true} is returned, otherwise {@code false}.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @see #contains(Object)
*/
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over the specified collection, and adds
* each object returned by the iterator to this collection, in turn.
*
* <p>Note that this implementation will throw an
* {@code UnsupportedOperationException} unless {@code add} is
* overridden (assuming the specified collection is non-empty).
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IllegalStateException {@inheritDoc}
*
* @see #add(Object)
*/
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over this collection, checking each
* element returned by the iterator in turn to see if it's contained
* in the specified collection. If it's so contained, it's removed from
* this collection with the iterator's {@code remove} method.
*
* <p>Note that this implementation will throw an
* {@code UnsupportedOperationException} if the iterator returned by the
* {@code iterator} method does not implement the {@code remove} method
* and this collection contains one or more elements in common with the
* specified collection.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*
* @see #remove(Object)
* @see #contains(Object)
*/
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over this collection, checking each
* element returned by the iterator in turn to see if it's contained
* in the specified collection. If it's not so contained, it's removed
* from this collection with the iterator's {@code remove} method.
*
* <p>Note that this implementation will throw an
* {@code UnsupportedOperationException} if the iterator returned by the
* {@code iterator} method does not implement the {@code remove} method
* and this collection contains one or more elements not present in the
* specified collection.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*
* @see #remove(Object)
* @see #contains(Object)
*/
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<E> it = iterator();
while (it.hasNext()) {
if (!c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over this collection, removing each
* element using the {@code Iterator.remove} operation. Most
* implementations will probably choose to override this method for
* efficiency.
*
* <p>Note that this implementation will throw an
* {@code UnsupportedOperationException} if the iterator returned by this
* collection's {@code iterator} method does not implement the
* {@code remove} method and this collection is non-empty.
*
* @throws UnsupportedOperationException {@inheritDoc}
*/
public void clear() {
Iterator<E> it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}
// String conversion
/**
* Returns a string representation of this collection. The string
* representation consists of a list of the collection's elements in the
* order they are returned by its iterator, enclosed in square brackets
* ({@code "[]"}). Adjacent elements are separated by the characters
* {@code ", "} (comma and space). Elements are converted to strings as
* by {@link String#valueOf(Object)}.
*
* @return a string representation of this collection
*/
public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
}

View file

@ -0,0 +1,942 @@
/*
* Copyright (c) 1997, 2016, 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;
import java.util.function.Consumer;
/**
* This class provides a skeletal implementation of the {@link List}
* interface to minimize the effort required to implement this interface
* backed by a "random access" data store (such as an array). For sequential
* access data (such as a linked list), {@link AbstractSequentialList} should
* be used in preference to this class.
*
* <p>To implement an unmodifiable list, the programmer needs only to extend
* this class and provide implementations for the {@link #get(int)} and
* {@link List#size() size()} methods.
*
* <p>To implement a modifiable list, the programmer must additionally
* override the {@link #set(int, Object) set(int, E)} method (which otherwise
* throws an {@code UnsupportedOperationException}). If the list is
* variable-size the programmer must additionally override the
* {@link #add(int, Object) add(int, E)} and {@link #remove(int)} methods.
*
* <p>The programmer should generally provide a void (no argument) and collection
* constructor, as per the recommendation in the {@link Collection} interface
* specification.
*
* <p>Unlike the other abstract collection implementations, the programmer does
* <i>not</i> have to provide an iterator implementation; the iterator and
* list iterator are implemented by this class, on top of the "random access"
* methods:
* {@link #get(int)},
* {@link #set(int, Object) set(int, E)},
* {@link #add(int, Object) add(int, E)} and
* {@link #remove(int)}.
*
* <p>The documentation for each non-abstract method in this class describes its
* implementation in detail. Each of these methods may be overridden if the
* collection being implemented admits a more efficient implementation.
*
* <p>This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch
* @author Neal Gafter
* @since 1.2
*/
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected AbstractList() {
}
/**
* Appends the specified element to the end of this list (optional
* operation).
*
* <p>Lists that support this operation may place limitations on what
* elements may be added to this list. In particular, some
* lists will refuse to add null elements, and others will impose
* restrictions on the type of elements that may be added. List
* classes should clearly specify in their documentation any restrictions
* on what elements may be added.
*
* @implSpec
* This implementation calls {@code add(size(), e)}.
*
* <p>Note that this implementation throws an
* {@code UnsupportedOperationException} unless
* {@link #add(int, Object) add(int, E)} is overridden.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
* @throws UnsupportedOperationException if the {@code add} operation
* is not supported by this list
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this list
* @throws NullPointerException if the specified element is null and this
* list does not permit null elements
* @throws IllegalArgumentException if some property of this element
* prevents it from being added to this list
*/
public boolean add(E e) {
add(size(), e);
return true;
}
/**
* {@inheritDoc}
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public abstract E get(int index);
/**
* {@inheritDoc}
*
* @implSpec
* This implementation always throws an
* {@code UnsupportedOperationException}.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation always throws an
* {@code UnsupportedOperationException}.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation always throws an
* {@code UnsupportedOperationException}.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E remove(int index) {
throw new UnsupportedOperationException();
}
// Search Operations
/**
* {@inheritDoc}
*
* @implSpec
* This implementation first gets a list iterator (with
* {@code listIterator()}). Then, it iterates over the list until the
* specified element is found or the end of the list is reached.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public int indexOf(Object o) {
ListIterator<E> it = listIterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return it.previousIndex();
} else {
while (it.hasNext())
if (o.equals(it.next()))
return it.previousIndex();
}
return -1;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation first gets a list iterator that points to the end
* of the list (with {@code listIterator(size())}). Then, it iterates
* backwards over the list until the specified element is found, or the
* beginning of the list is reached.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public int lastIndexOf(Object o) {
ListIterator<E> it = listIterator(size());
if (o==null) {
while (it.hasPrevious())
if (it.previous()==null)
return it.nextIndex();
} else {
while (it.hasPrevious())
if (o.equals(it.previous()))
return it.nextIndex();
}
return -1;
}
// Bulk Operations
/**
* Removes all of the elements from this list (optional operation).
* The list will be empty after this call returns.
*
* @implSpec
* This implementation calls {@code removeRange(0, size())}.
*
* <p>Note that this implementation throws an
* {@code UnsupportedOperationException} unless {@code remove(int
* index)} or {@code removeRange(int fromIndex, int toIndex)} is
* overridden.
*
* @throws UnsupportedOperationException if the {@code clear} operation
* is not supported by this list
*/
public void clear() {
removeRange(0, size());
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation gets an iterator over the specified collection
* and iterates over it, inserting the elements obtained from the
* iterator into this list at the appropriate position, one at a time,
* using {@code add(int, E)}.
* Many implementations will override this method for efficiency.
*
* <p>Note that this implementation throws an
* {@code UnsupportedOperationException} unless
* {@link #add(int, Object) add(int, E)} is overridden.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
boolean modified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
return modified;
}
// Iterators
/**
* Returns an iterator over the elements in this list in proper sequence.
*
* @implSpec
* This implementation returns a straightforward implementation of the
* iterator interface, relying on the backing list's {@code size()},
* {@code get(int)}, and {@code remove(int)} methods.
*
* <p>Note that the iterator returned by this method will throw an
* {@link UnsupportedOperationException} in response to its
* {@code remove} method unless the list's {@code remove(int)} method is
* overridden.
*
* <p>This implementation can be made to throw runtime exceptions in the
* face of concurrent modification, as described in the specification
* for the (protected) {@link #modCount} field.
*
* @return an iterator over the elements in this list in proper sequence
*/
public Iterator<E> iterator() {
return new Itr();
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns {@code listIterator(0)}.
*
* @see #listIterator(int)
*/
public ListIterator<E> listIterator() {
return listIterator(0);
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns a straightforward implementation of the
* {@code ListIterator} interface that extends the implementation of the
* {@code Iterator} interface returned by the {@code iterator()} method.
* The {@code ListIterator} implementation relies on the backing list's
* {@code get(int)}, {@code set(int, E)}, {@code add(int, E)}
* and {@code remove(int)} methods.
*
* <p>Note that the list iterator returned by this implementation will
* throw an {@link UnsupportedOperationException} in response to its
* {@code remove}, {@code set} and {@code add} methods unless the
* list's {@code remove(int)}, {@code set(int, E)}, and
* {@code add(int, E)} methods are overridden.
*
* <p>This implementation can be made to throw runtime exceptions in the
* face of concurrent modification, as described in the specification for
* the (protected) {@link #modCount} field.
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public ListIterator<E> listIterator(final int index) {
rangeCheckForAdd(index);
return new ListItr(index);
}
private class Itr implements Iterator<E> {
/**
* Index of element to be returned by subsequent call to next.
*/
int cursor = 0;
/**
* Index of element returned by most recent call to next or
* previous. Reset to -1 if this element is deleted by a call
* to remove.
*/
int lastRet = -1;
/**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public E previous() {
checkForComodification();
try {
int i = cursor - 1;
E previous = get(i);
lastRet = cursor = i;
return previous;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor-1;
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.set(lastRet, e);
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
AbstractList.this.add(i, e);
lastRet = -1;
cursor = i + 1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns a list that subclasses
* {@code AbstractList}. The subclass stores, in private fields, the
* size of the subList (which can change over its lifetime), and the
* expected {@code modCount} value of the backing list. There are two
* variants of the subclass, one of which implements {@code RandomAccess}.
* If this list implements {@code RandomAccess} the returned list will
* be an instance of the subclass that implements {@code RandomAccess}.
*
* <p>The subclass's {@code set(int, E)}, {@code get(int)},
* {@code add(int, E)}, {@code remove(int)}, {@code addAll(int,
* Collection)} and {@code removeRange(int, int)} methods all
* delegate to the corresponding methods on the backing abstract list,
* after bounds-checking the index and adjusting for the offset. The
* {@code addAll(Collection c)} method merely returns {@code addAll(size,
* c)}.
*
* <p>The {@code listIterator(int)} method returns a "wrapper object"
* over a list iterator on the backing list, which is created with the
* corresponding method on the backing list. The {@code iterator} method
* merely returns {@code listIterator()}, and the {@code size} method
* merely returns the subclass's {@code size} field.
*
* <p>All methods first check to see if the actual {@code modCount} of
* the backing list is equal to its expected value, and throw a
* {@code ConcurrentModificationException} if it is not.
*
* @throws IndexOutOfBoundsException if an endpoint index value is out of range
* {@code (fromIndex < 0 || toIndex > size)}
* @throws IllegalArgumentException if the endpoint indices are out of order
* {@code (fromIndex > toIndex)}
*/
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size());
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(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 + ")");
}
// Comparison and hashing
/**
* Compares the specified object with this list for equality. Returns
* {@code true} if and only if the specified object is also a list, both
* lists have the same size, and all corresponding pairs of elements in
* the two lists are <i>equal</i>. (Two elements {@code e1} and
* {@code e2} are <i>equal</i> if {@code (e1==null ? e2==null :
* e1.equals(e2))}.) In other words, two lists are defined to be
* equal if they contain the same elements in the same order.
*
* @implSpec
* This implementation first checks if the specified object is this
* list. If so, it returns {@code true}; if not, it checks if the
* specified object is a list. If not, it returns {@code false}; if so,
* it iterates over both lists, comparing corresponding pairs of elements.
* If any comparison returns {@code false}, this method returns
* {@code false}. If either iterator runs out of elements before the
* other it returns {@code false} (as the lists are of unequal length);
* otherwise it returns {@code true} when the iterations complete.
*
* @param o the object to be compared for equality with this list
* @return {@code true} if the specified object is equal to this list
*/
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator<?> e2 = ((List<?>) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
/**
* Returns the hash code value for this list.
*
* @implSpec
* This implementation uses exactly the code that is used to define the
* list hash function in the documentation for the {@link List#hashCode}
* method.
*
* @return the hash code value for this list
*/
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
/**
* Removes from this list all of the elements whose index is between
* {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
* Shifts any succeeding elements to the left (reduces their index).
* This call shortens the list by {@code (toIndex - fromIndex)} elements.
* (If {@code toIndex==fromIndex}, this operation has no effect.)
*
* <p>This method is called by the {@code clear} operation on this list
* and its subLists. Overriding this method to take advantage of
* the internals of the list implementation can <i>substantially</i>
* improve the performance of the {@code clear} operation on this list
* and its subLists.
*
* @implSpec
* This implementation gets a list iterator positioned before
* {@code fromIndex}, and repeatedly calls {@code ListIterator.next}
* followed by {@code ListIterator.remove} until the entire range has
* been removed. <b>Note: if {@code ListIterator.remove} requires linear
* time, this implementation requires quadratic time.</b>
*
* @param fromIndex index of first element to be removed
* @param toIndex index after last element to be removed
*/
protected void removeRange(int fromIndex, int toIndex) {
ListIterator<E> it = listIterator(fromIndex);
for (int i=0, n=toIndex-fromIndex; i<n; i++) {
it.next();
it.remove();
}
}
/**
* The number of times this list has been <i>structurally modified</i>.
* Structural modifications are those that change the size of the
* list, or otherwise perturb it in such a fashion that iterations in
* progress may yield incorrect results.
*
* <p>This field is used by the iterator and list iterator implementation
* returned by the {@code iterator} and {@code listIterator} methods.
* If the value of this field changes unexpectedly, the iterator (or list
* iterator) will throw a {@code ConcurrentModificationException} in
* response to the {@code next}, {@code remove}, {@code previous},
* {@code set} or {@code add} operations. This provides
* <i>fail-fast</i> behavior, rather than non-deterministic behavior in
* the face of concurrent modification during iteration.
*
* <p><b>Use of this field by subclasses is optional.</b> If a subclass
* wishes to provide fail-fast iterators (and list iterators), then it
* merely has to increment this field in its {@code add(int, E)} and
* {@code remove(int)} methods (and any other methods that it overrides
* that result in structural modifications to the list). A single call to
* {@code add(int, E)} or {@code remove(int)} must add no more than
* one to this field, or the iterators (and list iterators) will throw
* bogus {@code ConcurrentModificationExceptions}. If an implementation
* does not wish to provide fail-fast iterators, this field may be
* ignored.
*/
protected transient int modCount = 0;
private void rangeCheckForAdd(int index) {
if (index < 0 || index > size())
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size();
}
/**
* An index-based split-by-two, lazily initialized Spliterator covering
* a List that access elements via {@link List#get}.
*
* If access results in an IndexOutOfBoundsException then a
* ConcurrentModificationException is thrown instead (since the list has
* been structurally modified while traversing).
*
* If the List is an instance of AbstractList then concurrent modification
* checking is performed using the AbstractList's modCount field.
*/
static final class RandomAccessSpliterator<E> implements Spliterator<E> {
private final List<E> list;
private int index; // current index, modified on advance/split
private int fence; // -1 until used; then one past last index
// The following fields are valid if covering an AbstractList
private final AbstractList<E> alist;
private int expectedModCount; // initialized when fence set
RandomAccessSpliterator(List<E> list) {
assert list instanceof RandomAccess;
this.list = list;
this.index = 0;
this.fence = -1;
this.alist = list instanceof AbstractList ? (AbstractList<E>) list : null;
this.expectedModCount = alist != null ? alist.modCount : 0;
}
/** Create new spliterator covering the given range */
private RandomAccessSpliterator(RandomAccessSpliterator<E> parent,
int origin, int fence) {
this.list = parent.list;
this.index = origin;
this.fence = fence;
this.alist = parent.alist;
this.expectedModCount = parent.expectedModCount;
}
private int getFence() { // initialize fence to size on first use
int hi;
List<E> lst = list;
if ((hi = fence) < 0) {
if (alist != null) {
expectedModCount = alist.modCount;
}
hi = fence = lst.size();
}
return hi;
}
public Spliterator<E> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null : // divide range in half unless too small
new RandomAccessSpliterator<>(this, lo, index = mid);
}
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
int hi = getFence(), i = index;
if (i < hi) {
index = i + 1;
action.accept(get(list, i));
checkAbstractListModCount(alist, expectedModCount);
return true;
}
return false;
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
List<E> lst = list;
int hi = getFence();
int i = index;
index = hi;
for (; i < hi; i++) {
action.accept(get(lst, i));
}
checkAbstractListModCount(alist, expectedModCount);
}
public long estimateSize() {
return (long) (getFence() - index);
}
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
private static <E> E get(List<E> list, int i) {
try {
return list.get(i);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
static void checkAbstractListModCount(AbstractList<?> alist, int expectedModCount) {
if (alist != null && alist.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
}
private static class SubList<E> extends AbstractList<E> {
private final AbstractList<E> root;
private final SubList<E> parent;
private final int offset;
protected int size;
/**
* Constructs a sublist of an arbitrary AbstractList, which is
* not a SubList itself.
*/
public SubList(AbstractList<E> root, int fromIndex, int toIndex) {
this.root = root;
this.parent = null;
this.offset = fromIndex;
this.size = toIndex - fromIndex;
this.modCount = root.modCount;
}
/**
* Constructs a sublist of another SubList.
*/
protected SubList(SubList<E> parent, int fromIndex, int toIndex) {
this.root = parent.root;
this.parent = parent;
this.offset = parent.offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = root.modCount;
}
public E set(int index, E element) {
Objects.checkIndex(index, size);
checkForComodification();
return root.set(offset + index, element);
}
public E get(int index) {
Objects.checkIndex(index, size);
checkForComodification();
return root.get(offset + index);
}
public int size() {
checkForComodification();
return size;
}
public void add(int index, E element) {
rangeCheckForAdd(index);
checkForComodification();
root.add(offset + index, element);
updateSizeAndModCount(1);
}
public E remove(int index) {
Objects.checkIndex(index, size);
checkForComodification();
E result = root.remove(offset + index);
updateSizeAndModCount(-1);
return result;
}
protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
root.removeRange(offset + fromIndex, offset + toIndex);
updateSizeAndModCount(fromIndex - toIndex);
}
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
int cSize = c.size();
if (cSize==0)
return false;
checkForComodification();
root.addAll(offset + index, c);
updateSizeAndModCount(cSize);
return true;
}
public Iterator<E> iterator() {
return listIterator();
}
public ListIterator<E> listIterator(int index) {
checkForComodification();
rangeCheckForAdd(index);
return new ListIterator<E>() {
private final ListIterator<E> i =
root.listIterator(offset + index);
public boolean hasNext() {
return nextIndex() < size;
}
public E next() {
if (hasNext())
return i.next();
else
throw new NoSuchElementException();
}
public boolean hasPrevious() {
return previousIndex() >= 0;
}
public E previous() {
if (hasPrevious())
return i.previous();
else
throw new NoSuchElementException();
}
public int nextIndex() {
return i.nextIndex() - offset;
}
public int previousIndex() {
return i.previousIndex() - offset;
}
public void remove() {
i.remove();
updateSizeAndModCount(-1);
}
public void set(E e) {
i.set(e);
}
public void add(E e) {
i.add(e);
updateSizeAndModCount(1);
}
};
}
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList<>(this, fromIndex, toIndex);
}
private void rangeCheckForAdd(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
private void checkForComodification() {
if (root.modCount != this.modCount)
throw new ConcurrentModificationException();
}
private void updateSizeAndModCount(int sizeChange) {
SubList<E> slist = this;
do {
slist.size += sizeChange;
slist.modCount = root.modCount;
slist = slist.parent;
} while (slist != null);
}
}
private static class RandomAccessSubList<E>
extends SubList<E> implements RandomAccess {
/**
* Constructs a sublist of an arbitrary AbstractList, which is
* not a RandomAccessSubList itself.
*/
RandomAccessSubList(AbstractList<E> root,
int fromIndex, int toIndex) {
super(root, fromIndex, toIndex);
}
/**
* Constructs a sublist of another RandomAccessSubList.
*/
RandomAccessSubList(RandomAccessSubList<E> parent,
int fromIndex, int toIndex) {
super(parent, fromIndex, toIndex);
}
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new RandomAccessSubList<>(this, fromIndex, toIndex);
}
}
}

View file

@ -0,0 +1,857 @@
/*
* Copyright (c) 1997, 2013, 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;
import java.util.Map.Entry;
/**
* This class provides a skeletal implementation of the {@code Map}
* interface, to minimize the effort required to implement this interface.
*
* <p>To implement an unmodifiable map, the programmer needs only to extend this
* class and provide an implementation for the {@code entrySet} method, which
* returns a set-view of the map's mappings. Typically, the returned set
* will, in turn, be implemented atop {@code AbstractSet}. This set should
* not support the {@code add} or {@code remove} methods, and its iterator
* should not support the {@code remove} method.
*
* <p>To implement a modifiable map, the programmer must additionally override
* this class's {@code put} method (which otherwise throws an
* {@code UnsupportedOperationException}), and the iterator returned by
* {@code entrySet().iterator()} must additionally implement its
* {@code remove} method.
*
* <p>The programmer should generally provide a void (no argument) and map
* constructor, as per the recommendation in the {@code Map} interface
* specification.
*
* <p>The documentation for each non-abstract method in this class describes its
* implementation in detail. Each of these methods may be overridden if the
* map being implemented admits a more efficient implementation.
*
* <p>This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
*
* @author Josh Bloch
* @author Neal Gafter
* @see Map
* @see Collection
* @since 1.2
*/
public abstract class AbstractMap<K,V> implements Map<K,V> {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected AbstractMap() {
}
// Query Operations
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns {@code entrySet().size()}.
*/
public int size() {
return entrySet().size();
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns {@code size() == 0}.
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over {@code entrySet()} searching
* for an entry with the specified value. If such an entry is found,
* {@code true} is returned. If the iteration terminates without
* finding such an entry, {@code false} is returned. Note that this
* implementation requires linear time in the size of the map.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public boolean containsValue(Object value) {
Iterator<Entry<K,V>> i = entrySet().iterator();
if (value==null) {
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getValue()==null)
return true;
}
} else {
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (value.equals(e.getValue()))
return true;
}
}
return false;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over {@code entrySet()} searching
* for an entry with the specified key. If such an entry is found,
* {@code true} is returned. If the iteration terminates without
* finding such an entry, {@code false} is returned. Note that this
* implementation requires linear time in the size of the map; many
* implementations will override this method.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public boolean containsKey(Object key) {
Iterator<Map.Entry<K,V>> i = entrySet().iterator();
if (key==null) {
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getKey()==null)
return true;
}
} else {
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (key.equals(e.getKey()))
return true;
}
}
return false;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over {@code entrySet()} searching
* for an entry with the specified key. If such an entry is found,
* the entry's value is returned. If the iteration terminates without
* finding such an entry, {@code null} is returned. Note that this
* implementation requires linear time in the size of the map; many
* implementations will override this method.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public V get(Object key) {
Iterator<Entry<K,V>> i = entrySet().iterator();
if (key==null) {
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getKey()==null)
return e.getValue();
}
} else {
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (key.equals(e.getKey()))
return e.getValue();
}
}
return null;
}
// Modification Operations
/**
* {@inheritDoc}
*
* @implSpec
* This implementation always throws an
* {@code UnsupportedOperationException}.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over {@code entrySet()} searching for an
* entry with the specified key. If such an entry is found, its value is
* obtained with its {@code getValue} operation, the entry is removed
* from the collection (and the backing map) with the iterator's
* {@code remove} operation, and the saved value is returned. If the
* iteration terminates without finding such an entry, {@code null} is
* returned. Note that this implementation requires linear time in the
* size of the map; many implementations will override this method.
*
* <p>Note that this implementation throws an
* {@code UnsupportedOperationException} if the {@code entrySet}
* iterator does not support the {@code remove} method and this map
* contains a mapping for the specified key.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public V remove(Object key) {
Iterator<Entry<K,V>> i = entrySet().iterator();
Entry<K,V> correctEntry = null;
if (key==null) {
while (correctEntry==null && i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getKey()==null)
correctEntry = e;
}
} else {
while (correctEntry==null && i.hasNext()) {
Entry<K,V> e = i.next();
if (key.equals(e.getKey()))
correctEntry = e;
}
}
V oldValue = null;
if (correctEntry !=null) {
oldValue = correctEntry.getValue();
i.remove();
}
return oldValue;
}
// Bulk Operations
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over the specified map's
* {@code entrySet()} collection, and calls this map's {@code put}
* operation once for each entry returned by the iteration.
*
* <p>Note that this implementation throws an
* {@code UnsupportedOperationException} if this map does not support
* the {@code put} operation and the specified map is nonempty.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
public void putAll(Map<? extends K, ? extends V> m) {
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
put(e.getKey(), e.getValue());
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation calls {@code entrySet().clear()}.
*
* <p>Note that this implementation throws an
* {@code UnsupportedOperationException} if the {@code entrySet}
* does not support the {@code clear} operation.
*
* @throws UnsupportedOperationException {@inheritDoc}
*/
public void clear() {
entrySet().clear();
}
// Views
/**
* Each of these fields are initialized to contain an instance of the
* appropriate view the first time this view is requested. The views are
* stateless, so there's no reason to create more than one of each.
*
* <p>Since there is no synchronization performed while accessing these fields,
* it is expected that java.util.Map view classes using these fields have
* no non-final fields (or any fields at all except for outer-this). Adhering
* to this rule would make the races on these fields benign.
*
* <p>It is also imperative that implementations read the field only once,
* as in:
*
* <pre> {@code
* public Set<K> keySet() {
* Set<K> ks = keySet; // single racy read
* if (ks == null) {
* ks = new KeySet();
* keySet = ks;
* }
* return ks;
* }
*}</pre>
*/
transient Set<K> keySet;
transient Collection<V> values;
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns a set that subclasses {@link AbstractSet}.
* The subclass's iterator method returns a "wrapper object" over this
* map's {@code entrySet()} iterator. The {@code size} method
* delegates to this map's {@code size} method and the
* {@code contains} method delegates to this map's
* {@code containsKey} method.
*
* <p>The set is created the first time this method is called,
* and returned in response to all subsequent calls. No synchronization
* is performed, so there is a slight chance that multiple calls to this
* method will not all return the same set.
*/
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new AbstractSet<K>() {
public Iterator<K> iterator() {
return new Iterator<K>() {
private Iterator<Entry<K,V>> i = entrySet().iterator();
public boolean hasNext() {
return i.hasNext();
}
public K next() {
return i.next().getKey();
}
public void remove() {
i.remove();
}
};
}
public int size() {
return AbstractMap.this.size();
}
public boolean isEmpty() {
return AbstractMap.this.isEmpty();
}
public void clear() {
AbstractMap.this.clear();
}
public boolean contains(Object k) {
return AbstractMap.this.containsKey(k);
}
};
keySet = ks;
}
return ks;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns a collection that subclasses {@link
* AbstractCollection}. The subclass's iterator method returns a
* "wrapper object" over this map's {@code entrySet()} iterator.
* The {@code size} method delegates to this map's {@code size}
* method and the {@code contains} method delegates to this map's
* {@code containsValue} method.
*
* <p>The collection is created the first time this method is called, and
* returned in response to all subsequent calls. No synchronization is
* performed, so there is a slight chance that multiple calls to this
* method will not all return the same collection.
*/
public Collection<V> values() {
Collection<V> vals = values;
if (vals == null) {
vals = new AbstractCollection<V>() {
public Iterator<V> iterator() {
return new Iterator<V>() {
private Iterator<Entry<K,V>> i = entrySet().iterator();
public boolean hasNext() {
return i.hasNext();
}
public V next() {
return i.next().getValue();
}
public void remove() {
i.remove();
}
};
}
public int size() {
return AbstractMap.this.size();
}
public boolean isEmpty() {
return AbstractMap.this.isEmpty();
}
public void clear() {
AbstractMap.this.clear();
}
public boolean contains(Object v) {
return AbstractMap.this.containsValue(v);
}
};
values = vals;
}
return vals;
}
public abstract Set<Entry<K,V>> entrySet();
// Comparison and hashing
/**
* Compares the specified object with this map for equality. Returns
* {@code true} if the given object is also a map and the two maps
* represent the same mappings. More formally, two maps {@code m1} and
* {@code m2} represent the same mappings if
* {@code m1.entrySet().equals(m2.entrySet())}. This ensures that the
* {@code equals} method works properly across different implementations
* of the {@code Map} interface.
*
* @implSpec
* This implementation first checks if the specified object is this map;
* if so it returns {@code true}. Then, it checks if the specified
* object is a map whose size is identical to the size of this map; if
* not, it returns {@code false}. If so, it iterates over this map's
* {@code entrySet} collection, and checks that the specified map
* contains each mapping that this map contains. If the specified map
* fails to contain such a mapping, {@code false} is returned. If the
* iteration completes, {@code true} is returned.
*
* @param o object to be compared for equality with this map
* @return {@code true} if the specified object is equal to this map
*/
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map))
return false;
Map<?,?> m = (Map<?,?>) o;
if (m.size() != size())
return false;
try {
for (Entry<K, V> e : entrySet()) {
K key = e.getKey();
V value = e.getValue();
if (value == null) {
if (!(m.get(key) == null && m.containsKey(key)))
return false;
} else {
if (!value.equals(m.get(key)))
return false;
}
}
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
return true;
}
/**
* Returns the hash code value for this map. The hash code of a map is
* defined to be the sum of the hash codes of each entry in the map's
* {@code entrySet()} view. This ensures that {@code m1.equals(m2)}
* implies that {@code m1.hashCode()==m2.hashCode()} for any two maps
* {@code m1} and {@code m2}, as required by the general contract of
* {@link Object#hashCode}.
*
* @implSpec
* This implementation iterates over {@code entrySet()}, calling
* {@link Map.Entry#hashCode hashCode()} on each element (entry) in the
* set, and adding up the results.
*
* @return the hash code value for this map
* @see Map.Entry#hashCode()
* @see Object#equals(Object)
* @see Set#equals(Object)
*/
public int hashCode() {
int h = 0;
for (Entry<K, V> entry : entrySet())
h += entry.hashCode();
return h;
}
/**
* Returns a string representation of this map. The string representation
* consists of a list of key-value mappings in the order returned by the
* map's {@code entrySet} view's iterator, enclosed in braces
* ({@code "{}"}). Adjacent mappings are separated by the characters
* {@code ", "} (comma and space). Each key-value mapping is rendered as
* the key followed by an equals sign ({@code "="}) followed by the
* associated value. Keys and values are converted to strings as by
* {@link String#valueOf(Object)}.
*
* @return a string representation of this map
*/
public String toString() {
Iterator<Entry<K,V>> i = entrySet().iterator();
if (! i.hasNext())
return "{}";
StringBuilder sb = new StringBuilder();
sb.append('{');
for (;;) {
Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
sb.append(key == this ? "(this Map)" : key);
sb.append('=');
sb.append(value == this ? "(this Map)" : value);
if (! i.hasNext())
return sb.append('}').toString();
sb.append(',').append(' ');
}
}
/**
* Returns a shallow copy of this {@code AbstractMap} instance: the keys
* and values themselves are not cloned.
*
* @return a shallow copy of this map
*/
protected Object clone() throws CloneNotSupportedException {
AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
result.keySet = null;
result.values = null;
return result;
}
/**
* Utility method for SimpleEntry and SimpleImmutableEntry.
* Test for equality, checking for nulls.
*
* NB: Do not replace with Object.equals until JDK-8015417 is resolved.
*/
private static boolean eq(Object o1, Object o2) {
return o1 == null ? o2 == null : o1.equals(o2);
}
// Implementation Note: SimpleEntry and SimpleImmutableEntry
// are distinct unrelated classes, even though they share
// some code. Since you can't add or subtract final-ness
// of a field in a subclass, they can't share representations,
// and the amount of duplicated code is too small to warrant
// exposing a common abstract class.
/**
* An Entry maintaining a key and a value. The value may be
* changed using the {@code setValue} method. This class
* facilitates the process of building custom map
* implementations. For example, it may be convenient to return
* arrays of {@code SimpleEntry} instances in method
* {@code Map.entrySet().toArray}.
*
* @since 1.6
*/
public static class SimpleEntry<K,V>
implements Entry<K,V>, java.io.Serializable
{
private static final long serialVersionUID = -8499721149061103585L;
private final K key;
private V value;
/**
* Creates an entry representing a mapping from the specified
* key to the specified value.
*
* @param key the key represented by this entry
* @param value the value represented by this entry
*/
public SimpleEntry(K key, V value) {
this.key = key;
this.value = value;
}
/**
* Creates an entry representing the same mapping as the
* specified entry.
*
* @param entry the entry to copy
*/
public SimpleEntry(Entry<? extends K, ? extends V> entry) {
this.key = entry.getKey();
this.value = entry.getValue();
}
/**
* Returns the key corresponding to this entry.
*
* @return the key corresponding to this entry
*/
public K getKey() {
return key;
}
/**
* Returns the value corresponding to this entry.
*
* @return the value corresponding to this entry
*/
public V getValue() {
return value;
}
/**
* Replaces the value corresponding to this entry with the specified
* value.
*
* @param value new value to be stored in this entry
* @return the old value corresponding to the entry
*/
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
/**
* 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 represent the same mapping. More formally, two
* entries {@code e1} and {@code e2} represent the same mapping
* if<pre>
* (e1.getKey()==null ?
* e2.getKey()==null :
* e1.getKey().equals(e2.getKey()))
* &amp;&amp;
* (e1.getValue()==null ?
* e2.getValue()==null :
* e1.getValue().equals(e2.getValue()))</pre>
* This ensures that the {@code equals} method works properly across
* different implementations of the {@code Map.Entry} interface.
*
* @param o object to be compared for equality with this map entry
* @return {@code true} if the specified object is equal to this map
* entry
* @see #hashCode
*/
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
return eq(key, e.getKey()) && eq(value, e.getValue());
}
/**
* Returns the hash code value for this map entry. The hash code
* of a map entry {@code e} is defined to be: <pre>
* (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
* (e.getValue()==null ? 0 : e.getValue().hashCode())</pre>
* This ensures that {@code e1.equals(e2)} implies that
* {@code e1.hashCode()==e2.hashCode()} for any two Entries
* {@code e1} and {@code e2}, as required by the general
* contract of {@link Object#hashCode}.
*
* @return the hash code value for this map entry
* @see #equals
*/
public int hashCode() {
return (key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : 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
*/
public String toString() {
return key + "=" + value;
}
}
/**
* An Entry maintaining an immutable key and value. This class
* does not support method {@code setValue}. This class may be
* convenient in methods that return thread-safe snapshots of
* key-value mappings.
*
* @since 1.6
*/
public static class SimpleImmutableEntry<K,V>
implements Entry<K,V>, java.io.Serializable
{
private static final long serialVersionUID = 7138329143949025153L;
private final K key;
private final V value;
/**
* Creates an entry representing a mapping from the specified
* key to the specified value.
*
* @param key the key represented by this entry
* @param value the value represented by this entry
*/
public SimpleImmutableEntry(K key, V value) {
this.key = key;
this.value = value;
}
/**
* Creates an entry representing the same mapping as the
* specified entry.
*
* @param entry the entry to copy
*/
public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) {
this.key = entry.getKey();
this.value = entry.getValue();
}
/**
* Returns the key corresponding to this entry.
*
* @return the key corresponding to this entry
*/
public K getKey() {
return key;
}
/**
* Returns the value corresponding to this entry.
*
* @return the value corresponding to this entry
*/
public V getValue() {
return value;
}
/**
* Replaces the value corresponding to this entry with the specified
* value (optional operation). This implementation simply throws
* {@code UnsupportedOperationException}, as this class implements
* an <i>immutable</i> map entry.
*
* @param value new value to be stored in this entry
* @return (Does not return)
* @throws UnsupportedOperationException always
*/
public V setValue(V value) {
throw new UnsupportedOperationException();
}
/**
* 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 represent the same mapping. More formally, two
* entries {@code e1} and {@code e2} represent the same mapping
* if<pre>
* (e1.getKey()==null ?
* e2.getKey()==null :
* e1.getKey().equals(e2.getKey()))
* &amp;&amp;
* (e1.getValue()==null ?
* e2.getValue()==null :
* e1.getValue().equals(e2.getValue()))</pre>
* This ensures that the {@code equals} method works properly across
* different implementations of the {@code Map.Entry} interface.
*
* @param o object to be compared for equality with this map entry
* @return {@code true} if the specified object is equal to this map
* entry
* @see #hashCode
*/
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
return eq(key, e.getKey()) && eq(value, e.getValue());
}
/**
* Returns the hash code value for this map entry. The hash code
* of a map entry {@code e} is defined to be: <pre>
* (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
* (e.getValue()==null ? 0 : e.getValue().hashCode())</pre>
* This ensures that {@code e1.equals(e2)} implies that
* {@code e1.hashCode()==e2.hashCode()} for any two Entries
* {@code e1} and {@code e2}, as required by the general
* contract of {@link Object#hashCode}.
*
* @return the hash code value for this map entry
* @see #equals
*/
public int hashCode() {
return (key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : 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
*/
public String toString() {
return key + "=" + value;
}
}
}

View file

@ -0,0 +1,192 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
package java.util;
/**
* This class provides skeletal implementations of some {@link Queue}
* operations. The implementations in this class are appropriate when
* the base implementation does <em>not</em> allow {@code null}
* elements. Methods {@link #add add}, {@link #remove remove}, and
* {@link #element element} are based on {@link #offer offer}, {@link
* #poll poll}, and {@link #peek peek}, respectively, but throw
* exceptions instead of indicating failure via {@code false} or
* {@code null} returns.
*
* <p>A {@code Queue} implementation that extends this class must
* minimally define a method {@link Queue#offer} which does not permit
* insertion of {@code null} elements, along with methods {@link
* Queue#peek}, {@link Queue#poll}, {@link Collection#size}, and
* {@link Collection#iterator}. Typically, additional methods will be
* overridden as well. If these requirements cannot be met, consider
* instead subclassing {@link AbstractCollection}.
*
* <p>This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @since 1.5
* @author Doug Lea
* @param <E> the type of elements held in this queue
*/
public abstract class AbstractQueue<E>
extends AbstractCollection<E>
implements Queue<E> {
/**
* Constructor for use by subclasses.
*/
protected AbstractQueue() {
}
/**
* Inserts the specified element into this queue if it is possible to do so
* immediately without violating capacity restrictions, returning
* {@code true} upon success and throwing an {@code IllegalStateException}
* if no space is currently available.
*
* <p>This implementation returns {@code true} if {@code offer} succeeds,
* else throws an {@code IllegalStateException}.
*
* @param e the element to add
* @return {@code true} (as specified by {@link Collection#add})
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null and
* this queue does not permit null elements
* @throws IllegalArgumentException if some property of this element
* prevents it from being added to this queue
*/
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
/**
* Retrieves and removes the head of this queue. This method differs
* from {@link #poll poll} only in that it throws an exception if this
* queue is empty.
*
* <p>This implementation returns the result of {@code poll}
* unless the queue is empty.
*
* @return the head of this queue
* @throws NoSuchElementException if this queue is empty
*/
public E remove() {
E x = poll();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
/**
* Retrieves, but does not remove, the head of this queue. This method
* differs from {@link #peek peek} only in that it throws an exception if
* this queue is empty.
*
* <p>This implementation returns the result of {@code peek}
* unless the queue is empty.
*
* @return the head of this queue
* @throws NoSuchElementException if this queue is empty
*/
public E element() {
E x = peek();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
/**
* Removes all of the elements from this queue.
* The queue will be empty after this call returns.
*
* <p>This implementation repeatedly invokes {@link #poll poll} until it
* returns {@code null}.
*/
public void clear() {
while (poll() != null)
;
}
/**
* Adds all of the elements in the specified collection to this
* queue. Attempts to addAll of a queue to itself result in
* {@code IllegalArgumentException}. Further, the behavior of
* this operation is undefined if the specified collection is
* modified while the operation is in progress.
*
* <p>This implementation iterates over the specified collection,
* and adds each element returned by the iterator to this
* queue, in turn. A runtime exception encountered while
* trying to add an element (including, in particular, a
* {@code null} element) may result in only some of the elements
* having been successfully added when the associated exception is
* thrown.
*
* @param c collection containing elements to be added to this queue
* @return {@code true} if this queue changed as a result of the call
* @throws ClassCastException if the class of an element of the specified
* collection prevents it from being added to this queue
* @throws NullPointerException if the specified collection contains a
* null element and this queue does not permit null elements,
* or if the specified collection is null
* @throws IllegalArgumentException if some property of an element of the
* specified collection prevents it from being added to this
* queue, or if the specified collection is this queue
* @throws IllegalStateException if not all the elements can be added at
* this time due to insertion restrictions
* @see #add(Object)
*/
public boolean addAll(Collection<? extends E> c) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
}

View file

@ -0,0 +1,252 @@
/*
* Copyright (c) 1997, 2006, 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;
/**
* This class provides a skeletal implementation of the {@code List}
* interface to minimize the effort required to implement this interface
* backed by a "sequential access" data store (such as a linked list). For
* random access data (such as an array), {@code AbstractList} should be used
* in preference to this class.<p>
*
* This class is the opposite of the {@code AbstractList} class in the sense
* that it implements the "random access" methods ({@code get(int index)},
* {@code set(int index, E element)}, {@code add(int index, E element)} and
* {@code remove(int index)}) on top of the list's list iterator, instead of
* the other way around.<p>
*
* To implement a list the programmer needs only to extend this class and
* provide implementations for the {@code listIterator} and {@code size}
* methods. For an unmodifiable list, the programmer need only implement the
* list iterator's {@code hasNext}, {@code next}, {@code hasPrevious},
* {@code previous} and {@code index} methods.<p>
*
* For a modifiable list the programmer should additionally implement the list
* iterator's {@code set} method. For a variable-size list the programmer
* should additionally implement the list iterator's {@code remove} and
* {@code add} methods.<p>
*
* The programmer should generally provide a void (no argument) and collection
* constructor, as per the recommendation in the {@code Collection} interface
* specification.<p>
*
* This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch
* @author Neal Gafter
* @see Collection
* @see List
* @see AbstractList
* @see AbstractCollection
* @since 1.2
*/
public abstract class AbstractSequentialList<E> extends AbstractList<E> {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected AbstractSequentialList() {
}
/**
* Returns the element at the specified position in this list.
*
* <p>This implementation first gets a list iterator pointing to the
* indexed element (with {@code listIterator(index)}). Then, it gets
* the element using {@code ListIterator.next} and returns it.
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
try {
return listIterator(index).next();
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
/**
* Replaces the element at the specified position in this list with the
* specified element (optional operation).
*
* <p>This implementation first gets a list iterator pointing to the
* indexed element (with {@code listIterator(index)}). Then, it gets
* the current element using {@code ListIterator.next} and replaces it
* with {@code ListIterator.set}.
*
* <p>Note that this implementation will throw an
* {@code UnsupportedOperationException} if the list iterator does not
* implement the {@code set} operation.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
try {
ListIterator<E> e = listIterator(index);
E oldVal = e.next();
e.set(element);
return oldVal;
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
/**
* Inserts the specified element at the specified position in this list
* (optional operation). Shifts the element currently at that position
* (if any) and any subsequent elements to the right (adds one to their
* indices).
*
* <p>This implementation first gets a list iterator pointing to the
* indexed element (with {@code listIterator(index)}). Then, it
* inserts the specified element with {@code ListIterator.add}.
*
* <p>Note that this implementation will throw an
* {@code UnsupportedOperationException} if the list iterator does not
* implement the {@code add} operation.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
try {
listIterator(index).add(element);
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
/**
* Removes the element at the specified position in this list (optional
* operation). Shifts any subsequent elements to the left (subtracts one
* from their indices). Returns the element that was removed from the
* list.
*
* <p>This implementation first gets a list iterator pointing to the
* indexed element (with {@code listIterator(index)}). Then, it removes
* the element with {@code ListIterator.remove}.
*
* <p>Note that this implementation will throw an
* {@code UnsupportedOperationException} if the list iterator does not
* implement the {@code remove} operation.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E remove(int index) {
try {
ListIterator<E> e = listIterator(index);
E outCast = e.next();
e.remove();
return outCast;
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
// Bulk Operations
/**
* Inserts all of the elements in the specified collection into this
* list at the specified position (optional operation). Shifts the
* element currently at that position (if any) and any subsequent
* elements to the right (increases their indices). The new elements
* will appear in this list in the order that they are returned by the
* specified collection's iterator. The behavior of this operation is
* undefined if the specified collection is modified while the
* operation is in progress. (Note that this will occur if the specified
* collection is this list, and it's nonempty.)
*
* <p>This implementation gets an iterator over the specified collection and
* a list iterator over this list pointing to the indexed element (with
* {@code listIterator(index)}). Then, it iterates over the specified
* collection, inserting the elements obtained from the iterator into this
* list, one at a time, using {@code ListIterator.add} followed by
* {@code ListIterator.next} (to skip over the added element).
*
* <p>Note that this implementation will throw an
* {@code UnsupportedOperationException} if the list iterator returned by
* the {@code listIterator} method does not implement the {@code add}
* operation.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public boolean addAll(int index, Collection<? extends E> c) {
try {
boolean modified = false;
ListIterator<E> e1 = listIterator(index);
for (E e : c) {
e1.add(e);
modified = true;
}
return modified;
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
// Iterators
/**
* Returns an iterator over the elements in this list (in proper
* sequence).<p>
*
* This implementation merely returns a list iterator over the list.
*
* @return an iterator over the elements in this list (in proper sequence)
*/
public Iterator<E> iterator() {
return listIterator();
}
/**
* Returns a list iterator over the elements in this list (in proper
* sequence).
*
* @param index index of first element to be returned from the list
* iterator (by a call to the {@code next} method)
* @return a list iterator over the elements in this list (in proper
* sequence)
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public abstract ListIterator<E> listIterator(int index);
}

View file

@ -0,0 +1,186 @@
/*
* Copyright (c) 1997, 2013, 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;
/**
* This class provides a skeletal implementation of the {@code Set}
* interface to minimize the effort required to implement this
* interface. <p>
*
* The process of implementing a set by extending this class is identical
* to that of implementing a Collection by extending AbstractCollection,
* except that all of the methods and constructors in subclasses of this
* class must obey the additional constraints imposed by the {@code Set}
* interface (for instance, the add method must not permit addition of
* multiple instances of an object to a set).<p>
*
* Note that this class does not override any of the implementations from
* the {@code AbstractCollection} class. It merely adds implementations
* for {@code equals} and {@code hashCode}.<p>
*
* This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <E> the type of elements maintained by this set
*
* @author Josh Bloch
* @author Neal Gafter
* @see Collection
* @see AbstractCollection
* @see Set
* @since 1.2
*/
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected AbstractSet() {
}
// Comparison and hashing
/**
* Compares the specified object with this set for equality. Returns
* {@code true} if the given object is also a set, the two sets have
* the same size, and every member of the given set is contained in
* this set. This ensures that the {@code equals} method works
* properly across different implementations of the {@code Set}
* interface.<p>
*
* This implementation first checks if the specified object is this
* set; if so it returns {@code true}. Then, it checks if the
* specified object is a set whose size is identical to the size of
* this set; if not, it returns false. If so, it returns
* {@code containsAll((Collection) o)}.
*
* @param o object to be compared for equality with this set
* @return {@code true} if the specified object is equal to this set
*/
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Collection<?> c = (Collection<?>) o;
if (c.size() != size())
return false;
try {
return containsAll(c);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
}
/**
* Returns the hash code value for this set. The hash code of a set is
* defined to be the sum of the hash codes of the elements in the set,
* where the hash code of a {@code null} element is defined to be zero.
* This ensures that {@code s1.equals(s2)} implies that
* {@code s1.hashCode()==s2.hashCode()} for any two sets {@code s1}
* and {@code s2}, as required by the general contract of
* {@link Object#hashCode}.
*
* <p>This implementation iterates over the set, calling the
* {@code hashCode} method on each element in the set, and adding up
* the results.
*
* @return the hash code value for this set
* @see Object#equals(Object)
* @see Set#equals(Object)
*/
public int hashCode() {
int h = 0;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
if (obj != null)
h += obj.hashCode();
}
return h;
}
/**
* Removes from this set all of its elements that are contained in the
* specified collection (optional operation). If the specified
* collection is also a set, this operation effectively modifies this
* set so that its value is the <i>asymmetric set difference</i> of
* the two sets.
*
* <p>This implementation determines which is the smaller of this set
* and the specified collection, by invoking the {@code size}
* method on each. If this set has fewer elements, then the
* implementation iterates over this set, checking each element
* returned by the iterator in turn to see if it is contained in
* the specified collection. If it is so contained, it is removed
* from this set with the iterator's {@code remove} method. If
* the specified collection has fewer elements, then the
* implementation iterates over the specified collection, removing
* from this set each element returned by the iterator, using this
* set's {@code remove} method.
*
* <p>Note that this implementation will throw an
* {@code UnsupportedOperationException} if the iterator returned by the
* {@code iterator} method does not implement the {@code remove} method.
*
* @param c collection containing elements to be removed from this set
* @return {@code true} if this set changed as a result of the call
* @throws UnsupportedOperationException if the {@code removeAll} operation
* is not supported by this set
* @throws ClassCastException if the class of an element of this set
* is incompatible with the specified collection
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this set contains a null element and the
* specified collection does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #remove(Object)
* @see #contains(Object)
*/
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
if (size() > c.size()) {
for (Object e : c)
modified |= remove(e);
} else {
for (Iterator<?> i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
}
return modified;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,706 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
package java.util;
import java.util.concurrent.CountedCompleter;
import java.util.concurrent.ForkJoinPool;
import java.util.function.BinaryOperator;
import java.util.function.DoubleBinaryOperator;
import java.util.function.IntBinaryOperator;
import java.util.function.LongBinaryOperator;
/**
* ForkJoin tasks to perform Arrays.parallelPrefix operations.
*
* @author Doug Lea
* @since 1.8
*/
class ArrayPrefixHelpers {
private ArrayPrefixHelpers() {} // non-instantiable
/*
* Parallel prefix (aka cumulate, scan) task classes
* are based loosely on Guy Blelloch's original
* algorithm (http://www.cs.cmu.edu/~scandal/alg/scan.html):
* Keep dividing by two to threshold segment size, and then:
* Pass 1: Create tree of partial sums for each segment
* Pass 2: For each segment, cumulate with offset of left sibling
*
* This version improves performance within FJ framework mainly by
* allowing the second pass of ready left-hand sides to proceed
* even if some right-hand side first passes are still executing.
* It also combines first and second pass for leftmost segment,
* and skips the first pass for rightmost segment (whose result is
* not needed for second pass). It similarly manages to avoid
* requiring that users supply an identity basis for accumulations
* by tracking those segments/subtasks for which the first
* existing element is used as base.
*
* Managing this relies on ORing some bits in the pendingCount for
* phases/states: CUMULATE, SUMMED, and FINISHED. CUMULATE is the
* main phase bit. When false, segments compute only their sum.
* When true, they cumulate array elements. CUMULATE is set at
* root at beginning of second pass and then propagated down. But
* it may also be set earlier for subtrees with lo==0 (the left
* spine of tree). SUMMED is a one bit join count. For leafs, it
* is set when summed. For internal nodes, it becomes true when
* one child is summed. When the second child finishes summing,
* we then moves up tree to trigger the cumulate phase. FINISHED
* is also a one bit join count. For leafs, it is set when
* cumulated. For internal nodes, it becomes true when one child
* is cumulated. When the second child finishes cumulating, it
* then moves up tree, completing at the root.
*
* To better exploit locality and reduce overhead, the compute
* method loops starting with the current task, moving if possible
* to one of its subtasks rather than forking.
*
* As usual for this sort of utility, there are 4 versions, that
* are simple copy/paste/adapt variants of each other. (The
* double and int versions differ from long version solely by
* replacing "long" (with case-matching)).
*/
// see above
static final int CUMULATE = 1;
static final int SUMMED = 2;
static final int FINISHED = 4;
/** The smallest subtask array partition size to use as threshold */
static final int MIN_PARTITION = 16;
static final class CumulateTask<T> extends CountedCompleter<Void> {
final T[] array;
final BinaryOperator<T> function;
CumulateTask<T> left, right;
T in, out;
final int lo, hi, origin, fence, threshold;
/** Root task constructor */
public CumulateTask(CumulateTask<T> parent,
BinaryOperator<T> function,
T[] array, int lo, int hi) {
super(parent);
this.function = function; this.array = array;
this.lo = this.origin = lo; this.hi = this.fence = hi;
int p;
this.threshold =
(p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
<= MIN_PARTITION ? MIN_PARTITION : p;
}
/** Subtask constructor */
CumulateTask(CumulateTask<T> parent, BinaryOperator<T> function,
T[] array, int origin, int fence, int threshold,
int lo, int hi) {
super(parent);
this.function = function; this.array = array;
this.origin = origin; this.fence = fence;
this.threshold = threshold;
this.lo = lo; this.hi = hi;
}
public final void compute() {
final BinaryOperator<T> fn;
final T[] a;
if ((fn = this.function) == null || (a = this.array) == null)
throw new NullPointerException(); // hoist checks
int th = threshold, org = origin, fnc = fence, l, h;
CumulateTask<T> t = this;
outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
if (h - l > th) {
CumulateTask<T> lt = t.left, rt = t.right, f;
if (lt == null) { // first pass
int mid = (l + h) >>> 1;
f = rt = t.right =
new CumulateTask<T>(t, fn, a, org, fnc, th, mid, h);
t = lt = t.left =
new CumulateTask<T>(t, fn, a, org, fnc, th, l, mid);
}
else { // possibly refork
T pin = t.in;
lt.in = pin;
f = t = null;
if (rt != null) {
T lout = lt.out;
rt.in = (l == org ? lout :
fn.apply(pin, lout));
for (int c;;) {
if (((c = rt.getPendingCount()) & CUMULATE) != 0)
break;
if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
t = rt;
break;
}
}
}
for (int c;;) {
if (((c = lt.getPendingCount()) & CUMULATE) != 0)
break;
if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
if (t != null)
f = t;
t = lt;
break;
}
}
if (t == null)
break;
}
if (f != null)
f.fork();
}
else {
int state; // Transition to sum, cumulate, or both
for (int b;;) {
if (((b = t.getPendingCount()) & FINISHED) != 0)
break outer; // already done
state = ((b & CUMULATE) != 0 ? FINISHED :
(l > org) ? SUMMED : (SUMMED|FINISHED));
if (t.compareAndSetPendingCount(b, b|state))
break;
}
T sum;
if (state != SUMMED) {
int first;
if (l == org) { // leftmost; no in
sum = a[org];
first = org + 1;
}
else {
sum = t.in;
first = l;
}
for (int i = first; i < h; ++i) // cumulate
a[i] = sum = fn.apply(sum, a[i]);
}
else if (h < fnc) { // skip rightmost
sum = a[l];
for (int i = l + 1; i < h; ++i) // sum only
sum = fn.apply(sum, a[i]);
}
else
sum = t.in;
t.out = sum;
for (CumulateTask<T> par;;) { // propagate
@SuppressWarnings("unchecked") CumulateTask<T> partmp
= (CumulateTask<T>)t.getCompleter();
if ((par = partmp) == null) {
if ((state & FINISHED) != 0) // enable join
t.quietlyComplete();
break outer;
}
int b = par.getPendingCount();
if ((b & state & FINISHED) != 0)
t = par; // both done
else if ((b & state & SUMMED) != 0) { // both summed
int nextState; CumulateTask<T> lt, rt;
if ((lt = par.left) != null &&
(rt = par.right) != null) {
T lout = lt.out;
par.out = (rt.hi == fnc ? lout :
fn.apply(lout, rt.out));
}
int refork = (((b & CUMULATE) == 0 &&
par.lo == org) ? CUMULATE : 0);
if ((nextState = b|state|refork) == b ||
par.compareAndSetPendingCount(b, nextState)) {
state = SUMMED; // drop finished
t = par;
if (refork != 0)
par.fork();
}
}
else if (par.compareAndSetPendingCount(b, b|state))
break outer; // sib not ready
}
}
}
}
private static final long serialVersionUID = 5293554502939613543L;
}
static final class LongCumulateTask extends CountedCompleter<Void> {
final long[] array;
final LongBinaryOperator function;
LongCumulateTask left, right;
long in, out;
final int lo, hi, origin, fence, threshold;
/** Root task constructor */
public LongCumulateTask(LongCumulateTask parent,
LongBinaryOperator function,
long[] array, int lo, int hi) {
super(parent);
this.function = function; this.array = array;
this.lo = this.origin = lo; this.hi = this.fence = hi;
int p;
this.threshold =
(p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
<= MIN_PARTITION ? MIN_PARTITION : p;
}
/** Subtask constructor */
LongCumulateTask(LongCumulateTask parent, LongBinaryOperator function,
long[] array, int origin, int fence, int threshold,
int lo, int hi) {
super(parent);
this.function = function; this.array = array;
this.origin = origin; this.fence = fence;
this.threshold = threshold;
this.lo = lo; this.hi = hi;
}
public final void compute() {
final LongBinaryOperator fn;
final long[] a;
if ((fn = this.function) == null || (a = this.array) == null)
throw new NullPointerException(); // hoist checks
int th = threshold, org = origin, fnc = fence, l, h;
LongCumulateTask t = this;
outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
if (h - l > th) {
LongCumulateTask lt = t.left, rt = t.right, f;
if (lt == null) { // first pass
int mid = (l + h) >>> 1;
f = rt = t.right =
new LongCumulateTask(t, fn, a, org, fnc, th, mid, h);
t = lt = t.left =
new LongCumulateTask(t, fn, a, org, fnc, th, l, mid);
}
else { // possibly refork
long pin = t.in;
lt.in = pin;
f = t = null;
if (rt != null) {
long lout = lt.out;
rt.in = (l == org ? lout :
fn.applyAsLong(pin, lout));
for (int c;;) {
if (((c = rt.getPendingCount()) & CUMULATE) != 0)
break;
if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
t = rt;
break;
}
}
}
for (int c;;) {
if (((c = lt.getPendingCount()) & CUMULATE) != 0)
break;
if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
if (t != null)
f = t;
t = lt;
break;
}
}
if (t == null)
break;
}
if (f != null)
f.fork();
}
else {
int state; // Transition to sum, cumulate, or both
for (int b;;) {
if (((b = t.getPendingCount()) & FINISHED) != 0)
break outer; // already done
state = ((b & CUMULATE) != 0 ? FINISHED :
(l > org) ? SUMMED : (SUMMED|FINISHED));
if (t.compareAndSetPendingCount(b, b|state))
break;
}
long sum;
if (state != SUMMED) {
int first;
if (l == org) { // leftmost; no in
sum = a[org];
first = org + 1;
}
else {
sum = t.in;
first = l;
}
for (int i = first; i < h; ++i) // cumulate
a[i] = sum = fn.applyAsLong(sum, a[i]);
}
else if (h < fnc) { // skip rightmost
sum = a[l];
for (int i = l + 1; i < h; ++i) // sum only
sum = fn.applyAsLong(sum, a[i]);
}
else
sum = t.in;
t.out = sum;
for (LongCumulateTask par;;) { // propagate
if ((par = (LongCumulateTask)t.getCompleter()) == null) {
if ((state & FINISHED) != 0) // enable join
t.quietlyComplete();
break outer;
}
int b = par.getPendingCount();
if ((b & state & FINISHED) != 0)
t = par; // both done
else if ((b & state & SUMMED) != 0) { // both summed
int nextState; LongCumulateTask lt, rt;
if ((lt = par.left) != null &&
(rt = par.right) != null) {
long lout = lt.out;
par.out = (rt.hi == fnc ? lout :
fn.applyAsLong(lout, rt.out));
}
int refork = (((b & CUMULATE) == 0 &&
par.lo == org) ? CUMULATE : 0);
if ((nextState = b|state|refork) == b ||
par.compareAndSetPendingCount(b, nextState)) {
state = SUMMED; // drop finished
t = par;
if (refork != 0)
par.fork();
}
}
else if (par.compareAndSetPendingCount(b, b|state))
break outer; // sib not ready
}
}
}
}
private static final long serialVersionUID = -5074099945909284273L;
}
static final class DoubleCumulateTask extends CountedCompleter<Void> {
final double[] array;
final DoubleBinaryOperator function;
DoubleCumulateTask left, right;
double in, out;
final int lo, hi, origin, fence, threshold;
/** Root task constructor */
public DoubleCumulateTask(DoubleCumulateTask parent,
DoubleBinaryOperator function,
double[] array, int lo, int hi) {
super(parent);
this.function = function; this.array = array;
this.lo = this.origin = lo; this.hi = this.fence = hi;
int p;
this.threshold =
(p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
<= MIN_PARTITION ? MIN_PARTITION : p;
}
/** Subtask constructor */
DoubleCumulateTask(DoubleCumulateTask parent, DoubleBinaryOperator function,
double[] array, int origin, int fence, int threshold,
int lo, int hi) {
super(parent);
this.function = function; this.array = array;
this.origin = origin; this.fence = fence;
this.threshold = threshold;
this.lo = lo; this.hi = hi;
}
public final void compute() {
final DoubleBinaryOperator fn;
final double[] a;
if ((fn = this.function) == null || (a = this.array) == null)
throw new NullPointerException(); // hoist checks
int th = threshold, org = origin, fnc = fence, l, h;
DoubleCumulateTask t = this;
outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
if (h - l > th) {
DoubleCumulateTask lt = t.left, rt = t.right, f;
if (lt == null) { // first pass
int mid = (l + h) >>> 1;
f = rt = t.right =
new DoubleCumulateTask(t, fn, a, org, fnc, th, mid, h);
t = lt = t.left =
new DoubleCumulateTask(t, fn, a, org, fnc, th, l, mid);
}
else { // possibly refork
double pin = t.in;
lt.in = pin;
f = t = null;
if (rt != null) {
double lout = lt.out;
rt.in = (l == org ? lout :
fn.applyAsDouble(pin, lout));
for (int c;;) {
if (((c = rt.getPendingCount()) & CUMULATE) != 0)
break;
if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
t = rt;
break;
}
}
}
for (int c;;) {
if (((c = lt.getPendingCount()) & CUMULATE) != 0)
break;
if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
if (t != null)
f = t;
t = lt;
break;
}
}
if (t == null)
break;
}
if (f != null)
f.fork();
}
else {
int state; // Transition to sum, cumulate, or both
for (int b;;) {
if (((b = t.getPendingCount()) & FINISHED) != 0)
break outer; // already done
state = ((b & CUMULATE) != 0 ? FINISHED :
(l > org) ? SUMMED : (SUMMED|FINISHED));
if (t.compareAndSetPendingCount(b, b|state))
break;
}
double sum;
if (state != SUMMED) {
int first;
if (l == org) { // leftmost; no in
sum = a[org];
first = org + 1;
}
else {
sum = t.in;
first = l;
}
for (int i = first; i < h; ++i) // cumulate
a[i] = sum = fn.applyAsDouble(sum, a[i]);
}
else if (h < fnc) { // skip rightmost
sum = a[l];
for (int i = l + 1; i < h; ++i) // sum only
sum = fn.applyAsDouble(sum, a[i]);
}
else
sum = t.in;
t.out = sum;
for (DoubleCumulateTask par;;) { // propagate
if ((par = (DoubleCumulateTask)t.getCompleter()) == null) {
if ((state & FINISHED) != 0) // enable join
t.quietlyComplete();
break outer;
}
int b = par.getPendingCount();
if ((b & state & FINISHED) != 0)
t = par; // both done
else if ((b & state & SUMMED) != 0) { // both summed
int nextState; DoubleCumulateTask lt, rt;
if ((lt = par.left) != null &&
(rt = par.right) != null) {
double lout = lt.out;
par.out = (rt.hi == fnc ? lout :
fn.applyAsDouble(lout, rt.out));
}
int refork = (((b & CUMULATE) == 0 &&
par.lo == org) ? CUMULATE : 0);
if ((nextState = b|state|refork) == b ||
par.compareAndSetPendingCount(b, nextState)) {
state = SUMMED; // drop finished
t = par;
if (refork != 0)
par.fork();
}
}
else if (par.compareAndSetPendingCount(b, b|state))
break outer; // sib not ready
}
}
}
}
private static final long serialVersionUID = -586947823794232033L;
}
static final class IntCumulateTask extends CountedCompleter<Void> {
final int[] array;
final IntBinaryOperator function;
IntCumulateTask left, right;
int in, out;
final int lo, hi, origin, fence, threshold;
/** Root task constructor */
public IntCumulateTask(IntCumulateTask parent,
IntBinaryOperator function,
int[] array, int lo, int hi) {
super(parent);
this.function = function; this.array = array;
this.lo = this.origin = lo; this.hi = this.fence = hi;
int p;
this.threshold =
(p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
<= MIN_PARTITION ? MIN_PARTITION : p;
}
/** Subtask constructor */
IntCumulateTask(IntCumulateTask parent, IntBinaryOperator function,
int[] array, int origin, int fence, int threshold,
int lo, int hi) {
super(parent);
this.function = function; this.array = array;
this.origin = origin; this.fence = fence;
this.threshold = threshold;
this.lo = lo; this.hi = hi;
}
public final void compute() {
final IntBinaryOperator fn;
final int[] a;
if ((fn = this.function) == null || (a = this.array) == null)
throw new NullPointerException(); // hoist checks
int th = threshold, org = origin, fnc = fence, l, h;
IntCumulateTask t = this;
outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
if (h - l > th) {
IntCumulateTask lt = t.left, rt = t.right, f;
if (lt == null) { // first pass
int mid = (l + h) >>> 1;
f = rt = t.right =
new IntCumulateTask(t, fn, a, org, fnc, th, mid, h);
t = lt = t.left =
new IntCumulateTask(t, fn, a, org, fnc, th, l, mid);
}
else { // possibly refork
int pin = t.in;
lt.in = pin;
f = t = null;
if (rt != null) {
int lout = lt.out;
rt.in = (l == org ? lout :
fn.applyAsInt(pin, lout));
for (int c;;) {
if (((c = rt.getPendingCount()) & CUMULATE) != 0)
break;
if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
t = rt;
break;
}
}
}
for (int c;;) {
if (((c = lt.getPendingCount()) & CUMULATE) != 0)
break;
if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
if (t != null)
f = t;
t = lt;
break;
}
}
if (t == null)
break;
}
if (f != null)
f.fork();
}
else {
int state; // Transition to sum, cumulate, or both
for (int b;;) {
if (((b = t.getPendingCount()) & FINISHED) != 0)
break outer; // already done
state = ((b & CUMULATE) != 0 ? FINISHED :
(l > org) ? SUMMED : (SUMMED|FINISHED));
if (t.compareAndSetPendingCount(b, b|state))
break;
}
int sum;
if (state != SUMMED) {
int first;
if (l == org) { // leftmost; no in
sum = a[org];
first = org + 1;
}
else {
sum = t.in;
first = l;
}
for (int i = first; i < h; ++i) // cumulate
a[i] = sum = fn.applyAsInt(sum, a[i]);
}
else if (h < fnc) { // skip rightmost
sum = a[l];
for (int i = l + 1; i < h; ++i) // sum only
sum = fn.applyAsInt(sum, a[i]);
}
else
sum = t.in;
t.out = sum;
for (IntCumulateTask par;;) { // propagate
if ((par = (IntCumulateTask)t.getCompleter()) == null) {
if ((state & FINISHED) != 0) // enable join
t.quietlyComplete();
break outer;
}
int b = par.getPendingCount();
if ((b & state & FINISHED) != 0)
t = par; // both done
else if ((b & state & SUMMED) != 0) { // both summed
int nextState; IntCumulateTask lt, rt;
if ((lt = par.left) != null &&
(rt = par.right) != null) {
int lout = lt.out;
par.out = (rt.hi == fnc ? lout :
fn.applyAsInt(lout, rt.out));
}
int refork = (((b & CUMULATE) == 0 &&
par.lo == org) ? CUMULATE : 0);
if ((nextState = b|state|refork) == b ||
par.compareAndSetPendingCount(b, nextState)) {
state = SUMMED; // drop finished
t = par;
if (refork != 0)
par.fork();
}
}
else if (par.compareAndSetPendingCount(b, b|state))
break outer; // sib not ready
}
}
}
}
private static final long serialVersionUID = 3731755594596840961L;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,545 @@
/*
* 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;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.Unsafe;
/**
* Utility methods to find a mismatch between two primitive arrays.
*
* <p>Array equality and lexicographical comparison can be built on top of
* array mismatch functionality.
*
* <p>The mismatch method implementation, {@link #vectorizedMismatch}, leverages
* vector-based techniques to access and compare the contents of two arrays.
* The Java implementation uses {@code Unsafe.getLongUnaligned} to access the
* content of an array, thus access is supported on platforms that do not
* support unaligned access. For a byte[] array, 8 bytes (64 bits) can be
* accessed and compared as a unit rather than individually, which increases
* the performance when the method is compiled by the HotSpot VM. On supported
* platforms the mismatch implementation is intrinsified to leverage SIMD
* instructions. So for a byte[] array, 16 bytes (128 bits), 32 bytes
* (256 bits), and perhaps in the future even 64 bytes (512 bits), platform
* permitting, can be accessed and compared as a unit, which further increases
* the performance over the Java implementation.
*
* <p>None of the mismatch methods perform array bounds checks. It is the
* responsibility of the caller (direct or otherwise) to perform such checks
* before calling this method.
*/
class ArraysSupport {
static final Unsafe U = Unsafe.getUnsafe();
private static final boolean BIG_ENDIAN = U.isBigEndian();
private static final int LOG2_ARRAY_BOOLEAN_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE);
private static final int LOG2_ARRAY_BYTE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BYTE_INDEX_SCALE);
private static final int LOG2_ARRAY_CHAR_INDEX_SCALE = exactLog2(Unsafe.ARRAY_CHAR_INDEX_SCALE);
private static final int LOG2_ARRAY_SHORT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_SHORT_INDEX_SCALE);
private static final int LOG2_ARRAY_INT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_INT_INDEX_SCALE);
private static final int LOG2_ARRAY_LONG_INDEX_SCALE = exactLog2(Unsafe.ARRAY_LONG_INDEX_SCALE);
private static final int LOG2_ARRAY_FLOAT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_FLOAT_INDEX_SCALE);
private static final int LOG2_ARRAY_DOUBLE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
private static final int LOG2_BYTE_BIT_SIZE = exactLog2(Byte.SIZE);
private static int exactLog2(int scale) {
if ((scale & (scale - 1)) != 0)
throw new Error("data type scale not a power of two");
return Integer.numberOfTrailingZeros(scale);
}
private ArraysSupport() {}
/**
* Find the relative index of the first mismatching pair of elements in two
* primitive arrays of the same component type. Pairs of elements will be
* tested in order relative to given offsets into both arrays.
*
* <p>This method does not perform type checks or bounds checks. It is the
* responsibility of the caller to perform such checks before calling this
* method.
*
* <p>The given offsets, in bytes, need not be aligned according to the
* given log<sub>2</sub> size the array elements. More specifically, an
* offset modulus the size need not be zero.
*
* @param a the first array to be tested for mismatch, or {@code null} for
* direct memory access
* @param aOffset the relative offset, in bytes, from the base address of
* the first array to test from, otherwise if the first array is
* {@code null}, an absolute address pointing to the first element to test.
* @param b the second array to be tested for mismatch, or {@code null} for
* direct memory access
* @param bOffset the relative offset, in bytes, from the base address of
* the second array to test from, otherwise if the second array is
* {@code null}, an absolute address pointing to the first element to test.
* @param length the number of array elements to test
* @param log2ArrayIndexScale log<sub>2</sub> of the array index scale, that
* corresponds to the size, in bytes, of an array element.
* @return if a mismatch is found a relative index, between 0 (inclusive)
* and {@code length} (exclusive), of the first mismatching pair of elements
* in the two arrays. Otherwise, if a mismatch is not found the bitwise
* compliment of the number of remaining pairs of elements to be checked in
* the tail of the two arrays.
*/
@HotSpotIntrinsicCandidate
static int vectorizedMismatch(Object a, long aOffset,
Object b, long bOffset,
int length,
int log2ArrayIndexScale) {
// assert a.getClass().isArray();
// assert b.getClass().isArray();
// assert 0 <= length <= sizeOf(a)
// assert 0 <= length <= sizeOf(b)
// assert 0 <= log2ArrayIndexScale <= 3
int log2ValuesPerWidth = LOG2_ARRAY_LONG_INDEX_SCALE - log2ArrayIndexScale;
int wi = 0;
for (; wi < length >> log2ValuesPerWidth; wi++) {
long bi = ((long) wi) << LOG2_ARRAY_LONG_INDEX_SCALE;
long av = U.getLongUnaligned(a, aOffset + bi);
long bv = U.getLongUnaligned(b, bOffset + bi);
if (av != bv) {
long x = av ^ bv;
int o = BIG_ENDIAN
? Long.numberOfLeadingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale)
: Long.numberOfTrailingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale);
return (wi << log2ValuesPerWidth) + o;
}
}
// Calculate the tail of remaining elements to check
int tail = length - (wi << log2ValuesPerWidth);
if (log2ArrayIndexScale < LOG2_ARRAY_INT_INDEX_SCALE) {
int wordTail = 1 << (LOG2_ARRAY_INT_INDEX_SCALE - log2ArrayIndexScale);
// Handle 4 bytes or 2 chars in the tail using int width
if (tail >= wordTail) {
long bi = ((long) wi) << LOG2_ARRAY_LONG_INDEX_SCALE;
int av = U.getIntUnaligned(a, aOffset + bi);
int bv = U.getIntUnaligned(b, bOffset + bi);
if (av != bv) {
int x = av ^ bv;
int o = BIG_ENDIAN
? Integer.numberOfLeadingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale)
: Integer.numberOfTrailingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale);
return (wi << log2ValuesPerWidth) + o;
}
tail -= wordTail;
}
return ~tail;
}
else {
return ~tail;
}
}
// Booleans
// Each boolean element takes up one byte
static int mismatch(boolean[] a,
boolean[] b,
int length) {
int i = 0;
if (length > 7) {
i = vectorizedMismatch(
a, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
b, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
length, LOG2_ARRAY_BOOLEAN_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[i] != b[i])
return i;
}
return -1;
}
static int mismatch(boolean[] a, int aFromIndex,
boolean[] b, int bFromIndex,
int length) {
int i = 0;
if (length > 7) {
int aOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + aFromIndex;
int bOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + bFromIndex;
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_BOOLEAN_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[aFromIndex + i] != b[bFromIndex + i])
return i;
}
return -1;
}
// Bytes
/**
* Find the index of a mismatch between two arrays.
*
* <p>This method does not perform bounds checks. It is the responsibility
* of the caller to perform such bounds checks before calling this method.
*
* @param a the first array to be tested for a mismatch
* @param b the second array to be tested for a mismatch
* @param length the number of bytes from each array to check
* @return the index of a mismatch between the two arrays, otherwise -1 if
* no mismatch. The index will be within the range of (inclusive) 0 to
* (exclusive) the smaller of the two array lengths.
*/
static int mismatch(byte[] a,
byte[] b,
int length) {
// ISSUE: defer to index receiving methods if performance is good
// assert length <= a.length
// assert length <= b.length
int i = 0;
if (length > 7) {
i = vectorizedMismatch(
a, Unsafe.ARRAY_BYTE_BASE_OFFSET,
b, Unsafe.ARRAY_BYTE_BASE_OFFSET,
length, LOG2_ARRAY_BYTE_INDEX_SCALE);
if (i >= 0)
return i;
// Align to tail
i = length - ~i;
// assert i >= 0 && i <= 7;
}
// Tail < 8 bytes
for (; i < length; i++) {
if (a[i] != b[i])
return i;
}
return -1;
}
/**
* Find the relative index of a mismatch between two arrays starting from
* given indexes.
*
* <p>This method does not perform bounds checks. It is the responsibility
* of the caller to perform such bounds checks before calling this method.
*
* @param a the first array to be tested for a mismatch
* @param aFromIndex the index of the first element (inclusive) in the first
* array to be compared
* @param b the second array to be tested for a mismatch
* @param bFromIndex the index of the first element (inclusive) in the
* second array to be compared
* @param length the number of bytes from each array to check
* @return the relative index of a mismatch between the two arrays,
* otherwise -1 if no mismatch. The index will be within the range of
* (inclusive) 0 to (exclusive) the smaller of the two array bounds.
*/
static int mismatch(byte[] a, int aFromIndex,
byte[] b, int bFromIndex,
int length) {
// assert 0 <= aFromIndex < a.length
// assert 0 <= aFromIndex + length <= a.length
// assert 0 <= bFromIndex < b.length
// assert 0 <= bFromIndex + length <= b.length
// assert length >= 0
int i = 0;
if (length > 7) {
int aOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + aFromIndex;
int bOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + bFromIndex;
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_BYTE_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[aFromIndex + i] != b[bFromIndex + i])
return i;
}
return -1;
}
// Chars
static int mismatch(char[] a,
char[] b,
int length) {
int i = 0;
if (length > 3) {
i = vectorizedMismatch(
a, Unsafe.ARRAY_CHAR_BASE_OFFSET,
b, Unsafe.ARRAY_CHAR_BASE_OFFSET,
length, LOG2_ARRAY_CHAR_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[i] != b[i])
return i;
}
return -1;
}
static int mismatch(char[] a, int aFromIndex,
char[] b, int bFromIndex,
int length) {
int i = 0;
if (length > 3) {
int aOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_CHAR_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[aFromIndex + i] != b[bFromIndex + i])
return i;
}
return -1;
}
// Shorts
static int mismatch(short[] a,
short[] b,
int length) {
int i = 0;
if (length > 3) {
i = vectorizedMismatch(
a, Unsafe.ARRAY_SHORT_BASE_OFFSET,
b, Unsafe.ARRAY_SHORT_BASE_OFFSET,
length, LOG2_ARRAY_SHORT_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[i] != b[i])
return i;
}
return -1;
}
static int mismatch(short[] a, int aFromIndex,
short[] b, int bFromIndex,
int length) {
int i = 0;
if (length > 3) {
int aOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_SHORT_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[aFromIndex + i] != b[bFromIndex + i])
return i;
}
return -1;
}
// Ints
static int mismatch(int[] a,
int[] b,
int length) {
int i = 0;
if (length > 1) {
i = vectorizedMismatch(
a, Unsafe.ARRAY_INT_BASE_OFFSET,
b, Unsafe.ARRAY_INT_BASE_OFFSET,
length, LOG2_ARRAY_INT_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[i] != b[i])
return i;
}
return -1;
}
static int mismatch(int[] a, int aFromIndex,
int[] b, int bFromIndex,
int length) {
int i = 0;
if (length > 1) {
int aOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_INT_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[aFromIndex + i] != b[bFromIndex + i])
return i;
}
return -1;
}
// Floats
static int mismatch(float[] a,
float[] b,
int length) {
return mismatch(a, 0, b, 0, length);
}
static int mismatch(float[] a, int aFromIndex,
float[] b, int bFromIndex,
int length) {
int i = 0;
if (length > 1) {
int aOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_FLOAT_INDEX_SCALE);
// Mismatched
if (i >= 0) {
// Check if mismatch is not associated with two NaN values
if (!Float.isNaN(a[aFromIndex + i]) || !Float.isNaN(b[bFromIndex + i]))
return i;
// Mismatch on two different NaN values that are normalized to match
// Fall back to slow mechanism
// ISSUE: Consider looping over vectorizedMismatch adjusting ranges
// However, requires that returned value be relative to input ranges
i++;
}
// Matched
else {
i = length - ~i;
}
}
for (; i < length; i++) {
if (Float.floatToIntBits(a[aFromIndex + i]) != Float.floatToIntBits(b[bFromIndex + i]))
return i;
}
return -1;
}
// 64 bit sizes
// Long
static int mismatch(long[] a,
long[] b,
int length) {
if (length == 0) {
return -1;
}
int i = vectorizedMismatch(
a, Unsafe.ARRAY_LONG_BASE_OFFSET,
b, Unsafe.ARRAY_LONG_BASE_OFFSET,
length, LOG2_ARRAY_LONG_INDEX_SCALE);
return i >= 0 ? i : -1;
}
static int mismatch(long[] a, int aFromIndex,
long[] b, int bFromIndex,
int length) {
if (length == 0) {
return -1;
}
int aOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE);
int i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_LONG_INDEX_SCALE);
return i >= 0 ? i : -1;
}
// Double
static int mismatch(double[] a,
double[] b,
int length) {
return mismatch(a, 0, b, 0, length);
}
static int mismatch(double[] a, int aFromIndex,
double[] b, int bFromIndex,
int length) {
if (length == 0) {
return -1;
}
int aOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
int i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_DOUBLE_INDEX_SCALE);
if (i >= 0) {
// Check if mismatch is not associated with two NaN values
if (!Double.isNaN(a[aFromIndex + i]) || !Double.isNaN(b[bFromIndex + i]))
return i;
// Mismatch on two different NaN values that are normalized to match
// Fall back to slow mechanism
// ISSUE: Consider looping over vectorizedMismatch adjusting ranges
// However, requires that returned value be relative to input ranges
i++;
for (; i < length; i++) {
if (Double.doubleToLongBits(a[aFromIndex + i]) != Double.doubleToLongBits(b[bFromIndex + i]))
return i;
}
}
return -1;
}
}

View file

@ -0,0 +1,998 @@
/*
* Copyright (c) 2012, 2016, 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;
import java.io.FilterOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
/**
* This class consists exclusively of static methods for obtaining
* encoders and decoders for the Base64 encoding scheme. The
* implementation of this class supports the following types of Base64
* as specified in
* <a href="http://www.ietf.org/rfc/rfc4648.txt">RFC 4648</a> and
* <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
*
* <ul>
* <li><a id="basic"><b>Basic</b></a>
* <p> Uses "The Base64 Alphabet" as specified in Table 1 of
* RFC 4648 and RFC 2045 for encoding and decoding operation.
* The encoder does not add any line feed (line separator)
* character. The decoder rejects data that contains characters
* outside the base64 alphabet.</p></li>
*
* <li><a id="url"><b>URL and Filename safe</b></a>
* <p> Uses the "URL and Filename safe Base64 Alphabet" as specified
* in Table 2 of RFC 4648 for encoding and decoding. The
* encoder does not add any line feed (line separator) character.
* The decoder rejects data that contains characters outside the
* base64 alphabet.</p></li>
*
* <li><a id="mime"><b>MIME</b></a>
* <p> Uses the "The Base64 Alphabet" as specified in Table 1 of
* RFC 2045 for encoding and decoding operation. The encoded output
* must be represented in lines of no more than 76 characters each
* and uses a carriage return {@code '\r'} followed immediately by
* a linefeed {@code '\n'} as the line separator. No line separator
* is added to the end of the encoded output. All line separators
* or other characters not found in the base64 alphabet table are
* ignored in decoding operation.</p></li>
* </ul>
*
* <p> Unless otherwise noted, passing a {@code null} argument to a
* method of this class will cause a {@link java.lang.NullPointerException
* NullPointerException} to be thrown.
*
* @author Xueming Shen
* @since 1.8
*/
public class Base64 {
private Base64() {}
/**
* Returns a {@link Encoder} that encodes using the
* <a href="#basic">Basic</a> type base64 encoding scheme.
*
* @return A Base64 encoder.
*/
public static Encoder getEncoder() {
return Encoder.RFC4648;
}
/**
* Returns a {@link Encoder} that encodes using the
* <a href="#url">URL and Filename safe</a> type base64
* encoding scheme.
*
* @return A Base64 encoder.
*/
public static Encoder getUrlEncoder() {
return Encoder.RFC4648_URLSAFE;
}
/**
* Returns a {@link Encoder} that encodes using the
* <a href="#mime">MIME</a> type base64 encoding scheme.
*
* @return A Base64 encoder.
*/
public static Encoder getMimeEncoder() {
return Encoder.RFC2045;
}
/**
* Returns a {@link Encoder} that encodes using the
* <a href="#mime">MIME</a> type base64 encoding scheme
* with specified line length and line separators.
*
* @param lineLength
* the length of each output line (rounded down to nearest multiple
* of 4). If {@code lineLength <= 0} the output will not be separated
* in lines
* @param lineSeparator
* the line separator for each output line
*
* @return A Base64 encoder.
*
* @throws IllegalArgumentException if {@code lineSeparator} includes any
* character of "The Base64 Alphabet" as specified in Table 1 of
* RFC 2045.
*/
public static Encoder getMimeEncoder(int lineLength, byte[] lineSeparator) {
Objects.requireNonNull(lineSeparator);
int[] base64 = Decoder.fromBase64;
for (byte b : lineSeparator) {
if (base64[b & 0xff] != -1)
throw new IllegalArgumentException(
"Illegal base64 line separator character 0x" + Integer.toString(b, 16));
}
if (lineLength <= 0) {
return Encoder.RFC4648;
}
return new Encoder(false, lineSeparator, lineLength >> 2 << 2, true);
}
/**
* Returns a {@link Decoder} that decodes using the
* <a href="#basic">Basic</a> type base64 encoding scheme.
*
* @return A Base64 decoder.
*/
public static Decoder getDecoder() {
return Decoder.RFC4648;
}
/**
* Returns a {@link Decoder} that decodes using the
* <a href="#url">URL and Filename safe</a> type base64
* encoding scheme.
*
* @return A Base64 decoder.
*/
public static Decoder getUrlDecoder() {
return Decoder.RFC4648_URLSAFE;
}
/**
* Returns a {@link Decoder} that decodes using the
* <a href="#mime">MIME</a> type base64 decoding scheme.
*
* @return A Base64 decoder.
*/
public static Decoder getMimeDecoder() {
return Decoder.RFC2045;
}
/**
* This class implements an encoder for encoding byte data using
* the Base64 encoding scheme as specified in RFC 4648 and RFC 2045.
*
* <p> Instances of {@link Encoder} class are safe for use by
* multiple concurrent threads.
*
* <p> Unless otherwise noted, passing a {@code null} argument to
* a method of this class will cause a
* {@link java.lang.NullPointerException NullPointerException} to
* be thrown.
*
* @see Decoder
* @since 1.8
*/
public static class Encoder {
private final byte[] newline;
private final int linemax;
private final boolean isURL;
private final boolean doPadding;
private Encoder(boolean isURL, byte[] newline, int linemax, boolean doPadding) {
this.isURL = isURL;
this.newline = newline;
this.linemax = linemax;
this.doPadding = doPadding;
}
/**
* This array is a lookup table that translates 6-bit positive integer
* index values into their "Base64 Alphabet" equivalents as specified
* in "Table 1: The Base64 Alphabet" of RFC 2045 (and RFC 4648).
*/
private static final char[] toBase64 = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
/**
* It's the lookup table for "URL and Filename safe Base64" as specified
* in Table 2 of the RFC 4648, with the '+' and '/' changed to '-' and
* '_'. This table is used when BASE64_URL is specified.
*/
private static final char[] toBase64URL = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
};
private static final int MIMELINEMAX = 76;
private static final byte[] CRLF = new byte[] {'\r', '\n'};
static final Encoder RFC4648 = new Encoder(false, null, -1, true);
static final Encoder RFC4648_URLSAFE = new Encoder(true, null, -1, true);
static final Encoder RFC2045 = new Encoder(false, CRLF, MIMELINEMAX, true);
private final int outLength(int srclen) {
int len = 0;
if (doPadding) {
len = 4 * ((srclen + 2) / 3);
} else {
int n = srclen % 3;
len = 4 * (srclen / 3) + (n == 0 ? 0 : n + 1);
}
if (linemax > 0) // line separators
len += (len - 1) / linemax * newline.length;
return len;
}
/**
* Encodes all bytes from the specified byte array into a newly-allocated
* byte array using the {@link Base64} encoding scheme. The returned byte
* array is of the length of the resulting bytes.
*
* @param src
* the byte array to encode
* @return A newly-allocated byte array containing the resulting
* encoded bytes.
*/
public byte[] encode(byte[] src) {
int len = outLength(src.length); // dst array size
byte[] dst = new byte[len];
int ret = encode0(src, 0, src.length, dst);
if (ret != dst.length)
return Arrays.copyOf(dst, ret);
return dst;
}
/**
* Encodes all bytes from the specified byte array using the
* {@link Base64} encoding scheme, writing the resulting bytes to the
* given output byte array, starting at offset 0.
*
* <p> It is the responsibility of the invoker of this method to make
* sure the output byte array {@code dst} has enough space for encoding
* all bytes from the input byte array. No bytes will be written to the
* output byte array if the output byte array is not big enough.
*
* @param src
* the byte array to encode
* @param dst
* the output byte array
* @return The number of bytes written to the output byte array
*
* @throws IllegalArgumentException if {@code dst} does not have enough
* space for encoding all input bytes.
*/
public int encode(byte[] src, byte[] dst) {
int len = outLength(src.length); // dst array size
if (dst.length < len)
throw new IllegalArgumentException(
"Output byte array is too small for encoding all input bytes");
return encode0(src, 0, src.length, dst);
}
/**
* Encodes the specified byte array into a String using the {@link Base64}
* encoding scheme.
*
* <p> This method first encodes all input bytes into a base64 encoded
* byte array and then constructs a new String by using the encoded byte
* array and the {@link java.nio.charset.StandardCharsets#ISO_8859_1
* ISO-8859-1} charset.
*
* <p> In other words, an invocation of this method has exactly the same
* effect as invoking
* {@code new String(encode(src), StandardCharsets.ISO_8859_1)}.
*
* @param src
* the byte array to encode
* @return A String containing the resulting Base64 encoded characters
*/
@SuppressWarnings("deprecation")
public String encodeToString(byte[] src) {
byte[] encoded = encode(src);
return new String(encoded, 0, 0, encoded.length);
}
/**
* Encodes all remaining bytes from the specified byte buffer into
* a newly-allocated ByteBuffer using the {@link Base64} encoding
* scheme.
*
* Upon return, the source buffer's position will be updated to
* its limit; its limit will not have been changed. The returned
* output buffer's position will be zero and its limit will be the
* number of resulting encoded bytes.
*
* @param buffer
* the source ByteBuffer to encode
* @return A newly-allocated byte buffer containing the encoded bytes.
*/
public ByteBuffer encode(ByteBuffer buffer) {
int len = outLength(buffer.remaining());
byte[] dst = new byte[len];
int ret = 0;
if (buffer.hasArray()) {
ret = encode0(buffer.array(),
buffer.arrayOffset() + buffer.position(),
buffer.arrayOffset() + buffer.limit(),
dst);
buffer.position(buffer.limit());
} else {
byte[] src = new byte[buffer.remaining()];
buffer.get(src);
ret = encode0(src, 0, src.length, dst);
}
if (ret != dst.length)
dst = Arrays.copyOf(dst, ret);
return ByteBuffer.wrap(dst);
}
/**
* Wraps an output stream for encoding byte data using the {@link Base64}
* encoding scheme.
*
* <p> It is recommended to promptly close the returned output stream after
* use, during which it will flush all possible leftover bytes to the underlying
* output stream. Closing the returned output stream will close the underlying
* output stream.
*
* @param os
* the output stream.
* @return the output stream for encoding the byte data into the
* specified Base64 encoded format
*/
public OutputStream wrap(OutputStream os) {
Objects.requireNonNull(os);
return new EncOutputStream(os, isURL ? toBase64URL : toBase64,
newline, linemax, doPadding);
}
/**
* Returns an encoder instance that encodes equivalently to this one,
* but without adding any padding character at the end of the encoded
* byte data.
*
* <p> The encoding scheme of this encoder instance is unaffected by
* this invocation. The returned encoder instance should be used for
* non-padding encoding operation.
*
* @return an equivalent encoder that encodes without adding any
* padding character at the end
*/
public Encoder withoutPadding() {
if (!doPadding)
return this;
return new Encoder(isURL, newline, linemax, false);
}
private int encode0(byte[] src, int off, int end, byte[] dst) {
char[] base64 = isURL ? toBase64URL : toBase64;
int sp = off;
int slen = (end - off) / 3 * 3;
int sl = off + slen;
if (linemax > 0 && slen > linemax / 4 * 3)
slen = linemax / 4 * 3;
int dp = 0;
while (sp < sl) {
int sl0 = Math.min(sp + slen, sl);
for (int sp0 = sp, dp0 = dp ; sp0 < sl0; ) {
int bits = (src[sp0++] & 0xff) << 16 |
(src[sp0++] & 0xff) << 8 |
(src[sp0++] & 0xff);
dst[dp0++] = (byte)base64[(bits >>> 18) & 0x3f];
dst[dp0++] = (byte)base64[(bits >>> 12) & 0x3f];
dst[dp0++] = (byte)base64[(bits >>> 6) & 0x3f];
dst[dp0++] = (byte)base64[bits & 0x3f];
}
int dlen = (sl0 - sp) / 3 * 4;
dp += dlen;
sp = sl0;
if (dlen == linemax && sp < end) {
for (byte b : newline){
dst[dp++] = b;
}
}
}
if (sp < end) { // 1 or 2 leftover bytes
int b0 = src[sp++] & 0xff;
dst[dp++] = (byte)base64[b0 >> 2];
if (sp == end) {
dst[dp++] = (byte)base64[(b0 << 4) & 0x3f];
if (doPadding) {
dst[dp++] = '=';
dst[dp++] = '=';
}
} else {
int b1 = src[sp++] & 0xff;
dst[dp++] = (byte)base64[(b0 << 4) & 0x3f | (b1 >> 4)];
dst[dp++] = (byte)base64[(b1 << 2) & 0x3f];
if (doPadding) {
dst[dp++] = '=';
}
}
}
return dp;
}
}
/**
* This class implements a decoder for decoding byte data using the
* Base64 encoding scheme as specified in RFC 4648 and RFC 2045.
*
* <p> The Base64 padding character {@code '='} is accepted and
* interpreted as the end of the encoded byte data, but is not
* required. So if the final unit of the encoded byte data only has
* two or three Base64 characters (without the corresponding padding
* character(s) padded), they are decoded as if followed by padding
* character(s). If there is a padding character present in the
* final unit, the correct number of padding character(s) must be
* present, otherwise {@code IllegalArgumentException} (
* {@code IOException} when reading from a Base64 stream) is thrown
* during decoding.
*
* <p> Instances of {@link Decoder} class are safe for use by
* multiple concurrent threads.
*
* <p> Unless otherwise noted, passing a {@code null} argument to
* a method of this class will cause a
* {@link java.lang.NullPointerException NullPointerException} to
* be thrown.
*
* @see Encoder
* @since 1.8
*/
public static class Decoder {
private final boolean isURL;
private final boolean isMIME;
private Decoder(boolean isURL, boolean isMIME) {
this.isURL = isURL;
this.isMIME = isMIME;
}
/**
* Lookup table for decoding unicode characters drawn from the
* "Base64 Alphabet" (as specified in Table 1 of RFC 2045) into
* their 6-bit positive integer equivalents. Characters that
* are not in the Base64 alphabet but fall within the bounds of
* the array are encoded to -1.
*
*/
private static final int[] fromBase64 = new int[256];
static {
Arrays.fill(fromBase64, -1);
for (int i = 0; i < Encoder.toBase64.length; i++)
fromBase64[Encoder.toBase64[i]] = i;
fromBase64['='] = -2;
}
/**
* Lookup table for decoding "URL and Filename safe Base64 Alphabet"
* as specified in Table2 of the RFC 4648.
*/
private static final int[] fromBase64URL = new int[256];
static {
Arrays.fill(fromBase64URL, -1);
for (int i = 0; i < Encoder.toBase64URL.length; i++)
fromBase64URL[Encoder.toBase64URL[i]] = i;
fromBase64URL['='] = -2;
}
static final Decoder RFC4648 = new Decoder(false, false);
static final Decoder RFC4648_URLSAFE = new Decoder(true, false);
static final Decoder RFC2045 = new Decoder(false, true);
/**
* Decodes all bytes from the input byte array using the {@link Base64}
* encoding scheme, writing the results into a newly-allocated output
* byte array. The returned byte array is of the length of the resulting
* bytes.
*
* @param src
* the byte array to decode
*
* @return A newly-allocated byte array containing the decoded bytes.
*
* @throws IllegalArgumentException
* if {@code src} is not in valid Base64 scheme
*/
public byte[] decode(byte[] src) {
byte[] dst = new byte[outLength(src, 0, src.length)];
int ret = decode0(src, 0, src.length, dst);
if (ret != dst.length) {
dst = Arrays.copyOf(dst, ret);
}
return dst;
}
/**
* Decodes a Base64 encoded String into a newly-allocated byte array
* using the {@link Base64} encoding scheme.
*
* <p> An invocation of this method has exactly the same effect as invoking
* {@code decode(src.getBytes(StandardCharsets.ISO_8859_1))}
*
* @param src
* the string to decode
*
* @return A newly-allocated byte array containing the decoded bytes.
*
* @throws IllegalArgumentException
* if {@code src} is not in valid Base64 scheme
*/
public byte[] decode(String src) {
return decode(src.getBytes(StandardCharsets.ISO_8859_1));
}
/**
* Decodes all bytes from the input byte array using the {@link Base64}
* encoding scheme, writing the results into the given output byte array,
* starting at offset 0.
*
* <p> It is the responsibility of the invoker of this method to make
* sure the output byte array {@code dst} has enough space for decoding
* all bytes from the input byte array. No bytes will be written to
* the output byte array if the output byte array is not big enough.
*
* <p> If the input byte array is not in valid Base64 encoding scheme
* then some bytes may have been written to the output byte array before
* IllegalargumentException is thrown.
*
* @param src
* the byte array to decode
* @param dst
* the output byte array
*
* @return The number of bytes written to the output byte array
*
* @throws IllegalArgumentException
* if {@code src} is not in valid Base64 scheme, or {@code dst}
* does not have enough space for decoding all input bytes.
*/
public int decode(byte[] src, byte[] dst) {
int len = outLength(src, 0, src.length);
if (dst.length < len)
throw new IllegalArgumentException(
"Output byte array is too small for decoding all input bytes");
return decode0(src, 0, src.length, dst);
}
/**
* Decodes all bytes from the input byte buffer using the {@link Base64}
* encoding scheme, writing the results into a newly-allocated ByteBuffer.
*
* <p> Upon return, the source buffer's position will be updated to
* its limit; its limit will not have been changed. The returned
* output buffer's position will be zero and its limit will be the
* number of resulting decoded bytes
*
* <p> {@code IllegalArgumentException} is thrown if the input buffer
* is not in valid Base64 encoding scheme. The position of the input
* buffer will not be advanced in this case.
*
* @param buffer
* the ByteBuffer to decode
*
* @return A newly-allocated byte buffer containing the decoded bytes
*
* @throws IllegalArgumentException
* if {@code src} is not in valid Base64 scheme.
*/
public ByteBuffer decode(ByteBuffer buffer) {
int pos0 = buffer.position();
try {
byte[] src;
int sp, sl;
if (buffer.hasArray()) {
src = buffer.array();
sp = buffer.arrayOffset() + buffer.position();
sl = buffer.arrayOffset() + buffer.limit();
buffer.position(buffer.limit());
} else {
src = new byte[buffer.remaining()];
buffer.get(src);
sp = 0;
sl = src.length;
}
byte[] dst = new byte[outLength(src, sp, sl)];
return ByteBuffer.wrap(dst, 0, decode0(src, sp, sl, dst));
} catch (IllegalArgumentException iae) {
buffer.position(pos0);
throw iae;
}
}
/**
* Returns an input stream for decoding {@link Base64} encoded byte stream.
*
* <p> The {@code read} methods of the returned {@code InputStream} will
* throw {@code IOException} when reading bytes that cannot be decoded.
*
* <p> Closing the returned input stream will close the underlying
* input stream.
*
* @param is
* the input stream
*
* @return the input stream for decoding the specified Base64 encoded
* byte stream
*/
public InputStream wrap(InputStream is) {
Objects.requireNonNull(is);
return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME);
}
private int outLength(byte[] src, int sp, int sl) {
int[] base64 = isURL ? fromBase64URL : fromBase64;
int paddings = 0;
int len = sl - sp;
if (len == 0)
return 0;
if (len < 2) {
if (isMIME && base64[0] == -1)
return 0;
throw new IllegalArgumentException(
"Input byte[] should at least have 2 bytes for base64 bytes");
}
if (isMIME) {
// scan all bytes to fill out all non-alphabet. a performance
// trade-off of pre-scan or Arrays.copyOf
int n = 0;
while (sp < sl) {
int b = src[sp++] & 0xff;
if (b == '=') {
len -= (sl - sp + 1);
break;
}
if ((b = base64[b]) == -1)
n++;
}
len -= n;
} else {
if (src[sl - 1] == '=') {
paddings++;
if (src[sl - 2] == '=')
paddings++;
}
}
if (paddings == 0 && (len & 0x3) != 0)
paddings = 4 - (len & 0x3);
return 3 * ((len + 3) / 4) - paddings;
}
private int decode0(byte[] src, int sp, int sl, byte[] dst) {
int[] base64 = isURL ? fromBase64URL : fromBase64;
int dp = 0;
int bits = 0;
int shiftto = 18; // pos of first byte of 4-byte atom
while (sp < sl) {
int b = src[sp++] & 0xff;
if ((b = base64[b]) < 0) {
if (b == -2) { // padding byte '='
// = shiftto==18 unnecessary padding
// x= shiftto==12 a dangling single x
// x to be handled together with non-padding case
// xx= shiftto==6&&sp==sl missing last =
// xx=y shiftto==6 last is not =
if (shiftto == 6 && (sp == sl || src[sp++] != '=') ||
shiftto == 18) {
throw new IllegalArgumentException(
"Input byte array has wrong 4-byte ending unit");
}
break;
}
if (isMIME) // skip if for rfc2045
continue;
else
throw new IllegalArgumentException(
"Illegal base64 character " +
Integer.toString(src[sp - 1], 16));
}
bits |= (b << shiftto);
shiftto -= 6;
if (shiftto < 0) {
dst[dp++] = (byte)(bits >> 16);
dst[dp++] = (byte)(bits >> 8);
dst[dp++] = (byte)(bits);
shiftto = 18;
bits = 0;
}
}
// reached end of byte array or hit padding '=' characters.
if (shiftto == 6) {
dst[dp++] = (byte)(bits >> 16);
} else if (shiftto == 0) {
dst[dp++] = (byte)(bits >> 16);
dst[dp++] = (byte)(bits >> 8);
} else if (shiftto == 12) {
// dangling single "x", incorrectly encoded.
throw new IllegalArgumentException(
"Last unit does not have enough valid bits");
}
// anything left is invalid, if is not MIME.
// if MIME, ignore all non-base64 character
while (sp < sl) {
if (isMIME && base64[src[sp++] & 0xff] < 0)
continue;
throw new IllegalArgumentException(
"Input byte array has incorrect ending byte at " + sp);
}
return dp;
}
}
/*
* An output stream for encoding bytes into the Base64.
*/
private static class EncOutputStream extends FilterOutputStream {
private int leftover = 0;
private int b0, b1, b2;
private boolean closed = false;
private final char[] base64; // byte->base64 mapping
private final byte[] newline; // line separator, if needed
private final int linemax;
private final boolean doPadding;// whether or not to pad
private int linepos = 0;
EncOutputStream(OutputStream os, char[] base64,
byte[] newline, int linemax, boolean doPadding) {
super(os);
this.base64 = base64;
this.newline = newline;
this.linemax = linemax;
this.doPadding = doPadding;
}
@Override
public void write(int b) throws IOException {
byte[] buf = new byte[1];
buf[0] = (byte)(b & 0xff);
write(buf, 0, 1);
}
private void checkNewline() throws IOException {
if (linepos == linemax) {
out.write(newline);
linepos = 0;
}
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (closed)
throw new IOException("Stream is closed");
if (off < 0 || len < 0 || len > b.length - off)
throw new ArrayIndexOutOfBoundsException();
if (len == 0)
return;
if (leftover != 0) {
if (leftover == 1) {
b1 = b[off++] & 0xff;
len--;
if (len == 0) {
leftover++;
return;
}
}
b2 = b[off++] & 0xff;
len--;
checkNewline();
out.write(base64[b0 >> 2]);
out.write(base64[(b0 << 4) & 0x3f | (b1 >> 4)]);
out.write(base64[(b1 << 2) & 0x3f | (b2 >> 6)]);
out.write(base64[b2 & 0x3f]);
linepos += 4;
}
int nBits24 = len / 3;
leftover = len - (nBits24 * 3);
while (nBits24-- > 0) {
checkNewline();
int bits = (b[off++] & 0xff) << 16 |
(b[off++] & 0xff) << 8 |
(b[off++] & 0xff);
out.write(base64[(bits >>> 18) & 0x3f]);
out.write(base64[(bits >>> 12) & 0x3f]);
out.write(base64[(bits >>> 6) & 0x3f]);
out.write(base64[bits & 0x3f]);
linepos += 4;
}
if (leftover == 1) {
b0 = b[off++] & 0xff;
} else if (leftover == 2) {
b0 = b[off++] & 0xff;
b1 = b[off++] & 0xff;
}
}
@Override
public void close() throws IOException {
if (!closed) {
closed = true;
if (leftover == 1) {
checkNewline();
out.write(base64[b0 >> 2]);
out.write(base64[(b0 << 4) & 0x3f]);
if (doPadding) {
out.write('=');
out.write('=');
}
} else if (leftover == 2) {
checkNewline();
out.write(base64[b0 >> 2]);
out.write(base64[(b0 << 4) & 0x3f | (b1 >> 4)]);
out.write(base64[(b1 << 2) & 0x3f]);
if (doPadding) {
out.write('=');
}
}
leftover = 0;
out.close();
}
}
}
/*
* An input stream for decoding Base64 bytes
*/
private static class DecInputStream extends InputStream {
private final InputStream is;
private final boolean isMIME;
private final int[] base64; // base64 -> byte mapping
private int bits = 0; // 24-bit buffer for decoding
private int nextin = 18; // next available "off" in "bits" for input;
// -> 18, 12, 6, 0
private int nextout = -8; // next available "off" in "bits" for output;
// -> 8, 0, -8 (no byte for output)
private boolean eof = false;
private boolean closed = false;
DecInputStream(InputStream is, int[] base64, boolean isMIME) {
this.is = is;
this.base64 = base64;
this.isMIME = isMIME;
}
private byte[] sbBuf = new byte[1];
@Override
public int read() throws IOException {
return read(sbBuf, 0, 1) == -1 ? -1 : sbBuf[0] & 0xff;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (closed)
throw new IOException("Stream is closed");
if (eof && nextout < 0) // eof and no leftover
return -1;
if (off < 0 || len < 0 || len > b.length - off)
throw new IndexOutOfBoundsException();
int oldOff = off;
if (nextout >= 0) { // leftover output byte(s) in bits buf
do {
if (len == 0)
return off - oldOff;
b[off++] = (byte)(bits >> nextout);
len--;
nextout -= 8;
} while (nextout >= 0);
bits = 0;
}
while (len > 0) {
int v = is.read();
if (v == -1) {
eof = true;
if (nextin != 18) {
if (nextin == 12)
throw new IOException("Base64 stream has one un-decoded dangling byte.");
// treat ending xx/xxx without padding character legal.
// same logic as v == '=' below
b[off++] = (byte)(bits >> (16));
len--;
if (nextin == 0) { // only one padding byte
if (len == 0) { // no enough output space
bits >>= 8; // shift to lowest byte
nextout = 0;
} else {
b[off++] = (byte) (bits >> 8);
}
}
}
if (off == oldOff)
return -1;
else
return off - oldOff;
}
if (v == '=') { // padding byte(s)
// = shiftto==18 unnecessary padding
// x= shiftto==12 dangling x, invalid unit
// xx= shiftto==6 && missing last '='
// xx=y or last is not '='
if (nextin == 18 || nextin == 12 ||
nextin == 6 && is.read() != '=') {
throw new IOException("Illegal base64 ending sequence:" + nextin);
}
b[off++] = (byte)(bits >> (16));
len--;
if (nextin == 0) { // only one padding byte
if (len == 0) { // no enough output space
bits >>= 8; // shift to lowest byte
nextout = 0;
} else {
b[off++] = (byte) (bits >> 8);
}
}
eof = true;
break;
}
if ((v = base64[v]) == -1) {
if (isMIME) // skip if for rfc2045
continue;
else
throw new IOException("Illegal base64 character " +
Integer.toString(v, 16));
}
bits |= (v << nextin);
if (nextin == 0) {
nextin = 18; // clear for next
nextout = 16;
while (nextout >= 0) {
b[off++] = (byte)(bits >> nextout);
len--;
nextout -= 8;
if (len == 0 && nextout >= 0) { // don't clean "bits"
return off - oldOff;
}
}
bits = 0;
} else {
nextin -= 6;
}
}
return off - oldOff;
}
@Override
public int available() throws IOException {
if (closed)
throw new IOException("Stream is closed");
return is.available(); // TBD:
}
@Override
public void close() throws IOException {
if (!closed) {
closed = true;
is.close();
}
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,604 @@
/*
* Copyright (c) 1997, 2017, 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;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* The root interface in the <i>collection hierarchy</i>. A collection
* represents a group of objects, known as its <i>elements</i>. Some
* collections allow duplicate elements and others do not. Some are ordered
* and others unordered. The JDK does not provide any <i>direct</i>
* implementations of this interface: it provides implementations of more
* specific subinterfaces like {@code Set} and {@code List}. This interface
* is typically used to pass collections around and manipulate them where
* maximum generality is desired.
*
* <p><i>Bags</i> or <i>multisets</i> (unordered collections that may contain
* duplicate elements) should implement this interface directly.
*
* <p>All general-purpose {@code Collection} implementation classes (which
* typically implement {@code Collection} indirectly through one of its
* subinterfaces) should provide two "standard" constructors: a void (no
* arguments) constructor, which creates an empty collection, and a
* constructor with a single argument of type {@code Collection}, which
* creates a new collection with the same elements as its argument. In
* effect, the latter constructor allows the user to copy any collection,
* producing an equivalent collection of the desired implementation type.
* There is no way to enforce this convention (as interfaces cannot contain
* constructors) but all of the general-purpose {@code Collection}
* implementations in the Java platform libraries comply.
*
* <p>The "destructive" methods contained in this interface, that is, the
* methods that modify the collection on which they operate, are specified to
* throw {@code UnsupportedOperationException} if this collection does not
* support the operation. If this is the case, these methods may, but are not
* required to, throw an {@code UnsupportedOperationException} if the
* invocation would have no effect on the collection. For example, invoking
* the {@link #addAll(Collection)} method on an unmodifiable collection may,
* but is not required to, throw the exception if the collection to be added
* is empty.
*
* <p><a id="optional-restrictions">
* Some collection implementations have restrictions on the elements that
* they may contain.</a> For example, some implementations prohibit null elements,
* and some have restrictions on the types of their elements. Attempting to
* add an ineligible element throws an unchecked exception, typically
* {@code NullPointerException} or {@code ClassCastException}. Attempting
* to query the presence of an ineligible element may throw an exception,
* or it may simply return false; some implementations will exhibit the former
* behavior and some will exhibit the latter. More generally, attempting an
* operation on an ineligible element whose completion would not result in
* the insertion of an ineligible element into the collection may throw an
* exception or it may succeed, at the option of the implementation.
* Such exceptions are marked as "optional" in the specification for this
* interface.
*
* <p>It is up to each collection to determine its own synchronization
* policy. In the absence of a stronger guarantee by the
* implementation, undefined behavior may result from the invocation
* of any method on a collection that is being mutated by another
* thread; this includes direct invocations, passing the collection to
* a method that might perform invocations, and using an existing
* iterator to examine the collection.
*
* <p>Many methods in Collections Framework interfaces are defined in
* terms of the {@link Object#equals(Object) equals} method. For example,
* the specification for the {@link #contains(Object) contains(Object o)}
* method says: "returns {@code true} if and only if this collection
* contains at least one element {@code e} such that
* {@code (o==null ? e==null : o.equals(e))}." This specification should
* <i>not</i> be construed to imply that invoking {@code Collection.contains}
* with a non-null argument {@code o} will cause {@code o.equals(e)} to be
* invoked for any element {@code e}. Implementations are free to implement
* optimizations whereby the {@code equals} invocation is avoided, for
* example, by first comparing the hash codes of the two elements. (The
* {@link Object#hashCode()} specification guarantees that two objects with
* unequal hash codes cannot be equal.) More generally, implementations of
* the various Collections Framework interfaces are free to take advantage of
* the specified behavior of underlying {@link Object} methods wherever the
* implementor deems it appropriate.
*
* <p>Some collection operations which perform recursive traversal of the
* collection may fail with an exception for self-referential instances where
* the collection directly or indirectly contains itself. This includes the
* {@code clone()}, {@code equals()}, {@code hashCode()} and {@code toString()}
* methods. Implementations may optionally handle the self-referential scenario,
* however most current implementations do not do so.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @implSpec
* The default method implementations (inherited or otherwise) do not apply any
* synchronization protocol. If a {@code Collection} implementation has a
* specific synchronization protocol, then it must override default
* implementations to apply that protocol.
*
* @param <E> the type of elements in this collection
*
* @author Josh Bloch
* @author Neal Gafter
* @see Set
* @see List
* @see Map
* @see SortedSet
* @see SortedMap
* @see HashSet
* @see TreeSet
* @see ArrayList
* @see LinkedList
* @see Vector
* @see Collections
* @see Arrays
* @see AbstractCollection
* @since 1.2
*/
public interface Collection<E> extends Iterable<E> {
// Query Operations
/**
* Returns the number of elements in this collection. If this collection
* contains more than {@code Integer.MAX_VALUE} elements, returns
* {@code Integer.MAX_VALUE}.
*
* @return the number of elements in this collection
*/
int size();
/**
* Returns {@code true} if this collection contains no elements.
*
* @return {@code true} if this collection contains no elements
*/
boolean isEmpty();
/**
* Returns {@code true} if this collection contains the specified element.
* More formally, returns {@code true} if and only if this collection
* contains at least one element {@code e} such that
* {@code Objects.equals(o, e)}.
*
* @param o element whose presence in this collection is to be tested
* @return {@code true} if this collection contains the specified
* element
* @throws ClassCastException if the type of the specified element
* is incompatible with this collection
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* collection does not permit null elements
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean contains(Object o);
/**
* Returns an iterator over the elements in this collection. There are no
* guarantees concerning the order in which the elements are returned
* (unless this collection is an instance of some class that provides a
* guarantee).
*
* @return an {@code Iterator} over the elements in this collection
*/
Iterator<E> iterator();
/**
* Returns an array containing all of the elements in this collection.
* If this collection makes any guarantees as to what order its elements
* are returned by its iterator, this method must return the elements in
* the same order.
*
* <p>The returned array will be "safe" in that no references to it are
* maintained by this collection. (In other words, this method must
* allocate a new array even if this collection is backed by an array).
* The caller is thus free to modify the returned array.
*
* <p>This method acts as bridge between array-based and collection-based
* APIs.
*
* @return an array containing all of the elements in this collection
*/
Object[] toArray();
/**
* Returns an array containing all of the elements in this collection;
* the runtime type of the returned array is that of the specified array.
* If the collection fits in the specified array, it is returned therein.
* Otherwise, a new array is allocated with the runtime type of the
* specified array and the size of this collection.
*
* <p>If this collection fits in the specified array with room to spare
* (i.e., the array has more elements than this collection), the element
* in the array immediately following the end of the collection is set to
* {@code null}. (This is useful in determining the length of this
* collection <i>only</i> if the caller knows that this collection does
* not contain any {@code null} elements.)
*
* <p>If this collection makes any guarantees as to what order its elements
* are returned by its iterator, this method must return the elements in
* the same order.
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
* <p>Suppose {@code x} is a collection known to contain only strings.
* The following code can be used to dump the collection into a newly
* allocated array of {@code String}:
*
* <pre>
* String[] y = x.toArray(new String[0]);</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
*
* @param <T> the runtime type of the array to contain the collection
* @param a the array into which the elements of this collection are to be
* stored, if it is big enough; otherwise, a new array of the same
* runtime type is allocated for this purpose.
* @return an array containing all of the elements in this collection
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this collection
* @throws NullPointerException if the specified array is null
*/
<T> T[] toArray(T[] a);
// Modification Operations
/**
* Ensures that this collection contains the specified element (optional
* operation). Returns {@code true} if this collection changed as a
* result of the call. (Returns {@code false} if this collection does
* not permit duplicates and already contains the specified element.)<p>
*
* Collections that support this operation may place limitations on what
* elements may be added to this collection. In particular, some
* collections will refuse to add {@code null} elements, and others will
* impose restrictions on the type of elements that may be added.
* Collection classes should clearly specify in their documentation any
* restrictions on what elements may be added.<p>
*
* If a collection refuses to add a particular element for any reason
* other than that it already contains the element, it <i>must</i> throw
* an exception (rather than returning {@code false}). This preserves
* the invariant that a collection always contains the specified element
* after this call returns.
*
* @param e element whose presence in this collection is to be ensured
* @return {@code true} if this collection changed as a result of the
* call
* @throws UnsupportedOperationException if the {@code add} operation
* is not supported by this collection
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this collection
* @throws NullPointerException if the specified element is null and this
* collection does not permit null elements
* @throws IllegalArgumentException if some property of the element
* prevents it from being added to this collection
* @throws IllegalStateException if the element cannot be added at this
* time due to insertion restrictions
*/
boolean add(E e);
/**
* Removes a single instance of the specified element from this
* collection, if it is present (optional operation). More formally,
* removes an element {@code e} such that
* {@code Objects.equals(o, e)}, if
* this collection contains one or more such elements. Returns
* {@code true} if this collection contained the specified element (or
* equivalently, if this collection changed as a result of the call).
*
* @param o element to be removed from this collection, if present
* @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the type of the specified element
* is incompatible with this collection
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* collection does not permit null elements
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws UnsupportedOperationException if the {@code remove} operation
* is not supported by this collection
*/
boolean remove(Object o);
// Bulk Operations
/**
* Returns {@code true} if this collection contains all of the elements
* in the specified collection.
*
* @param c collection to be checked for containment in this collection
* @return {@code true} if this collection contains all of the elements
* in the specified collection
* @throws ClassCastException if the types of one or more elements
* in the specified collection are incompatible with this
* collection
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified collection contains one
* or more null elements and this collection does not permit null
* elements
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null.
* @see #contains(Object)
*/
boolean containsAll(Collection<?> c);
/**
* Adds all of the elements in the specified collection to this collection
* (optional operation). The behavior of this operation is undefined if
* the specified collection is modified while the operation is in progress.
* (This implies that the behavior of this call is undefined if the
* specified collection is this collection, and this collection is
* nonempty.)
*
* @param c collection containing elements to be added to this collection
* @return {@code true} if this collection changed as a result of the call
* @throws UnsupportedOperationException if the {@code addAll} operation
* is not supported by this collection
* @throws ClassCastException if the class of an element of the specified
* collection prevents it from being added to this collection
* @throws NullPointerException if the specified collection contains a
* null element and this collection does not permit null elements,
* or if the specified collection is null
* @throws IllegalArgumentException if some property of an element of the
* specified collection prevents it from being added to this
* collection
* @throws IllegalStateException if not all the elements can be added at
* this time due to insertion restrictions
* @see #add(Object)
*/
boolean addAll(Collection<? extends E> c);
/**
* Removes all of this collection's elements that are also contained in the
* specified collection (optional operation). After this call returns,
* this collection will contain no elements in common with the specified
* collection.
*
* @param c collection containing elements to be removed from this collection
* @return {@code true} if this collection changed as a result of the
* call
* @throws UnsupportedOperationException if the {@code removeAll} method
* is not supported by this collection
* @throws ClassCastException if the types of one or more elements
* in this collection are incompatible with the specified
* collection
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this collection contains one or more
* null elements and the specified collection does not support
* null elements
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #remove(Object)
* @see #contains(Object)
*/
boolean removeAll(Collection<?> c);
/**
* Removes all of the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @implSpec
* The default implementation traverses all elements of the collection using
* its {@link #iterator}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws NullPointerException if the specified filter is null
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @since 1.8
*/
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
/**
* Retains only the elements in this collection that are contained in the
* specified collection (optional operation). In other words, removes from
* this collection all of its elements that are not contained in the
* specified collection.
*
* @param c collection containing elements to be retained in this collection
* @return {@code true} if this collection changed as a result of the call
* @throws UnsupportedOperationException if the {@code retainAll} operation
* is not supported by this collection
* @throws ClassCastException if the types of one or more elements
* in this collection are incompatible with the specified
* collection
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this collection contains one or more
* null elements and the specified collection does not permit null
* elements
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #remove(Object)
* @see #contains(Object)
*/
boolean retainAll(Collection<?> c);
/**
* Removes all of the elements from this collection (optional operation).
* The collection will be empty after this method returns.
*
* @throws UnsupportedOperationException if the {@code clear} operation
* is not supported by this collection
*/
void clear();
// Comparison and hashing
/**
* Compares the specified object with this collection for equality. <p>
*
* While the {@code Collection} interface adds no stipulations to the
* general contract for the {@code Object.equals}, programmers who
* implement the {@code Collection} interface "directly" (in other words,
* create a class that is a {@code Collection} but is not a {@code Set}
* or a {@code List}) must exercise care if they choose to override the
* {@code Object.equals}. It is not necessary to do so, and the simplest
* course of action is to rely on {@code Object}'s implementation, but
* the implementor may wish to implement a "value comparison" in place of
* the default "reference comparison." (The {@code List} and
* {@code Set} interfaces mandate such value comparisons.)<p>
*
* The general contract for the {@code Object.equals} method states that
* equals must be symmetric (in other words, {@code a.equals(b)} if and
* only if {@code b.equals(a)}). The contracts for {@code List.equals}
* and {@code Set.equals} state that lists are only equal to other lists,
* and sets to other sets. Thus, a custom {@code equals} method for a
* collection class that implements neither the {@code List} nor
* {@code Set} interface must return {@code false} when this collection
* is compared to any list or set. (By the same logic, it is not possible
* to write a class that correctly implements both the {@code Set} and
* {@code List} interfaces.)
*
* @param o object to be compared for equality with this collection
* @return {@code true} if the specified object is equal to this
* collection
*
* @see Object#equals(Object)
* @see Set#equals(Object)
* @see List#equals(Object)
*/
boolean equals(Object o);
/**
* Returns the hash code value for this collection. While the
* {@code Collection} interface adds no stipulations to the general
* contract for the {@code Object.hashCode} method, programmers should
* take note that any class that overrides the {@code Object.equals}
* method must also override the {@code Object.hashCode} method in order
* to satisfy the general contract for the {@code Object.hashCode} method.
* In particular, {@code c1.equals(c2)} implies that
* {@code c1.hashCode()==c2.hashCode()}.
*
* @return the hash code value for this collection
*
* @see Object#hashCode()
* @see Object#equals(Object)
*/
int hashCode();
/**
* Creates a {@link Spliterator} over the elements in this collection.
*
* Implementations should document characteristic values reported by the
* spliterator. Such characteristic values are not required to be reported
* if the spliterator reports {@link Spliterator#SIZED} and this collection
* contains no elements.
*
* <p>The default implementation should be overridden by subclasses that
* can return a more efficient spliterator. In order to
* preserve expected laziness behavior for the {@link #stream()} and
* {@link #parallelStream()} methods, spliterators should either have the
* characteristic of {@code IMMUTABLE} or {@code CONCURRENT}, or be
* <em><a href="Spliterator.html#binding">late-binding</a></em>.
* If none of these is practical, the overriding class should describe the
* spliterator's documented policy of binding and structural interference,
* and should override the {@link #stream()} and {@link #parallelStream()}
* methods to create streams using a {@code Supplier} of the spliterator,
* as in:
* <pre>{@code
* Stream<E> s = StreamSupport.stream(() -> spliterator(), spliteratorCharacteristics)
* }</pre>
* <p>These requirements ensure that streams produced by the
* {@link #stream()} and {@link #parallelStream()} methods will reflect the
* contents of the collection as of initiation of the terminal stream
* operation.
*
* @implSpec
* The default implementation creates a
* <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator
* from the collection's {@code Iterator}. The spliterator inherits the
* <em>fail-fast</em> properties of the collection's iterator.
* <p>
* The created {@code Spliterator} reports {@link Spliterator#SIZED}.
*
* @implNote
* The created {@code Spliterator} additionally reports
* {@link Spliterator#SUBSIZED}.
*
* <p>If a spliterator covers no elements then the reporting of additional
* characteristic values, beyond that of {@code SIZED} and {@code SUBSIZED},
* does not aid clients to control, specialize or simplify computation.
* However, this does enable shared use of an immutable and empty
* spliterator instance (see {@link Spliterators#emptySpliterator()}) for
* empty collections, and enables clients to determine if such a spliterator
* covers no elements.
*
* @return a {@code Spliterator} over the elements in this collection
* @since 1.8
*/
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
/**
* Returns a sequential {@code Stream} with this collection as its source.
*
* <p>This method should be overridden when the {@link #spliterator()}
* method cannot return a spliterator that is {@code IMMUTABLE},
* {@code CONCURRENT}, or <em>late-binding</em>. (See {@link #spliterator()}
* for details.)
*
* @implSpec
* The default implementation creates a sequential {@code Stream} from the
* collection's {@code Spliterator}.
*
* @return a sequential {@code Stream} over the elements in this collection
* @since 1.8
*/
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
/**
* Returns a possibly parallel {@code Stream} with this collection as its
* source. It is allowable for this method to return a sequential stream.
*
* <p>This method should be overridden when the {@link #spliterator()}
* method cannot return a spliterator that is {@code IMMUTABLE},
* {@code CONCURRENT}, or <em>late-binding</em>. (See {@link #spliterator()}
* for details.)
*
* @implSpec
* The default implementation creates a parallel {@code Stream} from the
* collection's {@code Spliterator}.
*
* @return a possibly parallel {@code Stream} over the elements in this
* collection
* @since 1.8
*/
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,908 @@
/*
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2009 Google Inc. 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;
/**
* This is a near duplicate of {@link TimSort}, modified for use with
* arrays of objects that implement {@link Comparable}, instead of using
* explicit comparators.
*
* <p>If you are using an optimizing VM, you may find that ComparableTimSort
* offers no performance benefit over TimSort in conjunction with a
* comparator that simply returns {@code ((Comparable)first).compareTo(Second)}.
* If this is the case, you are better off deleting ComparableTimSort to
* eliminate the code duplication. (See Arrays.java for details.)
*
* @author Josh Bloch
*/
class ComparableTimSort {
/**
* This is the minimum sized sequence that will be merged. Shorter
* sequences will be lengthened by calling binarySort. If the entire
* array is less than this length, no merges will be performed.
*
* This constant should be a power of two. It was 64 in Tim Peter's C
* implementation, but 32 was empirically determined to work better in
* this implementation. In the unlikely event that you set this constant
* to be a number that's not a power of two, you'll need to change the
* {@link #minRunLength} computation.
*
* If you decrease this constant, you must change the stackLen
* computation in the TimSort constructor, or you risk an
* ArrayOutOfBounds exception. See listsort.txt for a discussion
* of the minimum stack length required as a function of the length
* of the array being sorted and the minimum merge sequence length.
*/
private static final int MIN_MERGE = 32;
/**
* The array being sorted.
*/
private final Object[] a;
/**
* When we get into galloping mode, we stay there until both runs win less
* often than MIN_GALLOP consecutive times.
*/
private static final int MIN_GALLOP = 7;
/**
* This controls when we get *into* galloping mode. It is initialized
* to MIN_GALLOP. The mergeLo and mergeHi methods nudge it higher for
* random data, and lower for highly structured data.
*/
private int minGallop = MIN_GALLOP;
/**
* Maximum initial size of tmp array, which is used for merging. The array
* can grow to accommodate demand.
*
* Unlike Tim's original C version, we do not allocate this much storage
* when sorting smaller arrays. This change was required for performance.
*/
private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
/**
* Temp storage for merges. A workspace array may optionally be
* provided in constructor, and if so will be used as long as it
* is big enough.
*/
private Object[] tmp;
private int tmpBase; // base of tmp array slice
private int tmpLen; // length of tmp array slice
/**
* A stack of pending runs yet to be merged. Run i starts at
* address base[i] and extends for len[i] elements. It's always
* true (so long as the indices are in bounds) that:
*
* runBase[i] + runLen[i] == runBase[i + 1]
*
* so we could cut the storage for this, but it's a minor amount,
* and keeping all the info explicit simplifies the code.
*/
private int stackSize = 0; // Number of pending runs on stack
private final int[] runBase;
private final int[] runLen;
/**
* Creates a TimSort instance to maintain the state of an ongoing sort.
*
* @param a the array to be sorted
* @param work a workspace array (slice)
* @param workBase origin of usable space in work array
* @param workLen usable size of work array
*/
private ComparableTimSort(Object[] a, Object[] work, int workBase, int workLen) {
this.a = a;
// Allocate temp storage (which may be increased later if necessary)
int len = a.length;
int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
if (work == null || workLen < tlen || workBase + tlen > work.length) {
tmp = new Object[tlen];
tmpBase = 0;
tmpLen = tlen;
}
else {
tmp = work;
tmpBase = workBase;
tmpLen = workLen;
}
/*
* Allocate runs-to-be-merged stack (which cannot be expanded). The
* stack length requirements are described in listsort.txt. The C
* version always uses the same stack length (85), but this was
* measured to be too expensive when sorting "mid-sized" arrays (e.g.,
* 100 elements) in Java. Therefore, we use smaller (but sufficiently
* large) stack lengths for smaller arrays. The "magic numbers" in the
* computation below must be changed if MIN_MERGE is decreased. See
* the MIN_MERGE declaration above for more information.
* The maximum value of 49 allows for an array up to length
* Integer.MAX_VALUE-4, if array is filled by the worst case stack size
* increasing scenario. More explanations are given in section 4 of:
* http://envisage-project.eu/wp-content/uploads/2015/02/sorting.pdf
*/
int stackLen = (len < 120 ? 5 :
len < 1542 ? 10 :
len < 119151 ? 24 : 49);
runBase = new int[stackLen];
runLen = new int[stackLen];
}
/*
* The next method (package private and static) constitutes the
* entire API of this class.
*/
/**
* Sorts the given range, using the given workspace array slice
* for temp storage when possible. This method is designed to be
* invoked from public methods (in class Arrays) after performing
* any necessary array bounds checks and expanding parameters into
* the required forms.
*
* @param a the array to be sorted
* @param lo the index of the first element, inclusive, to be sorted
* @param hi the index of the last element, exclusive, to be sorted
* @param work a workspace array (slice)
* @param workBase origin of usable space in work array
* @param workLen usable size of work array
* @since 1.8
*/
static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) {
assert a != null && lo >= 0 && lo <= hi && hi <= a.length;
int nRemaining = hi - lo;
if (nRemaining < 2)
return; // Arrays of size 0 and 1 are always sorted
// If array is small, do a "mini-TimSort" with no merges
if (nRemaining < MIN_MERGE) {
int initRunLen = countRunAndMakeAscending(a, lo, hi);
binarySort(a, lo, hi, lo + initRunLen);
return;
}
/**
* March over the array once, left to right, finding natural runs,
* extending short natural runs to minRun elements, and merging runs
* to maintain stack invariant.
*/
ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
int minRun = minRunLength(nRemaining);
do {
// Identify next run
int runLen = countRunAndMakeAscending(a, lo, hi);
// If run is short, extend to min(minRun, nRemaining)
if (runLen < minRun) {
int force = nRemaining <= minRun ? nRemaining : minRun;
binarySort(a, lo, lo + force, lo + runLen);
runLen = force;
}
// Push run onto pending-run stack, and maybe merge
ts.pushRun(lo, runLen);
ts.mergeCollapse();
// Advance to find next run
lo += runLen;
nRemaining -= runLen;
} while (nRemaining != 0);
// Merge all remaining runs to complete sort
assert lo == hi;
ts.mergeForceCollapse();
assert ts.stackSize == 1;
}
/**
* Sorts the specified portion of the specified array using a binary
* insertion sort. This is the best method for sorting small numbers
* of elements. It requires O(n log n) compares, but O(n^2) data
* movement (worst case).
*
* If the initial part of the specified range is already sorted,
* this method can take advantage of it: the method assumes that the
* elements from index {@code lo}, inclusive, to {@code start},
* exclusive are already sorted.
*
* @param a the array in which a range is to be sorted
* @param lo the index of the first element in the range to be sorted
* @param hi the index after the last element in the range to be sorted
* @param start the index of the first element in the range that is
* not already known to be sorted ({@code lo <= start <= hi})
*/
@SuppressWarnings({"fallthrough", "rawtypes", "unchecked"})
private static void binarySort(Object[] a, int lo, int hi, int start) {
assert lo <= start && start <= hi;
if (start == lo)
start++;
for ( ; start < hi; start++) {
Comparable pivot = (Comparable) a[start];
// Set left (and right) to the index where a[start] (pivot) belongs
int left = lo;
int right = start;
assert left <= right;
/*
* Invariants:
* pivot >= all in [lo, left).
* pivot < all in [right, start).
*/
while (left < right) {
int mid = (left + right) >>> 1;
if (pivot.compareTo(a[mid]) < 0)
right = mid;
else
left = mid + 1;
}
assert left == right;
/*
* The invariants still hold: pivot >= all in [lo, left) and
* pivot < all in [left, start), so pivot belongs at left. Note
* that if there are elements equal to pivot, left points to the
* first slot after them -- that's why this sort is stable.
* Slide elements over to make room for pivot.
*/
int n = start - left; // The number of elements to move
// Switch is just an optimization for arraycopy in default case
switch (n) {
case 2: a[left + 2] = a[left + 1];
case 1: a[left + 1] = a[left];
break;
default: System.arraycopy(a, left, a, left + 1, n);
}
a[left] = pivot;
}
}
/**
* Returns the length of the run beginning at the specified position in
* the specified array and reverses the run if it is descending (ensuring
* that the run will always be ascending when the method returns).
*
* A run is the longest ascending sequence with:
*
* a[lo] <= a[lo + 1] <= a[lo + 2] <= ...
*
* or the longest descending sequence with:
*
* a[lo] > a[lo + 1] > a[lo + 2] > ...
*
* For its intended use in a stable mergesort, the strictness of the
* definition of "descending" is needed so that the call can safely
* reverse a descending sequence without violating stability.
*
* @param a the array in which a run is to be counted and possibly reversed
* @param lo index of the first element in the run
* @param hi index after the last element that may be contained in the run.
It is required that {@code lo < hi}.
* @return the length of the run beginning at the specified position in
* the specified array
*/
@SuppressWarnings({"unchecked", "rawtypes"})
private static int countRunAndMakeAscending(Object[] a, int lo, int hi) {
assert lo < hi;
int runHi = lo + 1;
if (runHi == hi)
return 1;
// Find end of run, and reverse range if descending
if (((Comparable) a[runHi++]).compareTo(a[lo]) < 0) { // Descending
while (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) < 0)
runHi++;
reverseRange(a, lo, runHi);
} else { // Ascending
while (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) >= 0)
runHi++;
}
return runHi - lo;
}
/**
* Reverse the specified range of the specified array.
*
* @param a the array in which a range is to be reversed
* @param lo the index of the first element in the range to be reversed
* @param hi the index after the last element in the range to be reversed
*/
private static void reverseRange(Object[] a, int lo, int hi) {
hi--;
while (lo < hi) {
Object t = a[lo];
a[lo++] = a[hi];
a[hi--] = t;
}
}
/**
* Returns the minimum acceptable run length for an array of the specified
* length. Natural runs shorter than this will be extended with
* {@link #binarySort}.
*
* Roughly speaking, the computation is:
*
* If n < MIN_MERGE, return n (it's too small to bother with fancy stuff).
* Else if n is an exact power of 2, return MIN_MERGE/2.
* Else return an int k, MIN_MERGE/2 <= k <= MIN_MERGE, such that n/k
* is close to, but strictly less than, an exact power of 2.
*
* For the rationale, see listsort.txt.
*
* @param n the length of the array to be sorted
* @return the length of the minimum run to be merged
*/
private static int minRunLength(int n) {
assert n >= 0;
int r = 0; // Becomes 1 if any 1 bits are shifted off
while (n >= MIN_MERGE) {
r |= (n & 1);
n >>= 1;
}
return n + r;
}
/**
* Pushes the specified run onto the pending-run stack.
*
* @param runBase index of the first element in the run
* @param runLen the number of elements in the run
*/
private void pushRun(int runBase, int runLen) {
this.runBase[stackSize] = runBase;
this.runLen[stackSize] = runLen;
stackSize++;
}
/**
* Examines the stack of runs waiting to be merged and merges adjacent runs
* until the stack invariants are reestablished:
*
* 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1]
* 2. runLen[i - 2] > runLen[i - 1]
*
* This method is called each time a new run is pushed onto the stack,
* so the invariants are guaranteed to hold for i < stackSize upon
* entry to the method.
*/
private void mergeCollapse() {
while (stackSize > 1) {
int n = stackSize - 2;
if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) {
if (runLen[n - 1] < runLen[n + 1])
n--;
mergeAt(n);
} else if (runLen[n] <= runLen[n + 1]) {
mergeAt(n);
} else {
break; // Invariant is established
}
}
}
/**
* Merges all runs on the stack until only one remains. This method is
* called once, to complete the sort.
*/
private void mergeForceCollapse() {
while (stackSize > 1) {
int n = stackSize - 2;
if (n > 0 && runLen[n - 1] < runLen[n + 1])
n--;
mergeAt(n);
}
}
/**
* Merges the two runs at stack indices i and i+1. Run i must be
* the penultimate or antepenultimate run on the stack. In other words,
* i must be equal to stackSize-2 or stackSize-3.
*
* @param i stack index of the first of the two runs to merge
*/
@SuppressWarnings("unchecked")
private void mergeAt(int i) {
assert stackSize >= 2;
assert i >= 0;
assert i == stackSize - 2 || i == stackSize - 3;
int base1 = runBase[i];
int len1 = runLen[i];
int base2 = runBase[i + 1];
int len2 = runLen[i + 1];
assert len1 > 0 && len2 > 0;
assert base1 + len1 == base2;
/*
* Record the length of the combined runs; if i is the 3rd-last
* run now, also slide over the last run (which isn't involved
* in this merge). The current run (i+1) goes away in any case.
*/
runLen[i] = len1 + len2;
if (i == stackSize - 3) {
runBase[i + 1] = runBase[i + 2];
runLen[i + 1] = runLen[i + 2];
}
stackSize--;
/*
* Find where the first element of run2 goes in run1. Prior elements
* in run1 can be ignored (because they're already in place).
*/
int k = gallopRight((Comparable<Object>) a[base2], a, base1, len1, 0);
assert k >= 0;
base1 += k;
len1 -= k;
if (len1 == 0)
return;
/*
* Find where the last element of run1 goes in run2. Subsequent elements
* in run2 can be ignored (because they're already in place).
*/
len2 = gallopLeft((Comparable<Object>) a[base1 + len1 - 1], a,
base2, len2, len2 - 1);
assert len2 >= 0;
if (len2 == 0)
return;
// Merge remaining runs, using tmp array with min(len1, len2) elements
if (len1 <= len2)
mergeLo(base1, len1, base2, len2);
else
mergeHi(base1, len1, base2, len2);
}
/**
* Locates the position at which to insert the specified key into the
* specified sorted range; if the range contains an element equal to key,
* returns the index of the leftmost equal element.
*
* @param key the key whose insertion point to search for
* @param a the array in which to search
* @param base the index of the first element in the range
* @param len the length of the range; must be > 0
* @param hint the index at which to begin the search, 0 <= hint < n.
* The closer hint is to the result, the faster this method will run.
* @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k],
* pretending that a[b - 1] is minus infinity and a[b + n] is infinity.
* In other words, key belongs at index b + k; or in other words,
* the first k elements of a should precede key, and the last n - k
* should follow it.
*/
private static int gallopLeft(Comparable<Object> key, Object[] a,
int base, int len, int hint) {
assert len > 0 && hint >= 0 && hint < len;
int lastOfs = 0;
int ofs = 1;
if (key.compareTo(a[base + hint]) > 0) {
// Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs]
int maxOfs = len - hint;
while (ofs < maxOfs && key.compareTo(a[base + hint + ofs]) > 0) {
lastOfs = ofs;
ofs = (ofs << 1) + 1;
if (ofs <= 0) // int overflow
ofs = maxOfs;
}
if (ofs > maxOfs)
ofs = maxOfs;
// Make offsets relative to base
lastOfs += hint;
ofs += hint;
} else { // key <= a[base + hint]
// Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs]
final int maxOfs = hint + 1;
while (ofs < maxOfs && key.compareTo(a[base + hint - ofs]) <= 0) {
lastOfs = ofs;
ofs = (ofs << 1) + 1;
if (ofs <= 0) // int overflow
ofs = maxOfs;
}
if (ofs > maxOfs)
ofs = maxOfs;
// Make offsets relative to base
int tmp = lastOfs;
lastOfs = hint - ofs;
ofs = hint - tmp;
}
assert -1 <= lastOfs && lastOfs < ofs && ofs <= len;
/*
* Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere
* to the right of lastOfs but no farther right than ofs. Do a binary
* search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs].
*/
lastOfs++;
while (lastOfs < ofs) {
int m = lastOfs + ((ofs - lastOfs) >>> 1);
if (key.compareTo(a[base + m]) > 0)
lastOfs = m + 1; // a[base + m] < key
else
ofs = m; // key <= a[base + m]
}
assert lastOfs == ofs; // so a[base + ofs - 1] < key <= a[base + ofs]
return ofs;
}
/**
* Like gallopLeft, except that if the range contains an element equal to
* key, gallopRight returns the index after the rightmost equal element.
*
* @param key the key whose insertion point to search for
* @param a the array in which to search
* @param base the index of the first element in the range
* @param len the length of the range; must be > 0
* @param hint the index at which to begin the search, 0 <= hint < n.
* The closer hint is to the result, the faster this method will run.
* @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k]
*/
private static int gallopRight(Comparable<Object> key, Object[] a,
int base, int len, int hint) {
assert len > 0 && hint >= 0 && hint < len;
int ofs = 1;
int lastOfs = 0;
if (key.compareTo(a[base + hint]) < 0) {
// Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs]
int maxOfs = hint + 1;
while (ofs < maxOfs && key.compareTo(a[base + hint - ofs]) < 0) {
lastOfs = ofs;
ofs = (ofs << 1) + 1;
if (ofs <= 0) // int overflow
ofs = maxOfs;
}
if (ofs > maxOfs)
ofs = maxOfs;
// Make offsets relative to b
int tmp = lastOfs;
lastOfs = hint - ofs;
ofs = hint - tmp;
} else { // a[b + hint] <= key
// Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs]
int maxOfs = len - hint;
while (ofs < maxOfs && key.compareTo(a[base + hint + ofs]) >= 0) {
lastOfs = ofs;
ofs = (ofs << 1) + 1;
if (ofs <= 0) // int overflow
ofs = maxOfs;
}
if (ofs > maxOfs)
ofs = maxOfs;
// Make offsets relative to b
lastOfs += hint;
ofs += hint;
}
assert -1 <= lastOfs && lastOfs < ofs && ofs <= len;
/*
* Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to
* the right of lastOfs but no farther right than ofs. Do a binary
* search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs].
*/
lastOfs++;
while (lastOfs < ofs) {
int m = lastOfs + ((ofs - lastOfs) >>> 1);
if (key.compareTo(a[base + m]) < 0)
ofs = m; // key < a[b + m]
else
lastOfs = m + 1; // a[b + m] <= key
}
assert lastOfs == ofs; // so a[b + ofs - 1] <= key < a[b + ofs]
return ofs;
}
/**
* Merges two adjacent runs in place, in a stable fashion. The first
* element of the first run must be greater than the first element of the
* second run (a[base1] > a[base2]), and the last element of the first run
* (a[base1 + len1-1]) must be greater than all elements of the second run.
*
* For performance, this method should be called only when len1 <= len2;
* its twin, mergeHi should be called if len1 >= len2. (Either method
* may be called if len1 == len2.)
*
* @param base1 index of first element in first run to be merged
* @param len1 length of first run to be merged (must be > 0)
* @param base2 index of first element in second run to be merged
* (must be aBase + aLen)
* @param len2 length of second run to be merged (must be > 0)
*/
@SuppressWarnings({"unchecked", "rawtypes"})
private void mergeLo(int base1, int len1, int base2, int len2) {
assert len1 > 0 && len2 > 0 && base1 + len1 == base2;
// Copy first run into temp array
Object[] a = this.a; // For performance
Object[] tmp = ensureCapacity(len1);
int cursor1 = tmpBase; // Indexes into tmp array
int cursor2 = base2; // Indexes int a
int dest = base1; // Indexes int a
System.arraycopy(a, base1, tmp, cursor1, len1);
// Move first element of second run and deal with degenerate cases
a[dest++] = a[cursor2++];
if (--len2 == 0) {
System.arraycopy(tmp, cursor1, a, dest, len1);
return;
}
if (len1 == 1) {
System.arraycopy(a, cursor2, a, dest, len2);
a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge
return;
}
int minGallop = this.minGallop; // Use local variable for performance
outer:
while (true) {
int count1 = 0; // Number of times in a row that first run won
int count2 = 0; // Number of times in a row that second run won
/*
* Do the straightforward thing until (if ever) one run starts
* winning consistently.
*/
do {
assert len1 > 1 && len2 > 0;
if (((Comparable) a[cursor2]).compareTo(tmp[cursor1]) < 0) {
a[dest++] = a[cursor2++];
count2++;
count1 = 0;
if (--len2 == 0)
break outer;
} else {
a[dest++] = tmp[cursor1++];
count1++;
count2 = 0;
if (--len1 == 1)
break outer;
}
} while ((count1 | count2) < minGallop);
/*
* One run is winning so consistently that galloping may be a
* huge win. So try that, and continue galloping until (if ever)
* neither run appears to be winning consistently anymore.
*/
do {
assert len1 > 1 && len2 > 0;
count1 = gallopRight((Comparable) a[cursor2], tmp, cursor1, len1, 0);
if (count1 != 0) {
System.arraycopy(tmp, cursor1, a, dest, count1);
dest += count1;
cursor1 += count1;
len1 -= count1;
if (len1 <= 1) // len1 == 1 || len1 == 0
break outer;
}
a[dest++] = a[cursor2++];
if (--len2 == 0)
break outer;
count2 = gallopLeft((Comparable) tmp[cursor1], a, cursor2, len2, 0);
if (count2 != 0) {
System.arraycopy(a, cursor2, a, dest, count2);
dest += count2;
cursor2 += count2;
len2 -= count2;
if (len2 == 0)
break outer;
}
a[dest++] = tmp[cursor1++];
if (--len1 == 1)
break outer;
minGallop--;
} while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP);
if (minGallop < 0)
minGallop = 0;
minGallop += 2; // Penalize for leaving gallop mode
} // End of "outer" loop
this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field
if (len1 == 1) {
assert len2 > 0;
System.arraycopy(a, cursor2, a, dest, len2);
a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge
} else if (len1 == 0) {
throw new IllegalArgumentException(
"Comparison method violates its general contract!");
} else {
assert len2 == 0;
assert len1 > 1;
System.arraycopy(tmp, cursor1, a, dest, len1);
}
}
/**
* Like mergeLo, except that this method should be called only if
* len1 >= len2; mergeLo should be called if len1 <= len2. (Either method
* may be called if len1 == len2.)
*
* @param base1 index of first element in first run to be merged
* @param len1 length of first run to be merged (must be > 0)
* @param base2 index of first element in second run to be merged
* (must be aBase + aLen)
* @param len2 length of second run to be merged (must be > 0)
*/
@SuppressWarnings({"unchecked", "rawtypes"})
private void mergeHi(int base1, int len1, int base2, int len2) {
assert len1 > 0 && len2 > 0 && base1 + len1 == base2;
// Copy second run into temp array
Object[] a = this.a; // For performance
Object[] tmp = ensureCapacity(len2);
int tmpBase = this.tmpBase;
System.arraycopy(a, base2, tmp, tmpBase, len2);
int cursor1 = base1 + len1 - 1; // Indexes into a
int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
int dest = base2 + len2 - 1; // Indexes into a
// Move last element of first run and deal with degenerate cases
a[dest--] = a[cursor1--];
if (--len1 == 0) {
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
return;
}
if (len2 == 1) {
dest -= len1;
cursor1 -= len1;
System.arraycopy(a, cursor1 + 1, a, dest + 1, len1);
a[dest] = tmp[cursor2];
return;
}
int minGallop = this.minGallop; // Use local variable for performance
outer:
while (true) {
int count1 = 0; // Number of times in a row that first run won
int count2 = 0; // Number of times in a row that second run won
/*
* Do the straightforward thing until (if ever) one run
* appears to win consistently.
*/
do {
assert len1 > 0 && len2 > 1;
if (((Comparable) tmp[cursor2]).compareTo(a[cursor1]) < 0) {
a[dest--] = a[cursor1--];
count1++;
count2 = 0;
if (--len1 == 0)
break outer;
} else {
a[dest--] = tmp[cursor2--];
count2++;
count1 = 0;
if (--len2 == 1)
break outer;
}
} while ((count1 | count2) < minGallop);
/*
* One run is winning so consistently that galloping may be a
* huge win. So try that, and continue galloping until (if ever)
* neither run appears to be winning consistently anymore.
*/
do {
assert len1 > 0 && len2 > 1;
count1 = len1 - gallopRight((Comparable) tmp[cursor2], a, base1, len1, len1 - 1);
if (count1 != 0) {
dest -= count1;
cursor1 -= count1;
len1 -= count1;
System.arraycopy(a, cursor1 + 1, a, dest + 1, count1);
if (len1 == 0)
break outer;
}
a[dest--] = tmp[cursor2--];
if (--len2 == 1)
break outer;
count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, tmpBase, len2, len2 - 1);
if (count2 != 0) {
dest -= count2;
cursor2 -= count2;
len2 -= count2;
System.arraycopy(tmp, cursor2 + 1, a, dest + 1, count2);
if (len2 <= 1)
break outer; // len2 == 1 || len2 == 0
}
a[dest--] = a[cursor1--];
if (--len1 == 0)
break outer;
minGallop--;
} while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP);
if (minGallop < 0)
minGallop = 0;
minGallop += 2; // Penalize for leaving gallop mode
} // End of "outer" loop
this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field
if (len2 == 1) {
assert len1 > 0;
dest -= len1;
cursor1 -= len1;
System.arraycopy(a, cursor1 + 1, a, dest + 1, len1);
a[dest] = tmp[cursor2]; // Move first elt of run2 to front of merge
} else if (len2 == 0) {
throw new IllegalArgumentException(
"Comparison method violates its general contract!");
} else {
assert len1 == 0;
assert len2 > 0;
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
}
}
/**
* Ensures that the external array tmp has at least the specified
* number of elements, increasing its size if necessary. The size
* increases exponentially to ensure amortized linear time complexity.
*
* @param minCapacity the minimum required capacity of the tmp array
* @return tmp, whether or not it grew
*/
private Object[] ensureCapacity(int minCapacity) {
if (tmpLen < minCapacity) {
// Compute smallest power of 2 > minCapacity
int newSize = minCapacity;
newSize |= newSize >> 1;
newSize |= newSize >> 2;
newSize |= newSize >> 4;
newSize |= newSize >> 8;
newSize |= newSize >> 16;
newSize++;
if (newSize < 0) // Not bloody likely!
newSize = minCapacity;
else
newSize = Math.min(newSize, a.length >>> 1);
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
Object[] newArray = new Object[newSize];
tmp = newArray;
tmpLen = newSize;
tmpBase = 0;
}
return tmp;
}
}

View file

@ -0,0 +1,534 @@
/*
* Copyright (c) 1997, 2017, 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;
import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;
/**
* A comparison function, which imposes a <i>total ordering</i> on some
* collection of objects. Comparators can be passed to a sort method (such
* as {@link Collections#sort(List,Comparator) Collections.sort} or {@link
* Arrays#sort(Object[],Comparator) Arrays.sort}) to allow precise control
* over the sort order. Comparators can also be used to control the order of
* certain data structures (such as {@link SortedSet sorted sets} or {@link
* SortedMap sorted maps}), or to provide an ordering for collections of
* objects that don't have a {@link Comparable natural ordering}.<p>
*
* The ordering imposed by a comparator {@code c} on a set of elements
* {@code S} is said to be <i>consistent with equals</i> if and only if
* {@code c.compare(e1, e2)==0} has the same boolean value as
* {@code e1.equals(e2)} for every {@code e1} and {@code e2} in
* {@code S}.<p>
*
* Caution should be exercised when using a comparator capable of imposing an
* ordering inconsistent with equals to order a sorted set (or sorted map).
* Suppose a sorted set (or sorted map) with an explicit comparator {@code c}
* is used with elements (or keys) drawn from a set {@code S}. If the
* ordering imposed by {@code c} on {@code S} is inconsistent with equals,
* the sorted set (or sorted map) will behave "strangely." In particular the
* sorted set (or sorted map) will violate the general contract for set (or
* map), which is defined in terms of {@code equals}.<p>
*
* For example, suppose one adds two elements {@code a} and {@code b} such that
* {@code (a.equals(b) && c.compare(a, b) != 0)}
* to an empty {@code TreeSet} with comparator {@code c}.
* The second {@code add} operation will return
* true (and the size of the tree set will increase) because {@code a} and
* {@code b} are not equivalent from the tree set's perspective, even though
* this is contrary to the specification of the
* {@link Set#add Set.add} method.<p>
*
* Note: It is generally a good idea for comparators to also implement
* {@code java.io.Serializable}, as they may be used as ordering methods in
* serializable data structures (like {@link TreeSet}, {@link TreeMap}). In
* order for the data structure to serialize successfully, the comparator (if
* provided) must implement {@code Serializable}.<p>
*
* For the mathematically inclined, the <i>relation</i> that defines the
* <i>imposed ordering</i> that a given comparator {@code c} imposes on a
* given set of objects {@code S} is:<pre>
* {(x, y) such that c.compare(x, y) &lt;= 0}.
* </pre> The <i>quotient</i> for this total order is:<pre>
* {(x, y) such that c.compare(x, y) == 0}.
* </pre>
*
* It follows immediately from the contract for {@code compare} that the
* quotient is an <i>equivalence relation</i> on {@code S}, and that the
* imposed ordering is a <i>total order</i> on {@code S}. When we say that
* the ordering imposed by {@code c} on {@code S} is <i>consistent with
* equals</i>, we mean that the quotient for the ordering is the equivalence
* relation defined by the objects' {@link Object#equals(Object)
* equals(Object)} method(s):<pre>
* {(x, y) such that x.equals(y)}. </pre>
*
* <p>Unlike {@code Comparable}, a comparator may optionally permit
* comparison of null arguments, while maintaining the requirements for
* an equivalence relation.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <T> the type of objects that may be compared by this comparator
*
* @author Josh Bloch
* @author Neal Gafter
* @see Comparable
* @see java.io.Serializable
* @since 1.2
*/
@FunctionalInterface
public interface Comparator<T> {
/**
* Compares its two arguments for order. Returns a negative integer,
* zero, or a positive integer as the first argument is less than, equal
* to, or greater than the second.<p>
*
* The implementor must ensure that {@code sgn(compare(x, y)) ==
* -sgn(compare(y, x))} for all {@code x} and {@code y}. (This
* implies that {@code compare(x, y)} must throw an exception if and only
* if {@code compare(y, x)} throws an exception.)<p>
*
* The implementor must also ensure that the relation is transitive:
* {@code ((compare(x, y)>0) && (compare(y, z)>0))} implies
* {@code compare(x, z)>0}.<p>
*
* Finally, the implementor must ensure that {@code compare(x, y)==0}
* implies that {@code sgn(compare(x, z))==sgn(compare(y, z))} for all
* {@code z}.<p>
*
* It is generally the case, but <i>not</i> strictly required that
* {@code (compare(x, y)==0) == (x.equals(y))}. Generally speaking,
* any comparator that violates this condition should clearly indicate
* this fact. The recommended language is "Note: this comparator
* imposes orderings that are inconsistent with equals."<p>
*
* In the foregoing description, the notation
* {@code sgn(}<i>expression</i>{@code )} designates the mathematical
* <i>signum</i> function, which is defined to return one of {@code -1},
* {@code 0}, or {@code 1} according to whether the value of
* <i>expression</i> is negative, zero, or positive, respectively.
*
* @param o1 the first object to be compared.
* @param o2 the second object to be compared.
* @return a negative integer, zero, or a positive integer as the
* first argument is less than, equal to, or greater than the
* second.
* @throws NullPointerException if an argument is null and this
* comparator does not permit null arguments
* @throws ClassCastException if the arguments' types prevent them from
* being compared by this comparator.
*/
int compare(T o1, T o2);
/**
* Indicates whether some other object is &quot;equal to&quot; this
* comparator. This method must obey the general contract of
* {@link Object#equals(Object)}. Additionally, this method can return
* {@code true} <i>only</i> if the specified object is also a comparator
* and it imposes the same ordering as this comparator. Thus,
* {@code comp1.equals(comp2)} implies that {@code sgn(comp1.compare(o1,
* o2))==sgn(comp2.compare(o1, o2))} for every object reference
* {@code o1} and {@code o2}.<p>
*
* Note that it is <i>always</i> safe <i>not</i> to override
* {@code Object.equals(Object)}. However, overriding this method may,
* in some cases, improve performance by allowing programs to determine
* that two distinct comparators impose the same order.
*
* @param obj the reference object with which to compare.
* @return {@code true} only if the specified object is also
* a comparator and it imposes the same ordering as this
* comparator.
* @see Object#equals(Object)
* @see Object#hashCode()
*/
boolean equals(Object obj);
/**
* Returns a comparator that imposes the reverse ordering of this
* comparator.
*
* @return a comparator that imposes the reverse ordering of this
* comparator.
* @since 1.8
*/
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
/**
* Returns a lexicographic-order comparator with another comparator.
* If this {@code Comparator} considers two elements equal, i.e.
* {@code compare(a, b) == 0}, {@code other} is used to determine the order.
*
* <p>The returned comparator is serializable if the specified comparator
* is also serializable.
*
* @apiNote
* For example, to sort a collection of {@code String} based on the length
* and then case-insensitive natural ordering, the comparator can be
* composed using following code,
*
* <pre>{@code
* Comparator<String> cmp = Comparator.comparingInt(String::length)
* .thenComparing(String.CASE_INSENSITIVE_ORDER);
* }</pre>
*
* @param other the other comparator to be used when this comparator
* compares two objects that are equal.
* @return a lexicographic-order comparator composed of this and then the
* other comparator
* @throws NullPointerException if the argument is null.
* @since 1.8
*/
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a key to be compared with the given {@code Comparator}.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor, cmp))}.
*
* @param <U> the type of the sort key
* @param keyExtractor the function used to extract the sort key
* @param keyComparator the {@code Comparator} used to compare the sort key
* @return a lexicographic-order comparator composed of this comparator
* and then comparing on the key extracted by the keyExtractor function
* @throws NullPointerException if either argument is null.
* @see #comparing(Function, Comparator)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a {@code Comparable} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor))}.
*
* @param <U> the type of the {@link Comparable} sort key
* @param keyExtractor the function used to extract the {@link
* Comparable} sort key
* @return a lexicographic-order comparator composed of this and then the
* {@link Comparable} sort key.
* @throws NullPointerException if the argument is null.
* @see #comparing(Function)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts an {@code int} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparingInt(keyExtractor))}.
*
* @param keyExtractor the function used to extract the integer sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code int} sort key
* @throws NullPointerException if the argument is null.
* @see #comparingInt(ToIntFunction)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a {@code long} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparingLong(keyExtractor))}.
*
* @param keyExtractor the function used to extract the long sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code long} sort key
* @throws NullPointerException if the argument is null.
* @see #comparingLong(ToLongFunction)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
return thenComparing(comparingLong(keyExtractor));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a {@code double} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparingDouble(keyExtractor))}.
*
* @param keyExtractor the function used to extract the double sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code double} sort key
* @throws NullPointerException if the argument is null.
* @see #comparingDouble(ToDoubleFunction)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
return thenComparing(comparingDouble(keyExtractor));
}
/**
* Returns a comparator that imposes the reverse of the <em>natural
* ordering</em>.
*
* <p>The returned comparator is serializable and throws {@link
* NullPointerException} when comparing {@code null}.
*
* @param <T> the {@link Comparable} type of element to be compared
* @return a comparator that imposes the reverse of the <i>natural
* ordering</i> on {@code Comparable} objects.
* @see Comparable
* @since 1.8
*/
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
/**
* Returns a comparator that compares {@link Comparable} objects in natural
* order.
*
* <p>The returned comparator is serializable and throws {@link
* NullPointerException} when comparing {@code null}.
*
* @param <T> the {@link Comparable} type of element to be compared
* @return a comparator that imposes the <i>natural ordering</i> on {@code
* Comparable} objects.
* @see Comparable
* @since 1.8
*/
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}
/**
* Returns a null-friendly comparator that considers {@code null} to be
* less than non-null. When both are {@code null}, they are considered
* equal. If both are non-null, the specified {@code Comparator} is used
* to determine the order. If the specified comparator is {@code null},
* then the returned comparator considers all non-null values to be equal.
*
* <p>The returned comparator is serializable if the specified comparator
* is serializable.
*
* @param <T> the type of the elements to be compared
* @param comparator a {@code Comparator} for comparing non-null values
* @return a comparator that considers {@code null} to be less than
* non-null, and compares non-null objects with the supplied
* {@code Comparator}.
* @since 1.8
*/
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
}
/**
* Returns a null-friendly comparator that considers {@code null} to be
* greater than non-null. When both are {@code null}, they are considered
* equal. If both are non-null, the specified {@code Comparator} is used
* to determine the order. If the specified comparator is {@code null},
* then the returned comparator considers all non-null values to be equal.
*
* <p>The returned comparator is serializable if the specified comparator
* is serializable.
*
* @param <T> the type of the elements to be compared
* @param comparator a {@code Comparator} for comparing non-null values
* @return a comparator that considers {@code null} to be greater than
* non-null, and compares non-null objects with the supplied
* {@code Comparator}.
* @since 1.8
*/
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(false, comparator);
}
/**
* Accepts a function that extracts a sort key from a type {@code T}, and
* returns a {@code Comparator<T>} that compares by that sort key using
* the specified {@link Comparator}.
*
* <p>The returned comparator is serializable if the specified function
* and comparator are both serializable.
*
* @apiNote
* For example, to obtain a {@code Comparator} that compares {@code
* Person} objects by their last name ignoring case differences,
*
* <pre>{@code
* Comparator<Person> cmp = Comparator.comparing(
* Person::getLastName,
* String.CASE_INSENSITIVE_ORDER);
* }</pre>
*
* @param <T> the type of element to be compared
* @param <U> the type of the sort key
* @param keyExtractor the function used to extract the sort key
* @param keyComparator the {@code Comparator} used to compare the sort key
* @return a comparator that compares by an extracted key using the
* specified {@code Comparator}
* @throws NullPointerException if either argument is null
* @since 1.8
*/
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
/**
* Accepts a function that extracts a {@link java.lang.Comparable
* Comparable} sort key from a type {@code T}, and returns a {@code
* Comparator<T>} that compares by that sort key.
*
* <p>The returned comparator is serializable if the specified function
* is also serializable.
*
* @apiNote
* For example, to obtain a {@code Comparator} that compares {@code
* Person} objects by their last name,
*
* <pre>{@code
* Comparator<Person> byLastName = Comparator.comparing(Person::getLastName);
* }</pre>
*
* @param <T> the type of element to be compared
* @param <U> the type of the {@code Comparable} sort key
* @param keyExtractor the function used to extract the {@link
* Comparable} sort key
* @return a comparator that compares by an extracted key
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
/**
* Accepts a function that extracts an {@code int} sort key from a type
* {@code T}, and returns a {@code Comparator<T>} that compares by that
* sort key.
*
* <p>The returned comparator is serializable if the specified function
* is also serializable.
*
* @param <T> the type of element to be compared
* @param keyExtractor the function used to extract the integer sort key
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
}
/**
* Accepts a function that extracts a {@code long} sort key from a type
* {@code T}, and returns a {@code Comparator<T>} that compares by that
* sort key.
*
* <p>The returned comparator is serializable if the specified function is
* also serializable.
*
* @param <T> the type of element to be compared
* @param keyExtractor the function used to extract the long sort key
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
}
/**
* Accepts a function that extracts a {@code double} sort key from a type
* {@code T}, and returns a {@code Comparator<T>} that compares by that
* sort key.
*
* <p>The returned comparator is serializable if the specified function
* is also serializable.
*
* @param <T> the type of element to be compared
* @param keyExtractor the function used to extract the double sort key
* @return a comparator that compares by an extracted key
* @see #comparing(Function)
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
}
}

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2012, 2013, 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;
import java.io.Serializable;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
/**
* Package private supporting class for {@link Comparator}.
*/
class Comparators {
private Comparators() {
throw new AssertionError("no instances");
}
/**
* Compares {@link Comparable} objects in natural order.
*
* @see Comparable
*/
enum NaturalOrderComparator implements Comparator<Comparable<Object>> {
INSTANCE;
@Override
public int compare(Comparable<Object> c1, Comparable<Object> c2) {
return c1.compareTo(c2);
}
@Override
public Comparator<Comparable<Object>> reversed() {
return Comparator.reverseOrder();
}
}
/**
* Null-friendly comparators
*/
static final class NullComparator<T> implements Comparator<T>, Serializable {
private static final long serialVersionUID = -7569533591570686392L;
private final boolean nullFirst;
// if null, non-null Ts are considered equal
private final Comparator<T> real;
@SuppressWarnings("unchecked")
NullComparator(boolean nullFirst, Comparator<? super T> real) {
this.nullFirst = nullFirst;
this.real = (Comparator<T>) real;
}
@Override
public int compare(T a, T b) {
if (a == null) {
return (b == null) ? 0 : (nullFirst ? -1 : 1);
} else if (b == null) {
return nullFirst ? 1: -1;
} else {
return (real == null) ? 0 : real.compare(a, b);
}
}
@Override
public Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return new NullComparator<>(nullFirst, real == null ? other : real.thenComparing(other));
}
@Override
public Comparator<T> reversed() {
return new NullComparator<>(!nullFirst, real == null ? null : real.reversed());
}
}
}

View file

@ -0,0 +1,124 @@
/*
* Copyright (c) 1997, 2013, 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;
/**
* This exception may be thrown by methods that have detected concurrent
* modification of an object when such modification is not permissible.
* <p>
* For example, it is not generally permissible for one thread to modify a Collection
* while another thread is iterating over it. In general, the results of the
* iteration are undefined under these circumstances. Some Iterator
* implementations (including those of all the general purpose collection implementations
* provided by the JRE) may choose to throw this exception if this behavior is
* detected. Iterators that do this are known as <i>fail-fast</i> iterators,
* as they fail quickly and cleanly, rather that risking arbitrary,
* non-deterministic behavior at an undetermined time in the future.
* <p>
* Note that this exception does not always indicate that an object has
* been concurrently modified by a <i>different</i> thread. If a single
* thread issues a sequence of method invocations that violates the
* contract of an object, the object may throw this exception. For
* example, if a thread modifies a collection directly while it is
* iterating over the collection with a fail-fast iterator, the iterator
* will throw this exception.
*
* <p>Note that fail-fast behavior cannot be guaranteed as it is, generally
* speaking, impossible to make any hard guarantees in the presence of
* unsynchronized concurrent modification. Fail-fast operations
* throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>{@code ConcurrentModificationException}
* should be used only to detect bugs.</i>
*
* @author Josh Bloch
* @see Collection
* @see Iterator
* @see Spliterator
* @see ListIterator
* @see Vector
* @see LinkedList
* @see HashSet
* @see Hashtable
* @see TreeMap
* @see AbstractList
* @since 1.2
*/
public class ConcurrentModificationException extends RuntimeException {
private static final long serialVersionUID = -3666751008965953603L;
/**
* Constructs a ConcurrentModificationException with no
* detail message.
*/
public ConcurrentModificationException() {
}
/**
* Constructs a {@code ConcurrentModificationException} with the
* specified detail message.
*
* @param message the detail message pertaining to this exception.
*/
public ConcurrentModificationException(String message) {
super(message);
}
/**
* Constructs a new exception with the specified cause and a detail
* message of {@code (cause==null ? null : cause.toString())} (which
* typically contains the class and detail message of {@code cause}.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link Throwable#getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.7
*/
public ConcurrentModificationException(Throwable cause) {
super(cause);
}
/**
* Constructs a new exception with the specified detail message and
* cause.
*
* <p>Note that the detail message associated with <code>cause</code> is
* <i>not</i> automatically incorporated in this exception's detail
* message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link Throwable#getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link Throwable#getCause()} method). (A {@code null} value
* is permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.7
*/
public ConcurrentModificationException(String message, Throwable cause) {
super(message, cause);
}
}

View file

@ -0,0 +1,978 @@
/*
* Copyright (c) 2000, 2016, 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;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.IOException;
import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.spi.CurrencyNameProvider;
import sun.util.locale.provider.LocaleServiceProviderPool;
import sun.util.logging.PlatformLogger;
/**
* Represents a currency. Currencies are identified by their ISO 4217 currency
* codes. Visit the <a href="http://www.iso.org/iso/home/standards/currency_codes.htm">
* ISO web site</a> for more information.
* <p>
* The class is designed so that there's never more than one
* <code>Currency</code> instance for any given currency. Therefore, there's
* no public constructor. You obtain a <code>Currency</code> instance using
* the <code>getInstance</code> methods.
* <p>
* Users can supersede the Java runtime currency data by means of the system
* property {@code java.util.currency.data}. If this system property is
* defined then its value is the location of a properties file, the contents of
* which are key/value pairs of the ISO 3166 country codes and the ISO 4217
* currency data respectively. The value part consists of three ISO 4217 values
* of a currency, i.e., an alphabetic code, a numeric code, and a minor unit.
* Those three ISO 4217 values are separated by commas.
* The lines which start with '#'s are considered comment lines. An optional UTC
* timestamp may be specified per currency entry if users need to specify a
* cutover date indicating when the new data comes into effect. The timestamp is
* appended to the end of the currency properties and uses a comma as a separator.
* If a UTC datestamp is present and valid, the JRE will only use the new currency
* properties if the current UTC date is later than the date specified at class
* loading time. The format of the timestamp must be of ISO 8601 format :
* {@code 'yyyy-MM-dd'T'HH:mm:ss'}. For example,
* <p>
* <code>
* #Sample currency properties<br>
* JP=JPZ,999,0
* </code>
* <p>
* will supersede the currency data for Japan.
*
* <p>
* <code>
* #Sample currency properties with cutover date<br>
* JP=JPZ,999,0,2014-01-01T00:00:00
* </code>
* <p>
* will supersede the currency data for Japan if {@code Currency} class is loaded after
* 1st January 2014 00:00:00 GMT.
* <p>
* Where syntactically malformed entries are encountered, the entry is ignored
* and the remainder of entries in file are processed. For instances where duplicate
* country code entries exist, the behavior of the Currency information for that
* {@code Currency} is undefined and the remainder of entries in file are processed.
* <p>
* It is recommended to use {@link java.math.BigDecimal} class while dealing
* with {@code Currency} or monetary values as it provides better handling of floating
* point numbers and their operations.
*
* @see java.math.BigDecimal
* @since 1.4
*/
public final class Currency implements Serializable {
private static final long serialVersionUID = -158308464356906721L;
/**
* ISO 4217 currency code for this currency.
*
* @serial
*/
private final String currencyCode;
/**
* Default fraction digits for this currency.
* Set from currency data tables.
*/
private final transient int defaultFractionDigits;
/**
* ISO 4217 numeric code for this currency.
* Set from currency data tables.
*/
private final transient int numericCode;
// class data: instance map
private static ConcurrentMap<String, Currency> instances = new ConcurrentHashMap<>(7);
private static HashSet<Currency> available;
// Class data: currency data obtained from currency.data file.
// Purpose:
// - determine valid country codes
// - determine valid currency codes
// - map country codes to currency codes
// - obtain default fraction digits for currency codes
//
// sc = special case; dfd = default fraction digits
// Simple countries are those where the country code is a prefix of the
// currency code, and there are no known plans to change the currency.
//
// table formats:
// - mainTable:
// - maps country code to 32-bit int
// - 26*26 entries, corresponding to [A-Z]*[A-Z]
// - \u007F -> not valid country
// - bits 20-31: unused
// - bits 10-19: numeric code (0 to 1023)
// - bit 9: 1 - special case, bits 0-4 indicate which one
// 0 - simple country, bits 0-4 indicate final char of currency code
// - bits 5-8: fraction digits for simple countries, 0 for special cases
// - bits 0-4: final char for currency code for simple country, or ID of special case
// - special case IDs:
// - 0: country has no currency
// - other: index into specialCasesList
static int formatVersion;
static int dataVersion;
static int[] mainTable;
static List<SpecialCaseEntry> specialCasesList;
static List<OtherCurrencyEntry> otherCurrenciesList;
// handy constants - must match definitions in GenerateCurrencyData
// magic number
private static final int MAGIC_NUMBER = 0x43757244;
// number of characters from A to Z
private static final int A_TO_Z = ('Z' - 'A') + 1;
// entry for invalid country codes
private static final int INVALID_COUNTRY_ENTRY = 0x0000007F;
// entry for countries without currency
private static final int COUNTRY_WITHOUT_CURRENCY_ENTRY = 0x00000200;
// mask for simple case country entries
private static final int SIMPLE_CASE_COUNTRY_MASK = 0x00000000;
// mask for simple case country entry final character
private static final int SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK = 0x0000001F;
// mask for simple case country entry default currency digits
private static final int SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK = 0x000001E0;
// shift count for simple case country entry default currency digits
private static final int SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT = 5;
// maximum number for simple case country entry default currency digits
private static final int SIMPLE_CASE_COUNTRY_MAX_DEFAULT_DIGITS = 9;
// mask for special case country entries
private static final int SPECIAL_CASE_COUNTRY_MASK = 0x00000200;
// mask for special case country index
private static final int SPECIAL_CASE_COUNTRY_INDEX_MASK = 0x0000001F;
// delta from entry index component in main table to index into special case tables
private static final int SPECIAL_CASE_COUNTRY_INDEX_DELTA = 1;
// mask for distinguishing simple and special case countries
private static final int COUNTRY_TYPE_MASK = SIMPLE_CASE_COUNTRY_MASK | SPECIAL_CASE_COUNTRY_MASK;
// mask for the numeric code of the currency
private static final int NUMERIC_CODE_MASK = 0x000FFC00;
// shift count for the numeric code of the currency
private static final int NUMERIC_CODE_SHIFT = 10;
// Currency data format version
private static final int VALID_FORMAT_VERSION = 3;
static {
AccessController.doPrivileged(new PrivilegedAction<>() {
@Override
public Void run() {
try {
try (InputStream in = getClass().getResourceAsStream("/java/util/currency.data")) {
if (in == null) {
throw new InternalError("Currency data not found");
}
DataInputStream dis = new DataInputStream(new BufferedInputStream(in));
if (dis.readInt() != MAGIC_NUMBER) {
throw new InternalError("Currency data is possibly corrupted");
}
formatVersion = dis.readInt();
if (formatVersion != VALID_FORMAT_VERSION) {
throw new InternalError("Currency data format is incorrect");
}
dataVersion = dis.readInt();
mainTable = readIntArray(dis, A_TO_Z * A_TO_Z);
int scCount = dis.readInt();
specialCasesList = readSpecialCases(dis, scCount);
int ocCount = dis.readInt();
otherCurrenciesList = readOtherCurrencies(dis, ocCount);
}
} catch (IOException e) {
throw new InternalError(e);
}
// look for the properties file for overrides
String propsFile = System.getProperty("java.util.currency.data");
if (propsFile == null) {
propsFile = System.getProperty("java.home") + File.separator + "lib" +
File.separator + "currency.properties";
}
try {
File propFile = new File(propsFile);
if (propFile.exists()) {
Properties props = new Properties();
try (FileReader fr = new FileReader(propFile)) {
props.load(fr);
}
Set<String> keys = props.stringPropertyNames();
Pattern propertiesPattern =
Pattern.compile("([A-Z]{3})\\s*,\\s*(\\d{3})\\s*,\\s*" +
"(\\d+)\\s*,?\\s*(\\d{4}-\\d{2}-\\d{2}T\\d{2}:" +
"\\d{2}:\\d{2})?");
for (String key : keys) {
replaceCurrencyData(propertiesPattern,
key.toUpperCase(Locale.ROOT),
props.getProperty(key).toUpperCase(Locale.ROOT));
}
}
} catch (IOException e) {
info("currency.properties is ignored because of an IOException", e);
}
return null;
}
});
}
/**
* Constants for retrieving localized names from the name providers.
*/
private static final int SYMBOL = 0;
private static final int DISPLAYNAME = 1;
/**
* Constructs a <code>Currency</code> instance. The constructor is private
* so that we can insure that there's never more than one instance for a
* given currency.
*/
private Currency(String currencyCode, int defaultFractionDigits, int numericCode) {
this.currencyCode = currencyCode;
this.defaultFractionDigits = defaultFractionDigits;
this.numericCode = numericCode;
}
/**
* Returns the <code>Currency</code> instance for the given currency code.
*
* @param currencyCode the ISO 4217 code of the currency
* @return the <code>Currency</code> instance for the given currency code
* @exception NullPointerException if <code>currencyCode</code> is null
* @exception IllegalArgumentException if <code>currencyCode</code> is not
* a supported ISO 4217 code.
*/
public static Currency getInstance(String currencyCode) {
return getInstance(currencyCode, Integer.MIN_VALUE, 0);
}
private static Currency getInstance(String currencyCode, int defaultFractionDigits,
int numericCode) {
// Try to look up the currency code in the instances table.
// This does the null pointer check as a side effect.
// Also, if there already is an entry, the currencyCode must be valid.
Currency instance = instances.get(currencyCode);
if (instance != null) {
return instance;
}
if (defaultFractionDigits == Integer.MIN_VALUE) {
// Currency code not internally generated, need to verify first
// A currency code must have 3 characters and exist in the main table
// or in the list of other currencies.
boolean found = false;
if (currencyCode.length() != 3) {
throw new IllegalArgumentException();
}
char char1 = currencyCode.charAt(0);
char char2 = currencyCode.charAt(1);
int tableEntry = getMainTableEntry(char1, char2);
if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK
&& tableEntry != INVALID_COUNTRY_ENTRY
&& currencyCode.charAt(2) - 'A' == (tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK)) {
defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT;
found = true;
} else { //special case
int[] fractionAndNumericCode = SpecialCaseEntry.findEntry(currencyCode);
if (fractionAndNumericCode != null) {
defaultFractionDigits = fractionAndNumericCode[0];
numericCode = fractionAndNumericCode[1];
found = true;
}
}
if (!found) {
OtherCurrencyEntry ocEntry = OtherCurrencyEntry.findEntry(currencyCode);
if (ocEntry == null) {
throw new IllegalArgumentException();
}
defaultFractionDigits = ocEntry.fraction;
numericCode = ocEntry.numericCode;
}
}
Currency currencyVal =
new Currency(currencyCode, defaultFractionDigits, numericCode);
instance = instances.putIfAbsent(currencyCode, currencyVal);
return (instance != null ? instance : currencyVal);
}
/**
* Returns the <code>Currency</code> instance for the country of the
* given locale. The language and variant components of the locale
* are ignored. The result may vary over time, as countries change their
* currencies. For example, for the original member countries of the
* European Monetary Union, the method returns the old national currencies
* until December 31, 2001, and the Euro from January 1, 2002, local time
* of the respective countries.
* <p>
* The method returns <code>null</code> for territories that don't
* have a currency, such as Antarctica.
*
* @param locale the locale for whose country a <code>Currency</code>
* instance is needed
* @return the <code>Currency</code> instance for the country of the given
* locale, or {@code null}
* @exception NullPointerException if <code>locale</code>
* is {@code null}
* @exception IllegalArgumentException if the country of the given {@code locale}
* is not a supported ISO 3166 country code.
*/
public static Currency getInstance(Locale locale) {
String country = locale.getCountry();
if (country == null) {
throw new NullPointerException();
}
if (country.length() != 2) {
throw new IllegalArgumentException();
}
char char1 = country.charAt(0);
char char2 = country.charAt(1);
int tableEntry = getMainTableEntry(char1, char2);
if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK
&& tableEntry != INVALID_COUNTRY_ENTRY) {
char finalChar = (char) ((tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK) + 'A');
int defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
int numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT;
StringBuilder sb = new StringBuilder(country);
sb.append(finalChar);
return getInstance(sb.toString(), defaultFractionDigits, numericCode);
} else {
// special cases
if (tableEntry == INVALID_COUNTRY_ENTRY) {
throw new IllegalArgumentException();
}
if (tableEntry == COUNTRY_WITHOUT_CURRENCY_ENTRY) {
return null;
} else {
int index = SpecialCaseEntry.toIndex(tableEntry);
SpecialCaseEntry scEntry = specialCasesList.get(index);
if (scEntry.cutOverTime == Long.MAX_VALUE
|| System.currentTimeMillis() < scEntry.cutOverTime) {
return getInstance(scEntry.oldCurrency,
scEntry.oldCurrencyFraction,
scEntry.oldCurrencyNumericCode);
} else {
return getInstance(scEntry.newCurrency,
scEntry.newCurrencyFraction,
scEntry.newCurrencyNumericCode);
}
}
}
}
/**
* Gets the set of available currencies. The returned set of currencies
* contains all of the available currencies, which may include currencies
* that represent obsolete ISO 4217 codes. The set can be modified
* without affecting the available currencies in the runtime.
*
* @return the set of available currencies. If there is no currency
* available in the runtime, the returned set is empty.
* @since 1.7
*/
public static Set<Currency> getAvailableCurrencies() {
synchronized(Currency.class) {
if (available == null) {
available = new HashSet<>(256);
// Add simple currencies first
for (char c1 = 'A'; c1 <= 'Z'; c1 ++) {
for (char c2 = 'A'; c2 <= 'Z'; c2 ++) {
int tableEntry = getMainTableEntry(c1, c2);
if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK
&& tableEntry != INVALID_COUNTRY_ENTRY) {
char finalChar = (char) ((tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK) + 'A');
int defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
int numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT;
StringBuilder sb = new StringBuilder();
sb.append(c1);
sb.append(c2);
sb.append(finalChar);
available.add(getInstance(sb.toString(), defaultFractionDigits, numericCode));
} else if ((tableEntry & COUNTRY_TYPE_MASK) == SPECIAL_CASE_COUNTRY_MASK
&& tableEntry != INVALID_COUNTRY_ENTRY
&& tableEntry != COUNTRY_WITHOUT_CURRENCY_ENTRY) {
int index = SpecialCaseEntry.toIndex(tableEntry);
SpecialCaseEntry scEntry = specialCasesList.get(index);
if (scEntry.cutOverTime == Long.MAX_VALUE
|| System.currentTimeMillis() < scEntry.cutOverTime) {
available.add(getInstance(scEntry.oldCurrency,
scEntry.oldCurrencyFraction,
scEntry.oldCurrencyNumericCode));
} else {
available.add(getInstance(scEntry.newCurrency,
scEntry.newCurrencyFraction,
scEntry.newCurrencyNumericCode));
}
}
}
}
// Now add other currencies
for (OtherCurrencyEntry entry : otherCurrenciesList) {
available.add(getInstance(entry.currencyCode));
}
}
}
@SuppressWarnings("unchecked")
Set<Currency> result = (Set<Currency>) available.clone();
return result;
}
/**
* Gets the ISO 4217 currency code of this currency.
*
* @return the ISO 4217 currency code of this currency.
*/
public String getCurrencyCode() {
return currencyCode;
}
/**
* Gets the symbol of this currency for the default
* {@link Locale.Category#DISPLAY DISPLAY} locale.
* For example, for the US Dollar, the symbol is "$" if the default
* locale is the US, while for other locales it may be "US$". If no
* symbol can be determined, the ISO 4217 currency code is returned.
* <p>
* This is equivalent to calling
* {@link #getSymbol(Locale)
* getSymbol(Locale.getDefault(Locale.Category.DISPLAY))}.
*
* @return the symbol of this currency for the default
* {@link Locale.Category#DISPLAY DISPLAY} locale
*/
public String getSymbol() {
return getSymbol(Locale.getDefault(Locale.Category.DISPLAY));
}
/**
* Gets the symbol of this currency for the specified locale.
* For example, for the US Dollar, the symbol is "$" if the specified
* locale is the US, while for other locales it may be "US$". If no
* symbol can be determined, the ISO 4217 currency code is returned.
*
* @param locale the locale for which a display name for this currency is
* needed
* @return the symbol of this currency for the specified locale
* @exception NullPointerException if <code>locale</code> is null
*/
public String getSymbol(Locale locale) {
LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(CurrencyNameProvider.class);
String symbol = pool.getLocalizedObject(
CurrencyNameGetter.INSTANCE,
locale, currencyCode, SYMBOL);
if (symbol != null) {
return symbol;
}
// use currency code as symbol of last resort
return currencyCode;
}
/**
* Gets the default number of fraction digits used with this currency.
* Note that the number of fraction digits is the same as ISO 4217's
* minor unit for the currency.
* For example, the default number of fraction digits for the Euro is 2,
* while for the Japanese Yen it's 0.
* In the case of pseudo-currencies, such as IMF Special Drawing Rights,
* -1 is returned.
*
* @return the default number of fraction digits used with this currency
*/
public int getDefaultFractionDigits() {
return defaultFractionDigits;
}
/**
* Returns the ISO 4217 numeric code of this currency.
*
* @return the ISO 4217 numeric code of this currency
* @since 1.7
*/
public int getNumericCode() {
return numericCode;
}
/**
* Returns the 3 digit ISO 4217 numeric code of this currency as a {@code String}.
* Unlike {@link getNumericCode()}, which returns the numeric code as {@code int},
* this method always returns the numeric code as a 3 digit string.
* e.g. a numeric value of 32 would be returned as "032",
* and a numeric value of 6 would be returned as "006".
*
* @return the 3 digit ISO 4217 numeric code of this currency as a {@code String}
* @since 9
*/
public String getNumericCodeAsString() {
/* numeric code could be returned as a 3 digit string simply by using
String.format("%03d",numericCode); which uses regex to parse the format,
"%03d" in this case. Parsing a regex gives an extra performance overhead,
so String.format() approach is avoided in this scenario.
*/
if (numericCode < 100) {
StringBuilder sb = new StringBuilder();
sb.append('0');
if (numericCode < 10) {
sb.append('0');
}
return sb.append(numericCode).toString();
}
return String.valueOf(numericCode);
}
/**
* Gets the name that is suitable for displaying this currency for
* the default {@link Locale.Category#DISPLAY DISPLAY} locale.
* If there is no suitable display name found
* for the default locale, the ISO 4217 currency code is returned.
* <p>
* This is equivalent to calling
* {@link #getDisplayName(Locale)
* getDisplayName(Locale.getDefault(Locale.Category.DISPLAY))}.
*
* @return the display name of this currency for the default
* {@link Locale.Category#DISPLAY DISPLAY} locale
* @since 1.7
*/
public String getDisplayName() {
return getDisplayName(Locale.getDefault(Locale.Category.DISPLAY));
}
/**
* Gets the name that is suitable for displaying this currency for
* the specified locale. If there is no suitable display name found
* for the specified locale, the ISO 4217 currency code is returned.
*
* @param locale the locale for which a display name for this currency is
* needed
* @return the display name of this currency for the specified locale
* @exception NullPointerException if <code>locale</code> is null
* @since 1.7
*/
public String getDisplayName(Locale locale) {
LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(CurrencyNameProvider.class);
String result = pool.getLocalizedObject(
CurrencyNameGetter.INSTANCE,
locale, currencyCode, DISPLAYNAME);
if (result != null) {
return result;
}
// use currency code as symbol of last resort
return currencyCode;
}
/**
* Returns the ISO 4217 currency code of this currency.
*
* @return the ISO 4217 currency code of this currency
*/
@Override
public String toString() {
return currencyCode;
}
/**
* Resolves instances being deserialized to a single instance per currency.
*/
private Object readResolve() {
return getInstance(currencyCode);
}
/**
* Gets the main table entry for the country whose country code consists
* of char1 and char2.
*/
private static int getMainTableEntry(char char1, char char2) {
if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') {
throw new IllegalArgumentException();
}
return mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')];
}
/**
* Sets the main table entry for the country whose country code consists
* of char1 and char2.
*/
private static void setMainTableEntry(char char1, char char2, int entry) {
if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') {
throw new IllegalArgumentException();
}
mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')] = entry;
}
/**
* Obtains a localized currency names from a CurrencyNameProvider
* implementation.
*/
private static class CurrencyNameGetter
implements LocaleServiceProviderPool.LocalizedObjectGetter<CurrencyNameProvider,
String> {
private static final CurrencyNameGetter INSTANCE = new CurrencyNameGetter();
@Override
public String getObject(CurrencyNameProvider currencyNameProvider,
Locale locale,
String key,
Object... params) {
assert params.length == 1;
int type = (Integer)params[0];
switch(type) {
case SYMBOL:
return currencyNameProvider.getSymbol(key, locale);
case DISPLAYNAME:
return currencyNameProvider.getDisplayName(key, locale);
default:
assert false; // shouldn't happen
}
return null;
}
}
private static int[] readIntArray(DataInputStream dis, int count) throws IOException {
int[] ret = new int[count];
for (int i = 0; i < count; i++) {
ret[i] = dis.readInt();
}
return ret;
}
private static List<SpecialCaseEntry> readSpecialCases(DataInputStream dis,
int count)
throws IOException {
List<SpecialCaseEntry> list = new ArrayList<>(count);
long cutOverTime;
String oldCurrency;
String newCurrency;
int oldCurrencyFraction;
int newCurrencyFraction;
int oldCurrencyNumericCode;
int newCurrencyNumericCode;
for (int i = 0; i < count; i++) {
cutOverTime = dis.readLong();
oldCurrency = dis.readUTF();
newCurrency = dis.readUTF();
oldCurrencyFraction = dis.readInt();
newCurrencyFraction = dis.readInt();
oldCurrencyNumericCode = dis.readInt();
newCurrencyNumericCode = dis.readInt();
SpecialCaseEntry sc = new SpecialCaseEntry(cutOverTime,
oldCurrency, newCurrency,
oldCurrencyFraction, newCurrencyFraction,
oldCurrencyNumericCode, newCurrencyNumericCode);
list.add(sc);
}
return list;
}
private static List<OtherCurrencyEntry> readOtherCurrencies(DataInputStream dis,
int count)
throws IOException {
List<OtherCurrencyEntry> list = new ArrayList<>(count);
String currencyCode;
int fraction;
int numericCode;
for (int i = 0; i < count; i++) {
currencyCode = dis.readUTF();
fraction = dis.readInt();
numericCode = dis.readInt();
OtherCurrencyEntry oc = new OtherCurrencyEntry(currencyCode,
fraction,
numericCode);
list.add(oc);
}
return list;
}
/**
* Replaces currency data found in the currencydata.properties file
*
* @param pattern regex pattern for the properties
* @param ctry country code
* @param curdata currency data. This is a comma separated string that
* consists of "three-letter alphabet code", "three-digit numeric code",
* and "one-digit (0-9) default fraction digit".
* For example, "JPZ,392,0".
* An optional UTC date can be appended to the string (comma separated)
* to allow a currency change take effect after date specified.
* For example, "JP=JPZ,999,0,2014-01-01T00:00:00" has no effect unless
* UTC time is past 1st January 2014 00:00:00 GMT.
*/
private static void replaceCurrencyData(Pattern pattern, String ctry, String curdata) {
if (ctry.length() != 2) {
// ignore invalid country code
info("currency.properties entry for " + ctry +
" is ignored because of the invalid country code.", null);
return;
}
Matcher m = pattern.matcher(curdata);
if (!m.find() || (m.group(4) == null && countOccurrences(curdata, ',') >= 3)) {
// format is not recognized. ignore the data
// if group(4) date string is null and we've 4 values, bad date value
info("currency.properties entry for " + ctry +
" ignored because the value format is not recognized.", null);
return;
}
try {
if (m.group(4) != null && !isPastCutoverDate(m.group(4))) {
info("currency.properties entry for " + ctry +
" ignored since cutover date has not passed :" + curdata, null);
return;
}
} catch (ParseException ex) {
info("currency.properties entry for " + ctry +
" ignored since exception encountered :" + ex.getMessage(), null);
return;
}
String code = m.group(1);
int numeric = Integer.parseInt(m.group(2));
int entry = numeric << NUMERIC_CODE_SHIFT;
int fraction = Integer.parseInt(m.group(3));
if (fraction > SIMPLE_CASE_COUNTRY_MAX_DEFAULT_DIGITS) {
info("currency.properties entry for " + ctry +
" ignored since the fraction is more than " +
SIMPLE_CASE_COUNTRY_MAX_DEFAULT_DIGITS + ":" + curdata, null);
return;
}
int index = SpecialCaseEntry.indexOf(code, fraction, numeric);
/* if a country switches from simple case to special case or
* one special case to other special case which is not present
* in the sc arrays then insert the new entry in special case arrays
*/
if (index == -1 && (ctry.charAt(0) != code.charAt(0)
|| ctry.charAt(1) != code.charAt(1))) {
specialCasesList.add(new SpecialCaseEntry(code, fraction, numeric));
index = specialCasesList.size() - 1;
}
if (index == -1) {
// simple case
entry |= (fraction << SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT)
| (code.charAt(2) - 'A');
} else {
// special case
entry = SPECIAL_CASE_COUNTRY_MASK
| (index + SPECIAL_CASE_COUNTRY_INDEX_DELTA);
}
setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry);
}
private static boolean isPastCutoverDate(String s) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ROOT);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
format.setLenient(false);
long time = format.parse(s.trim()).getTime();
return System.currentTimeMillis() > time;
}
private static int countOccurrences(String value, char match) {
int count = 0;
for (char c : value.toCharArray()) {
if (c == match) {
++count;
}
}
return count;
}
private static void info(String message, Throwable t) {
PlatformLogger logger = PlatformLogger.getLogger("java.util.Currency");
if (logger.isLoggable(PlatformLogger.Level.INFO)) {
if (t != null) {
logger.info(message, t);
} else {
logger.info(message);
}
}
}
/* Used to represent a special case currency entry
* - cutOverTime: cut-over time in millis as returned by
* System.currentTimeMillis for special case countries that are changing
* currencies; Long.MAX_VALUE for countries that are not changing currencies
* - oldCurrency: old currencies for special case countries
* - newCurrency: new currencies for special case countries that are
* changing currencies; null for others
* - oldCurrencyFraction: default fraction digits for old currencies
* - newCurrencyFraction: default fraction digits for new currencies, 0 for
* countries that are not changing currencies
* - oldCurrencyNumericCode: numeric code for old currencies
* - newCurrencyNumericCode: numeric code for new currencies, 0 for countries
* that are not changing currencies
*/
private static class SpecialCaseEntry {
final private long cutOverTime;
final private String oldCurrency;
final private String newCurrency;
final private int oldCurrencyFraction;
final private int newCurrencyFraction;
final private int oldCurrencyNumericCode;
final private int newCurrencyNumericCode;
private SpecialCaseEntry(long cutOverTime, String oldCurrency, String newCurrency,
int oldCurrencyFraction, int newCurrencyFraction,
int oldCurrencyNumericCode, int newCurrencyNumericCode) {
this.cutOverTime = cutOverTime;
this.oldCurrency = oldCurrency;
this.newCurrency = newCurrency;
this.oldCurrencyFraction = oldCurrencyFraction;
this.newCurrencyFraction = newCurrencyFraction;
this.oldCurrencyNumericCode = oldCurrencyNumericCode;
this.newCurrencyNumericCode = newCurrencyNumericCode;
}
private SpecialCaseEntry(String currencyCode, int fraction,
int numericCode) {
this(Long.MAX_VALUE, currencyCode, "", fraction, 0, numericCode, 0);
}
//get the index of the special case entry
private static int indexOf(String code, int fraction, int numeric) {
int size = specialCasesList.size();
for (int index = 0; index < size; index++) {
SpecialCaseEntry scEntry = specialCasesList.get(index);
if (scEntry.oldCurrency.equals(code)
&& scEntry.oldCurrencyFraction == fraction
&& scEntry.oldCurrencyNumericCode == numeric
&& scEntry.cutOverTime == Long.MAX_VALUE) {
return index;
}
}
return -1;
}
// get the fraction and numericCode of the sc currencycode
private static int[] findEntry(String code) {
int[] fractionAndNumericCode = null;
int size = specialCasesList.size();
for (int index = 0; index < size; index++) {
SpecialCaseEntry scEntry = specialCasesList.get(index);
if (scEntry.oldCurrency.equals(code) && (scEntry.cutOverTime == Long.MAX_VALUE
|| System.currentTimeMillis() < scEntry.cutOverTime)) {
//consider only when there is no new currency or cutover time is not passed
fractionAndNumericCode = new int[2];
fractionAndNumericCode[0] = scEntry.oldCurrencyFraction;
fractionAndNumericCode[1] = scEntry.oldCurrencyNumericCode;
break;
} else if (scEntry.newCurrency.equals(code)
&& System.currentTimeMillis() >= scEntry.cutOverTime) {
//consider only if the cutover time is passed
fractionAndNumericCode = new int[2];
fractionAndNumericCode[0] = scEntry.newCurrencyFraction;
fractionAndNumericCode[1] = scEntry.newCurrencyNumericCode;
break;
}
}
return fractionAndNumericCode;
}
// convert the special case entry to sc arrays index
private static int toIndex(int tableEntry) {
return (tableEntry & SPECIAL_CASE_COUNTRY_INDEX_MASK) - SPECIAL_CASE_COUNTRY_INDEX_DELTA;
}
}
/* Used to represent Other currencies
* - currencyCode: currency codes that are not the main currency
* of a simple country
* - otherCurrenciesDFD: decimal format digits for other currencies
* - otherCurrenciesNumericCode: numeric code for other currencies
*/
private static class OtherCurrencyEntry {
final private String currencyCode;
final private int fraction;
final private int numericCode;
private OtherCurrencyEntry(String currencyCode, int fraction,
int numericCode) {
this.currencyCode = currencyCode;
this.fraction = fraction;
this.numericCode = numericCode;
}
//get the instance of the other currency code
private static OtherCurrencyEntry findEntry(String code) {
int size = otherCurrenciesList.size();
for (int index = 0; index < size; index++) {
OtherCurrencyEntry ocEntry = otherCurrenciesList.get(index);
if (ocEntry.currencyCode.equalsIgnoreCase(code)) {
return ocEntry;
}
}
return null;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,616 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Written by Doug Lea and Josh Bloch with assistance from members of
* JCP JSR-166 Expert Group and released to the public domain, as explained
* at http://creativecommons.org/publicdomain/zero/1.0/
*/
package java.util;
/**
* A linear collection that supports element insertion and removal at
* both ends. The name <i>deque</i> is short for "double ended queue"
* and is usually pronounced "deck". Most {@code Deque}
* implementations place no fixed limits on the number of elements
* they may contain, but this interface supports capacity-restricted
* deques as well as those with no fixed size limit.
*
* <p>This interface defines methods to access the elements at both
* ends of the deque. Methods are provided to insert, remove, and
* examine the element. Each of these methods exists in two forms:
* one throws an exception if the operation fails, the other returns a
* special value (either {@code null} or {@code false}, depending on
* the operation). The latter form of the insert operation is
* designed specifically for use with capacity-restricted
* {@code Deque} implementations; in most implementations, insert
* operations cannot fail.
*
* <p>The twelve methods described above are summarized in the
* following table:
*
* <table class="striped">
* <caption>Summary of Deque methods</caption>
* <thead>
* <tr>
* <td rowspan="2"></td>
* <th scope="col" colspan="2"> First Element (Head)</th>
* <th scope="col" colspan="2"> Last Element (Tail)</th>
* </tr>
* <tr>
* <th scope="col" style="font-weight:normal; font-style:italic">Throws exception</th>
* <th scope="col" style="font-weight:normal; font-style:italic">Special value</th>
* <th scope="col" style="font-weight:normal; font-style:italic">Throws exception</th>
* <th scope="col" style="font-weight:normal; font-style:italic">Special value</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th scope="row">Insert</th>
* <td>{@link #addFirst(Object) addFirst(e)}</td>
* <td>{@link #offerFirst(Object) offerFirst(e)}</td>
* <td>{@link #addLast(Object) addLast(e)}</td>
* <td>{@link #offerLast(Object) offerLast(e)}</td>
* </tr>
* <tr>
* <th scope="row">Remove</th>
* <td>{@link #removeFirst() removeFirst()}</td>
* <td>{@link #pollFirst() pollFirst()}</td>
* <td>{@link #removeLast() removeLast()}</td>
* <td>{@link #pollLast() pollLast()}</td>
* </tr>
* <tr>
* <th scope="row">Examine</th>
* <td>{@link #getFirst() getFirst()}</td>
* <td>{@link #peekFirst() peekFirst()}</td>
* <td>{@link #getLast() getLast()}</td>
* <td>{@link #peekLast() peekLast()}</td>
* </tr>
* </tbody>
* </table>
*
* <p>This interface extends the {@link Queue} interface. When a deque is
* used as a queue, FIFO (First-In-First-Out) behavior results. Elements are
* added at the end of the deque and removed from the beginning. The methods
* inherited from the {@code Queue} interface are precisely equivalent to
* {@code Deque} methods as indicated in the following table:
*
* <table class="striped">
* <caption>Comparison of Queue and Deque methods</caption>
* <thead>
* <tr>
* <th scope="col"> {@code Queue} Method</th>
* <th scope="col"> Equivalent {@code Deque} Method</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th scope="row">{@link #add(Object) add(e)}</th>
* <td>{@link #addLast(Object) addLast(e)}</td>
* </tr>
* <tr>
* <th scope="row">{@link #offer(Object) offer(e)}</th>
* <td>{@link #offerLast(Object) offerLast(e)}</td>
* </tr>
* <tr>
* <th scope="row">{@link #remove() remove()}</th>
* <td>{@link #removeFirst() removeFirst()}</td>
* </tr>
* <tr>
* <th scope="row">{@link #poll() poll()}</th>
* <td>{@link #pollFirst() pollFirst()}</td>
* </tr>
* <tr>
* <th scope="row">{@link #element() element()}</th>
* <td>{@link #getFirst() getFirst()}</td>
* </tr>
* <tr>
* <th scope="row">{@link #peek() peek()}</th>
* <td>{@link #peekFirst() peekFirst()}</td>
* </tr>
* </tbody>
* </table>
*
* <p>Deques can also be used as LIFO (Last-In-First-Out) stacks. This
* interface should be used in preference to the legacy {@link Stack} class.
* When a deque is used as a stack, elements are pushed and popped from the
* beginning of the deque. Stack methods are precisely equivalent to
* {@code Deque} methods as indicated in the table below:
*
* <table class="striped">
* <caption>Comparison of Stack and Deque methods</caption>
* <thead>
* <tr>
* <th scope="col"> Stack Method</th>
* <th scope="col"> Equivalent {@code Deque} Method</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th scope="row">{@link #push(Object) push(e)}</th>
* <td>{@link #addFirst(Object) addFirst(e)}</td>
* </tr>
* <tr>
* <th scope="row">{@link #pop() pop()}</th>
* <td>{@link #removeFirst() removeFirst()}</td>
* </tr>
* <tr>
* <th scope="row">{@link #peek() peek()}</th>
* <td>{@link #peekFirst() peekFirst()}</td>
* </tr>
* </tbody>
* </table>
*
* <p>Note that the {@link #peek peek} method works equally well when
* a deque is used as a queue or a stack; in either case, elements are
* drawn from the beginning of the deque.
*
* <p>This interface provides two methods to remove interior
* elements, {@link #removeFirstOccurrence removeFirstOccurrence} and
* {@link #removeLastOccurrence removeLastOccurrence}.
*
* <p>Unlike the {@link List} interface, this interface does not
* provide support for indexed access to elements.
*
* <p>While {@code Deque} implementations are not strictly required
* to prohibit the insertion of null elements, they are strongly
* encouraged to do so. Users of any {@code Deque} implementations
* that do allow null elements are strongly encouraged <i>not</i> to
* take advantage of the ability to insert nulls. This is so because
* {@code null} is used as a special return value by various methods
* to indicate that the deque is empty.
*
* <p>{@code Deque} implementations generally do not define
* element-based versions of the {@code equals} and {@code hashCode}
* methods, but instead inherit the identity-based versions from class
* {@code Object}.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Doug Lea
* @author Josh Bloch
* @since 1.6
* @param <E> the type of elements held in this deque
*/
public interface Deque<E> extends Queue<E> {
/**
* Inserts the specified element at the front of this deque if it is
* possible to do so immediately without violating capacity restrictions,
* throwing an {@code IllegalStateException} if no space is currently
* available. When using a capacity-restricted deque, it is generally
* preferable to use method {@link #offerFirst}.
*
* @param e the element to add
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
void addFirst(E e);
/**
* Inserts the specified element at the end of this deque if it is
* possible to do so immediately without violating capacity restrictions,
* throwing an {@code IllegalStateException} if no space is currently
* available. When using a capacity-restricted deque, it is generally
* preferable to use method {@link #offerLast}.
*
* <p>This method is equivalent to {@link #add}.
*
* @param e the element to add
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
void addLast(E e);
/**
* Inserts the specified element at the front of this deque unless it would
* violate capacity restrictions. When using a capacity-restricted deque,
* this method is generally preferable to the {@link #addFirst} method,
* which can fail to insert an element only by throwing an exception.
*
* @param e the element to add
* @return {@code true} if the element was added to this deque, else
* {@code false}
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
boolean offerFirst(E e);
/**
* Inserts the specified element at the end of this deque unless it would
* violate capacity restrictions. When using a capacity-restricted deque,
* this method is generally preferable to the {@link #addLast} method,
* which can fail to insert an element only by throwing an exception.
*
* @param e the element to add
* @return {@code true} if the element was added to this deque, else
* {@code false}
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
boolean offerLast(E e);
/**
* Retrieves and removes the first element of this deque. This method
* differs from {@link #pollFirst pollFirst} only in that it throws an
* exception if this deque is empty.
*
* @return the head of this deque
* @throws NoSuchElementException if this deque is empty
*/
E removeFirst();
/**
* Retrieves and removes the last element of this deque. This method
* differs from {@link #pollLast pollLast} only in that it throws an
* exception if this deque is empty.
*
* @return the tail of this deque
* @throws NoSuchElementException if this deque is empty
*/
E removeLast();
/**
* Retrieves and removes the first element of this deque,
* or returns {@code null} if this deque is empty.
*
* @return the head of this deque, or {@code null} if this deque is empty
*/
E pollFirst();
/**
* Retrieves and removes the last element of this deque,
* or returns {@code null} if this deque is empty.
*
* @return the tail of this deque, or {@code null} if this deque is empty
*/
E pollLast();
/**
* Retrieves, but does not remove, the first element of this deque.
*
* This method differs from {@link #peekFirst peekFirst} only in that it
* throws an exception if this deque is empty.
*
* @return the head of this deque
* @throws NoSuchElementException if this deque is empty
*/
E getFirst();
/**
* Retrieves, but does not remove, the last element of this deque.
* This method differs from {@link #peekLast peekLast} only in that it
* throws an exception if this deque is empty.
*
* @return the tail of this deque
* @throws NoSuchElementException if this deque is empty
*/
E getLast();
/**
* Retrieves, but does not remove, the first element of this deque,
* or returns {@code null} if this deque is empty.
*
* @return the head of this deque, or {@code null} if this deque is empty
*/
E peekFirst();
/**
* Retrieves, but does not remove, the last element of this deque,
* or returns {@code null} if this deque is empty.
*
* @return the tail of this deque, or {@code null} if this deque is empty
*/
E peekLast();
/**
* Removes the first occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
* More formally, removes the first element {@code e} such that
* {@code Objects.equals(o, e)} (if such an element exists).
* Returns {@code true} if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* @param o element to be removed from this deque, if present
* @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean removeFirstOccurrence(Object o);
/**
* Removes the last occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
* More formally, removes the last element {@code e} such that
* {@code Objects.equals(o, e)} (if such an element exists).
* Returns {@code true} if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* @param o element to be removed from this deque, if present
* @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean removeLastOccurrence(Object o);
// *** Queue methods ***
/**
* Inserts the specified element into the queue represented by this deque
* (in other words, at the tail of this deque) if it is possible to do so
* immediately without violating capacity restrictions, returning
* {@code true} upon success and throwing an
* {@code IllegalStateException} if no space is currently available.
* When using a capacity-restricted deque, it is generally preferable to
* use {@link #offer(Object) offer}.
*
* <p>This method is equivalent to {@link #addLast}.
*
* @param e the element to add
* @return {@code true} (as specified by {@link Collection#add})
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
boolean add(E e);
/**
* Inserts the specified element into the queue represented by this deque
* (in other words, at the tail of this deque) if it is possible to do so
* immediately without violating capacity restrictions, returning
* {@code true} upon success and {@code false} if no space is currently
* available. When using a capacity-restricted deque, this method is
* generally preferable to the {@link #add} method, which can fail to
* insert an element only by throwing an exception.
*
* <p>This method is equivalent to {@link #offerLast}.
*
* @param e the element to add
* @return {@code true} if the element was added to this deque, else
* {@code false}
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
boolean offer(E e);
/**
* Retrieves and removes the head of the queue represented by this deque
* (in other words, the first element of this deque).
* This method differs from {@link #poll() poll()} only in that it
* throws an exception if this deque is empty.
*
* <p>This method is equivalent to {@link #removeFirst()}.
*
* @return the head of the queue represented by this deque
* @throws NoSuchElementException if this deque is empty
*/
E remove();
/**
* Retrieves and removes the head of the queue represented by this deque
* (in other words, the first element of this deque), or returns
* {@code null} if this deque is empty.
*
* <p>This method is equivalent to {@link #pollFirst()}.
*
* @return the first element of this deque, or {@code null} if
* this deque is empty
*/
E poll();
/**
* Retrieves, but does not remove, the head of the queue represented by
* this deque (in other words, the first element of this deque).
* This method differs from {@link #peek peek} only in that it throws an
* exception if this deque is empty.
*
* <p>This method is equivalent to {@link #getFirst()}.
*
* @return the head of the queue represented by this deque
* @throws NoSuchElementException if this deque is empty
*/
E element();
/**
* Retrieves, but does not remove, the head of the queue represented by
* this deque (in other words, the first element of this deque), or
* returns {@code null} if this deque is empty.
*
* <p>This method is equivalent to {@link #peekFirst()}.
*
* @return the head of the queue represented by this deque, or
* {@code null} if this deque is empty
*/
E peek();
/**
* Adds all of the elements in the specified collection at the end
* of this deque, as if by calling {@link #addLast} on each one,
* in the order that they are returned by the collection's iterator.
*
* <p>When using a capacity-restricted deque, it is generally preferable
* to call {@link #offer(Object) offer} separately on each element.
*
* <p>An exception encountered while trying to add an element may result
* in only some of the elements having been successfully added when
* the associated exception is thrown.
*
* @param c the elements to be inserted into this deque
* @return {@code true} if this deque changed as a result of the call
* @throws IllegalStateException if not all the elements can be added at
* this time due to insertion restrictions
* @throws ClassCastException if the class of an element of the specified
* collection prevents it from being added to this deque
* @throws NullPointerException if the specified collection contains a
* null element and this deque does not permit null elements,
* or if the specified collection is null
* @throws IllegalArgumentException if some property of an element of the
* specified collection prevents it from being added to this deque
*/
boolean addAll(Collection<? extends E> c);
// *** Stack methods ***
/**
* Pushes an element onto the stack represented by this deque (in other
* words, at the head of this deque) if it is possible to do so
* immediately without violating capacity restrictions, throwing an
* {@code IllegalStateException} if no space is currently available.
*
* <p>This method is equivalent to {@link #addFirst}.
*
* @param e the element to push
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
void push(E e);
/**
* Pops an element from the stack represented by this deque. In other
* words, removes and returns the first element of this deque.
*
* <p>This method is equivalent to {@link #removeFirst()}.
*
* @return the element at the front of this deque (which is the top
* of the stack represented by this deque)
* @throws NoSuchElementException if this deque is empty
*/
E pop();
// *** Collection methods ***
/**
* Removes the first occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
* More formally, removes the first element {@code e} such that
* {@code Objects.equals(o, e)} (if such an element exists).
* Returns {@code true} if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* <p>This method is equivalent to {@link #removeFirstOccurrence(Object)}.
*
* @param o element to be removed from this deque, if present
* @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean remove(Object o);
/**
* Returns {@code true} if this deque contains the specified element.
* More formally, returns {@code true} if and only if this deque contains
* at least one element {@code e} such that {@code Objects.equals(o, e)}.
*
* @param o element whose presence in this deque is to be tested
* @return {@code true} if this deque contains the specified element
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean contains(Object o);
/**
* Returns the number of elements in this deque.
*
* @return the number of elements in this deque
*/
int size();
/**
* Returns an iterator over the elements in this deque in proper sequence.
* The elements will be returned in order from first (head) to last (tail).
*
* @return an iterator over the elements in this deque in proper sequence
*/
Iterator<E> iterator();
/**
* Returns an iterator over the elements in this deque in reverse
* sequential order. The elements will be returned in order from
* last (tail) to first (head).
*
* @return an iterator over the elements in this deque in reverse
* sequence
*/
Iterator<E> descendingIterator();
}

View file

@ -0,0 +1,155 @@
/*
* Copyright (c) 1995, 2004, 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;
/**
* The {@code Dictionary} class is the abstract parent of any
* class, such as {@code Hashtable}, which maps keys to values.
* Every key and every value is an object. In any one {@code Dictionary}
* object, every key is associated with at most one value. Given a
* {@code Dictionary} and a key, the associated element can be looked up.
* Any non-{@code null} object can be used as a key and as a value.
* <p>
* As a rule, the {@code equals} method should be used by
* implementations of this class to decide if two keys are the same.
* <p>
* <strong>NOTE: This class is obsolete. New implementations should
* implement the Map interface, rather than extending this class.</strong>
*
* @author unascribed
* @see java.util.Map
* @see java.lang.Object#equals(java.lang.Object)
* @see java.lang.Object#hashCode()
* @see java.util.Hashtable
* @since 1.0
*/
public abstract
class Dictionary<K,V> {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
public Dictionary() {
}
/**
* Returns the number of entries (distinct keys) in this dictionary.
*
* @return the number of keys in this dictionary.
*/
public abstract int size();
/**
* Tests if this dictionary maps no keys to value. The general contract
* for the {@code isEmpty} method is that the result is true if and only
* if this dictionary contains no entries.
*
* @return {@code true} if this dictionary maps no keys to values;
* {@code false} otherwise.
*/
public abstract boolean isEmpty();
/**
* Returns an enumeration of the keys in this dictionary. The general
* contract for the keys method is that an {@code Enumeration} object
* is returned that will generate all the keys for which this dictionary
* contains entries.
*
* @return an enumeration of the keys in this dictionary.
* @see java.util.Dictionary#elements()
* @see java.util.Enumeration
*/
public abstract Enumeration<K> keys();
/**
* Returns an enumeration of the values in this dictionary. The general
* contract for the {@code elements} method is that an
* {@code Enumeration} is returned that will generate all the elements
* contained in entries in this dictionary.
*
* @return an enumeration of the values in this dictionary.
* @see java.util.Dictionary#keys()
* @see java.util.Enumeration
*/
public abstract Enumeration<V> elements();
/**
* Returns the value to which the key is mapped in this dictionary.
* The general contract for the {@code isEmpty} method is that if this
* dictionary contains an entry for the specified key, the associated
* value is returned; otherwise, {@code null} is returned.
*
* @return the value to which the key is mapped in this dictionary;
* @param key a key in this dictionary.
* {@code null} if the key is not mapped to any value in
* this dictionary.
* @exception NullPointerException if the {@code key} is {@code null}.
* @see java.util.Dictionary#put(java.lang.Object, java.lang.Object)
*/
public abstract V get(Object key);
/**
* Maps the specified {@code key} to the specified
* {@code value} in this dictionary. Neither the key nor the
* value can be {@code null}.
* <p>
* If this dictionary already contains an entry for the specified
* {@code key}, the value already in this dictionary for that
* {@code key} is returned, after modifying the entry to contain the
* new element. <p>If this dictionary does not already have an entry
* for the specified {@code key}, an entry is created for the
* specified {@code key} and {@code value}, and {@code null} is
* returned.
* <p>
* The {@code value} can be retrieved by calling the
* {@code get} method with a {@code key} that is equal to
* the original {@code key}.
*
* @param key the hashtable key.
* @param value the value.
* @return the previous value to which the {@code key} was mapped
* in this dictionary, or {@code null} if the key did not
* have a previous mapping.
* @exception NullPointerException if the {@code key} or
* {@code value} is {@code null}.
* @see java.lang.Object#equals(java.lang.Object)
* @see java.util.Dictionary#get(java.lang.Object)
*/
public abstract V put(K key, V value);
/**
* Removes the {@code key} (and its corresponding
* {@code value}) from this dictionary. This method does nothing
* if the {@code key} is not in this dictionary.
*
* @param key the key that needs to be removed.
* @return the value to which the {@code key} had been mapped in this
* dictionary, or {@code null} if the key did not have a
* mapping.
* @exception NullPointerException if {@code key} is {@code null}.
*/
public abstract V remove(Object key);
}

View file

@ -0,0 +1,260 @@
/*
* Copyright (c) 2012, 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;
import java.util.function.DoubleConsumer;
import java.util.stream.Collector;
/**
* A state object for collecting statistics such as count, min, max, sum, and
* average.
*
* <p>This class is designed to work with (though does not require)
* {@linkplain java.util.stream streams}. For example, you can compute
* summary statistics on a stream of doubles with:
* <pre> {@code
* DoubleSummaryStatistics stats = doubleStream.collect(DoubleSummaryStatistics::new,
* DoubleSummaryStatistics::accept,
* DoubleSummaryStatistics::combine);
* }</pre>
*
* <p>{@code DoubleSummaryStatistics} can be used as a
* {@linkplain java.util.stream.Stream#collect(Collector) reduction}
* target for a {@linkplain java.util.stream.Stream stream}. For example:
*
* <pre> {@code
* DoubleSummaryStatistics stats = people.stream()
* .collect(Collectors.summarizingDouble(Person::getWeight));
*}</pre>
*
* This computes, in a single pass, the count of people, as well as the minimum,
* maximum, sum, and average of their weights.
*
* @implNote This implementation is not thread safe. However, it is safe to use
* {@link java.util.stream.Collectors#summarizingDouble(java.util.function.ToDoubleFunction)
* Collectors.summarizingDouble()} on a parallel stream, because the parallel
* implementation of {@link java.util.stream.Stream#collect Stream.collect()}
* provides the necessary partitioning, isolation, and merging of results for
* safe and efficient parallel execution.
* @since 1.8
*/
public class DoubleSummaryStatistics implements DoubleConsumer {
private long count;
private double sum;
private double sumCompensation; // Low order bits of sum
private double simpleSum; // Used to compute right sum for non-finite inputs
private double min = Double.POSITIVE_INFINITY;
private double max = Double.NEGATIVE_INFINITY;
/**
* Construct an empty instance with zero count, zero sum,
* {@code Double.POSITIVE_INFINITY} min, {@code Double.NEGATIVE_INFINITY}
* max and zero average.
*/
public DoubleSummaryStatistics() { }
/**
* Records another value into the summary information.
*
* @param value the input value
*/
@Override
public void accept(double value) {
++count;
simpleSum += value;
sumWithCompensation(value);
min = Math.min(min, value);
max = Math.max(max, value);
}
/**
* Combines the state of another {@code DoubleSummaryStatistics} into this
* one.
*
* @param other another {@code DoubleSummaryStatistics}
* @throws NullPointerException if {@code other} is null
*/
public void combine(DoubleSummaryStatistics other) {
count += other.count;
simpleSum += other.simpleSum;
sumWithCompensation(other.sum);
sumWithCompensation(other.sumCompensation);
min = Math.min(min, other.min);
max = Math.max(max, other.max);
}
/**
* Incorporate a new double value using Kahan summation /
* compensated summation.
*/
private void sumWithCompensation(double value) {
double tmp = value - sumCompensation;
double velvel = sum + tmp; // Little wolf of rounding error
sumCompensation = (velvel - sum) - tmp;
sum = velvel;
}
/**
* Return the count of values recorded.
*
* @return the count of values
*/
public final long getCount() {
return count;
}
/**
* Returns the sum of values recorded, or zero if no values have been
* recorded.
*
* <p> The value of a floating-point sum is a function both of the
* input values as well as the order of addition operations. The
* order of addition operations of this method is intentionally
* not defined to allow for implementation flexibility to improve
* the speed and accuracy of the computed result.
*
* In particular, this method may be implemented using compensated
* summation or other technique to reduce the error bound in the
* numerical sum compared to a simple summation of {@code double}
* values.
*
* Because of the unspecified order of operations and the
* possibility of using differing summation schemes, the output of
* this method may vary on the same input values.
*
* <p>Various conditions can result in a non-finite sum being
* computed. This can occur even if the all the recorded values
* being summed are finite. If any recorded value is non-finite,
* the sum will be non-finite:
*
* <ul>
*
* <li>If any recorded value is a NaN, then the final sum will be
* NaN.
*
* <li>If the recorded values contain one or more infinities, the
* sum will be infinite or NaN.
*
* <ul>
*
* <li>If the recorded values contain infinities of opposite sign,
* the sum will be NaN.
*
* <li>If the recorded values contain infinities of one sign and
* an intermediate sum overflows to an infinity of the opposite
* sign, the sum may be NaN.
*
* </ul>
*
* </ul>
*
* It is possible for intermediate sums of finite values to
* overflow into opposite-signed infinities; if that occurs, the
* final sum will be NaN even if the recorded values are all
* finite.
*
* If all the recorded values are zero, the sign of zero is
* <em>not</em> guaranteed to be preserved in the final sum.
*
* @apiNote Values sorted by increasing absolute magnitude tend to yield
* more accurate results.
*
* @return the sum of values, or zero if none
*/
public final double getSum() {
// Better error bounds to add both terms as the final sum
double tmp = sum + sumCompensation;
if (Double.isNaN(tmp) && Double.isInfinite(simpleSum))
// If the compensated sum is spuriously NaN from
// accumulating one or more same-signed infinite values,
// return the correctly-signed infinity stored in
// simpleSum.
return simpleSum;
else
return tmp;
}
/**
* Returns the minimum recorded value, {@code Double.NaN} if any recorded
* value was NaN or {@code Double.POSITIVE_INFINITY} if no values were
* recorded. Unlike the numerical comparison operators, this method
* considers negative zero to be strictly smaller than positive zero.
*
* @return the minimum recorded value, {@code Double.NaN} if any recorded
* value was NaN or {@code Double.POSITIVE_INFINITY} if no values were
* recorded
*/
public final double getMin() {
return min;
}
/**
* Returns the maximum recorded value, {@code Double.NaN} if any recorded
* value was NaN or {@code Double.NEGATIVE_INFINITY} if no values were
* recorded. Unlike the numerical comparison operators, this method
* considers negative zero to be strictly smaller than positive zero.
*
* @return the maximum recorded value, {@code Double.NaN} if any recorded
* value was NaN or {@code Double.NEGATIVE_INFINITY} if no values were
* recorded
*/
public final double getMax() {
return max;
}
/**
* Returns the arithmetic mean of values recorded, or zero if no
* values have been recorded.
*
* <p> The computed average can vary numerically and have the
* special case behavior as computing the sum; see {@link #getSum}
* for details.
*
* @apiNote Values sorted by increasing absolute magnitude tend to yield
* more accurate results.
*
* @return the arithmetic mean of values, or zero if none
*/
public final double getAverage() {
return getCount() > 0 ? getSum() / getCount() : 0.0d;
}
/**
* Returns a non-empty string representation of this object suitable for
* debugging. The exact presentation format is unspecified and may vary
* between implementations and versions.
*/
@Override
public String toString() {
return String.format(
"%s{count=%d, sum=%f, min=%f, average=%f, max=%f}",
this.getClass().getSimpleName(),
getCount(),
getSum(),
getMin(),
getAverage(),
getMax());
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2003, 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;
/**
* Unchecked exception thrown when duplicate flags are provided in the format
* specifier.
*
* <p> Unless otherwise specified, passing a {@code null} argument to any
* method or constructor in this class will cause a {@link
* NullPointerException} to be thrown.
*
* @since 1.5
*/
public class DuplicateFormatFlagsException extends IllegalFormatException {
private static final long serialVersionUID = 18890531L;
private String flags;
/**
* Constructs an instance of this class with the specified flags.
*
* @param f
* The set of format flags which contain a duplicate flag.
*/
public DuplicateFormatFlagsException(String f) {
if (f == null)
throw new NullPointerException();
this.flags = f;
}
/**
* Returns the set of flags which contains a duplicate flag.
*
* @return The flags
*/
public String getFlags() {
return flags;
}
public String getMessage() {
return String.format("Flags = '%s'", flags);
}
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 1994, 2008, 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;
/**
* Thrown by methods in the {@code Stack} class to indicate
* that the stack is empty.
*
* @author Jonathan Payne
* @see java.util.Stack
* @since 1.0
*/
public
class EmptyStackException extends RuntimeException {
private static final long serialVersionUID = 5084686378493302095L;
/**
* Constructs a new {@code EmptyStackException} with {@code null}
* as its error message string.
*/
public EmptyStackException() {
}
}

View file

@ -0,0 +1,812 @@
/*
* Copyright (c) 2003, 2012, 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;
import jdk.internal.misc.SharedSecrets;
/**
* A specialized {@link Map} implementation for use with enum type keys. All
* of the keys in an enum map must come from a single enum type that is
* specified, explicitly or implicitly, when the map is created. Enum maps
* are represented internally as arrays. This representation is extremely
* compact and efficient.
*
* <p>Enum maps are maintained in the <i>natural order</i> of their keys
* (the order in which the enum constants are declared). This is reflected
* in the iterators returned by the collections views ({@link #keySet()},
* {@link #entrySet()}, and {@link #values()}).
*
* <p>Iterators returned by the collection views are <i>weakly consistent</i>:
* they will never throw {@link ConcurrentModificationException} and they may
* or may not show the effects of any modifications to the map that occur while
* the iteration is in progress.
*
* <p>Null keys are not permitted. Attempts to insert a null key will
* throw {@link NullPointerException}. Attempts to test for the
* presence of a null key or to remove one will, however, function properly.
* Null values are permitted.
* <P>Like most collection implementations {@code EnumMap} is not
* synchronized. If multiple threads access an enum map concurrently, and at
* least one of the threads modifies the map, it should be synchronized
* externally. This is typically accomplished by synchronizing on some
* object that naturally encapsulates the enum map. If no such object exists,
* the map should be "wrapped" using the {@link Collections#synchronizedMap}
* method. This is best done at creation time, to prevent accidental
* unsynchronized access:
*
* <pre>
* Map&lt;EnumKey, V&gt; m
* = Collections.synchronizedMap(new EnumMap&lt;EnumKey, V&gt;(...));
* </pre>
*
* <p>Implementation note: All basic operations execute in constant time.
* They are likely (though not guaranteed) to be faster than their
* {@link HashMap} counterparts.
*
* <p>This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch
* @see EnumSet
* @since 1.5
*/
public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
implements java.io.Serializable, Cloneable
{
/**
* The {@code Class} object for the enum type of all the keys of this map.
*
* @serial
*/
private final Class<K> keyType;
/**
* All of the values comprising K. (Cached for performance.)
*/
private transient K[] keyUniverse;
/**
* Array representation of this map. The ith element is the value
* to which universe[i] is currently mapped, or null if it isn't
* mapped to anything, or NULL if it's mapped to null.
*/
private transient Object[] vals;
/**
* The number of mappings in this map.
*/
private transient int size = 0;
/**
* Distinguished non-null value for representing null values.
*/
private static final Object NULL = new Object() {
public int hashCode() {
return 0;
}
public String toString() {
return "java.util.EnumMap.NULL";
}
};
private Object maskNull(Object value) {
return (value == null ? NULL : value);
}
@SuppressWarnings("unchecked")
private V unmaskNull(Object value) {
return (V)(value == NULL ? null : value);
}
/**
* Creates an empty enum map with the specified key type.
*
* @param keyType the class object of the key type for this enum map
* @throws NullPointerException if {@code keyType} is null
*/
public EnumMap(Class<K> keyType) {
this.keyType = keyType;
keyUniverse = getKeyUniverse(keyType);
vals = new Object[keyUniverse.length];
}
/**
* Creates an enum map with the same key type as the specified enum
* map, initially containing the same mappings (if any).
*
* @param m the enum map from which to initialize this enum map
* @throws NullPointerException if {@code m} is null
*/
public EnumMap(EnumMap<K, ? extends V> m) {
keyType = m.keyType;
keyUniverse = m.keyUniverse;
vals = m.vals.clone();
size = m.size;
}
/**
* Creates an enum map initialized from the specified map. If the
* specified map is an {@code EnumMap} instance, this constructor behaves
* identically to {@link #EnumMap(EnumMap)}. Otherwise, the specified map
* must contain at least one mapping (in order to determine the new
* enum map's key type).
*
* @param m the map from which to initialize this enum map
* @throws IllegalArgumentException if {@code m} is not an
* {@code EnumMap} instance and contains no mappings
* @throws NullPointerException if {@code m} is null
*/
public EnumMap(Map<K, ? extends V> m) {
if (m instanceof EnumMap) {
EnumMap<K, ? extends V> em = (EnumMap<K, ? extends V>) m;
keyType = em.keyType;
keyUniverse = em.keyUniverse;
vals = em.vals.clone();
size = em.size;
} else {
if (m.isEmpty())
throw new IllegalArgumentException("Specified map is empty");
keyType = m.keySet().iterator().next().getDeclaringClass();
keyUniverse = getKeyUniverse(keyType);
vals = new Object[keyUniverse.length];
putAll(m);
}
}
// Query Operations
/**
* Returns the number of key-value mappings in this map.
*
* @return the number of key-value mappings in this map
*/
public int size() {
return size;
}
/**
* Returns {@code true} if this map maps one or more keys to the
* specified value.
*
* @param value the value whose presence in this map is to be tested
* @return {@code true} if this map maps one or more keys to this value
*/
public boolean containsValue(Object value) {
value = maskNull(value);
for (Object val : vals)
if (value.equals(val))
return true;
return false;
}
/**
* Returns {@code true} if this map contains a mapping for the specified
* key.
*
* @param key the key whose presence in this map is to be tested
* @return {@code true} if this map contains a mapping for the specified
* key
*/
public boolean containsKey(Object key) {
return isValidKey(key) && vals[((Enum<?>)key).ordinal()] != null;
}
private boolean containsMapping(Object key, Object value) {
return isValidKey(key) &&
maskNull(value).equals(vals[((Enum<?>)key).ordinal()]);
}
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*
* <p>More formally, if this map contains a mapping from a key
* {@code k} to a value {@code v} such that {@code (key == k)},
* then this method returns {@code v}; otherwise it returns
* {@code null}. (There can be at most one such mapping.)
*
* <p>A return value of {@code null} does not <i>necessarily</i>
* indicate that the map contains no mapping for the key; it's also
* possible that the map explicitly maps the key to {@code null}.
* The {@link #containsKey containsKey} operation may be used to
* distinguish these two cases.
*/
public V get(Object key) {
return (isValidKey(key) ?
unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
}
// Modification Operations
/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for this key, the old
* value is replaced.
*
* @param key the key with which the specified value is to be associated
* @param value the value to be associated with the specified key
*
* @return the previous value associated with specified key, or
* {@code null} if there was no mapping for key. (A {@code null}
* return can also indicate that the map previously associated
* {@code null} with the specified key.)
* @throws NullPointerException if the specified key is null
*/
public V put(K key, V value) {
typeCheck(key);
int index = key.ordinal();
Object oldValue = vals[index];
vals[index] = maskNull(value);
if (oldValue == null)
size++;
return unmaskNull(oldValue);
}
/**
* Removes the mapping for this key from this map if present.
*
* @param key the key whose mapping is to be removed from the map
* @return the previous value associated with specified key, or
* {@code null} if there was no entry for key. (A {@code null}
* return can also indicate that the map previously associated
* {@code null} with the specified key.)
*/
public V remove(Object key) {
if (!isValidKey(key))
return null;
int index = ((Enum<?>)key).ordinal();
Object oldValue = vals[index];
vals[index] = null;
if (oldValue != null)
size--;
return unmaskNull(oldValue);
}
private boolean removeMapping(Object key, Object value) {
if (!isValidKey(key))
return false;
int index = ((Enum<?>)key).ordinal();
if (maskNull(value).equals(vals[index])) {
vals[index] = null;
size--;
return true;
}
return false;
}
/**
* Returns true if key is of the proper type to be a key in this
* enum map.
*/
private boolean isValidKey(Object key) {
if (key == null)
return false;
// Cheaper than instanceof Enum followed by getDeclaringClass
Class<?> keyClass = key.getClass();
return keyClass == keyType || keyClass.getSuperclass() == keyType;
}
// Bulk Operations
/**
* Copies all of the mappings from the specified map to this map.
* These mappings will replace any mappings that this map had for
* any of the keys currently in the specified map.
*
* @param m the mappings to be stored in this map
* @throws NullPointerException the specified map is null, or if
* one or more keys in the specified map are null
*/
public void putAll(Map<? extends K, ? extends V> m) {
if (m instanceof EnumMap) {
EnumMap<?, ?> em = (EnumMap<?, ?>)m;
if (em.keyType != keyType) {
if (em.isEmpty())
return;
throw new ClassCastException(em.keyType + " != " + keyType);
}
for (int i = 0; i < keyUniverse.length; i++) {
Object emValue = em.vals[i];
if (emValue != null) {
if (vals[i] == null)
size++;
vals[i] = emValue;
}
}
} else {
super.putAll(m);
}
}
/**
* Removes all mappings from this map.
*/
public void clear() {
Arrays.fill(vals, null);
size = 0;
}
// Views
/**
* This field is initialized to contain an instance of the entry set
* view the first time this view is requested. The view is stateless,
* so there's no reason to create more than one.
*/
private transient Set<Map.Entry<K,V>> entrySet;
/**
* Returns a {@link Set} view of the keys contained in this map.
* The returned set obeys the general contract outlined in
* {@link Map#keySet()}. The set's iterator will return the keys
* in their natural order (the order in which the enum constants
* are declared).
*
* @return a set view of the keys contained in this enum map
*/
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
}
private class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return new KeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
int oldSize = size;
EnumMap.this.remove(o);
return size != oldSize;
}
public void clear() {
EnumMap.this.clear();
}
}
/**
* Returns a {@link Collection} view of the values contained in this map.
* The returned collection obeys the general contract outlined in
* {@link Map#values()}. The collection's iterator will return the
* values in the order their corresponding keys appear in map,
* which is their natural order (the order in which the enum constants
* are declared).
*
* @return a collection view of the values contained in this map
*/
public Collection<V> values() {
Collection<V> vs = values;
if (vs == null) {
vs = new Values();
values = vs;
}
return vs;
}
private class Values extends AbstractCollection<V> {
public Iterator<V> iterator() {
return new ValueIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsValue(o);
}
public boolean remove(Object o) {
o = maskNull(o);
for (int i = 0; i < vals.length; i++) {
if (o.equals(vals[i])) {
vals[i] = null;
size--;
return true;
}
}
return false;
}
public void clear() {
EnumMap.this.clear();
}
}
/**
* Returns a {@link Set} view of the mappings contained in this map.
* The returned set obeys the general contract outlined in
* {@link Map#keySet()}. The set's iterator will return the
* mappings in the order their keys appear in map, which is their
* natural order (the order in which the enum constants are declared).
*
* @return a set view of the mappings contained in this enum map
*/
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es = entrySet;
if (es != null)
return es;
else
return entrySet = new EntrySet();
}
private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator();
}
public boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
return containsMapping(entry.getKey(), entry.getValue());
}
public boolean remove(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
return removeMapping(entry.getKey(), entry.getValue());
}
public int size() {
return size;
}
public void clear() {
EnumMap.this.clear();
}
public Object[] toArray() {
return fillEntryArray(new Object[size]);
}
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
a = (T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
if (a.length > size)
a[size] = null;
return (T[]) fillEntryArray(a);
}
private Object[] fillEntryArray(Object[] a) {
int j = 0;
for (int i = 0; i < vals.length; i++)
if (vals[i] != null)
a[j++] = new AbstractMap.SimpleEntry<>(
keyUniverse[i], unmaskNull(vals[i]));
return a;
}
}
private abstract class EnumMapIterator<T> implements Iterator<T> {
// Lower bound on index of next element to return
int index = 0;
// Index of last returned element, or -1 if none
int lastReturnedIndex = -1;
public boolean hasNext() {
while (index < vals.length && vals[index] == null)
index++;
return index != vals.length;
}
public void remove() {
checkLastReturnedIndex();
if (vals[lastReturnedIndex] != null) {
vals[lastReturnedIndex] = null;
size--;
}
lastReturnedIndex = -1;
}
private void checkLastReturnedIndex() {
if (lastReturnedIndex < 0)
throw new IllegalStateException();
}
}
private class KeyIterator extends EnumMapIterator<K> {
public K next() {
if (!hasNext())
throw new NoSuchElementException();
lastReturnedIndex = index++;
return keyUniverse[lastReturnedIndex];
}
}
private class ValueIterator extends EnumMapIterator<V> {
public V next() {
if (!hasNext())
throw new NoSuchElementException();
lastReturnedIndex = index++;
return unmaskNull(vals[lastReturnedIndex]);
}
}
private class EntryIterator extends EnumMapIterator<Map.Entry<K,V>> {
private Entry lastReturnedEntry;
public Map.Entry<K,V> next() {
if (!hasNext())
throw new NoSuchElementException();
lastReturnedEntry = new Entry(index++);
return lastReturnedEntry;
}
public void remove() {
lastReturnedIndex =
((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
super.remove();
lastReturnedEntry.index = lastReturnedIndex;
lastReturnedEntry = null;
}
private class Entry implements Map.Entry<K,V> {
private int index;
private Entry(int index) {
this.index = index;
}
public K getKey() {
checkIndexForEntryUse();
return keyUniverse[index];
}
public V getValue() {
checkIndexForEntryUse();
return unmaskNull(vals[index]);
}
public V setValue(V value) {
checkIndexForEntryUse();
V oldValue = unmaskNull(vals[index]);
vals[index] = maskNull(value);
return oldValue;
}
public boolean equals(Object o) {
if (index < 0)
return o == this;
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
V ourValue = unmaskNull(vals[index]);
Object hisValue = e.getValue();
return (e.getKey() == keyUniverse[index] &&
(ourValue == hisValue ||
(ourValue != null && ourValue.equals(hisValue))));
}
public int hashCode() {
if (index < 0)
return super.hashCode();
return entryHashCode(index);
}
public String toString() {
if (index < 0)
return super.toString();
return keyUniverse[index] + "="
+ unmaskNull(vals[index]);
}
private void checkIndexForEntryUse() {
if (index < 0)
throw new IllegalStateException("Entry was removed");
}
}
}
// Comparison and hashing
/**
* Compares the specified object with this map for equality. Returns
* {@code true} if the given object is also a map and the two maps
* represent the same mappings, as specified in the {@link
* Map#equals(Object)} contract.
*
* @param o the object to be compared for equality with this map
* @return {@code true} if the specified object is equal to this map
*/
public boolean equals(Object o) {
if (this == o)
return true;
if (o instanceof EnumMap)
return equals((EnumMap<?,?>)o);
if (!(o instanceof Map))
return false;
Map<?,?> m = (Map<?,?>)o;
if (size != m.size())
return false;
for (int i = 0; i < keyUniverse.length; i++) {
if (null != vals[i]) {
K key = keyUniverse[i];
V value = unmaskNull(vals[i]);
if (null == value) {
if (!((null == m.get(key)) && m.containsKey(key)))
return false;
} else {
if (!value.equals(m.get(key)))
return false;
}
}
}
return true;
}
private boolean equals(EnumMap<?,?> em) {
if (em.size != size)
return false;
if (em.keyType != keyType)
return size == 0;
// Key types match, compare each value
for (int i = 0; i < keyUniverse.length; i++) {
Object ourValue = vals[i];
Object hisValue = em.vals[i];
if (hisValue != ourValue &&
(hisValue == null || !hisValue.equals(ourValue)))
return false;
}
return true;
}
/**
* Returns the hash code value for this map. The hash code of a map is
* defined to be the sum of the hash codes of each entry in the map.
*/
public int hashCode() {
int h = 0;
for (int i = 0; i < keyUniverse.length; i++) {
if (null != vals[i]) {
h += entryHashCode(i);
}
}
return h;
}
private int entryHashCode(int index) {
return (keyUniverse[index].hashCode() ^ vals[index].hashCode());
}
/**
* Returns a shallow copy of this enum map. The values themselves
* are not cloned.
*
* @return a shallow copy of this enum map
*/
@SuppressWarnings("unchecked")
public EnumMap<K, V> clone() {
EnumMap<K, V> result = null;
try {
result = (EnumMap<K, V>) super.clone();
} catch(CloneNotSupportedException e) {
throw new AssertionError();
}
result.vals = result.vals.clone();
result.entrySet = null;
return result;
}
/**
* Throws an exception if e is not of the correct type for this enum set.
*/
private void typeCheck(K key) {
Class<?> keyClass = key.getClass();
if (keyClass != keyType && keyClass.getSuperclass() != keyType)
throw new ClassCastException(keyClass + " != " + keyType);
}
/**
* Returns all of the values comprising K.
* The result is uncloned, cached, and shared by all callers.
*/
private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) {
return SharedSecrets.getJavaLangAccess()
.getEnumConstantsShared(keyType);
}
private static final long serialVersionUID = 458661240069192865L;
/**
* Save the state of the {@code EnumMap} instance to a stream (i.e.,
* serialize it).
*
* @serialData The <i>size</i> of the enum map (the number of key-value
* mappings) is emitted (int), followed by the key (Object)
* and value (Object) for each key-value mapping represented
* by the enum map.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException
{
// Write out the key type and any hidden stuff
s.defaultWriteObject();
// Write out size (number of Mappings)
s.writeInt(size);
// Write out keys and values (alternating)
int entriesToBeWritten = size;
for (int i = 0; entriesToBeWritten > 0; i++) {
if (null != vals[i]) {
s.writeObject(keyUniverse[i]);
s.writeObject(unmaskNull(vals[i]));
entriesToBeWritten--;
}
}
}
/**
* Reconstitute the {@code EnumMap} instance from a stream (i.e.,
* deserialize it).
*/
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException
{
// Read in the key type and any hidden stuff
s.defaultReadObject();
keyUniverse = getKeyUniverse(keyType);
vals = new Object[keyUniverse.length];
// Read in size (number of Mappings)
int size = s.readInt();
// Read the keys and values, and put the mappings in the HashMap
for (int i = 0; i < size; i++) {
K key = (K) s.readObject();
V value = (V) s.readObject();
put(key, value);
}
}
}

View file

@ -0,0 +1,467 @@
/*
* Copyright (c) 2003, 2014, 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;
import jdk.internal.misc.SharedSecrets;
/**
* A specialized {@link Set} implementation for use with enum types. All of
* the elements in an enum set must come from a single enum type that is
* specified, explicitly or implicitly, when the set is created. Enum sets
* are represented internally as bit vectors. This representation is
* extremely compact and efficient. The space and time performance of this
* class should be good enough to allow its use as a high-quality, typesafe
* alternative to traditional {@code int}-based "bit flags." Even bulk
* operations (such as {@code containsAll} and {@code retainAll}) should
* run very quickly if their argument is also an enum set.
*
* <p>The iterator returned by the {@code iterator} method traverses the
* elements in their <i>natural order</i> (the order in which the enum
* constants are declared). The returned iterator is <i>weakly
* consistent</i>: it will never throw {@link ConcurrentModificationException}
* and it may or may not show the effects of any modifications to the set that
* occur while the iteration is in progress.
*
* <p>Null elements are not permitted. Attempts to insert a null element
* will throw {@link NullPointerException}. Attempts to test for the
* presence of a null element or to remove one will, however, function
* properly.
*
* <P>Like most collection implementations, {@code EnumSet} is not
* synchronized. If multiple threads access an enum set concurrently, and at
* least one of the threads modifies the set, it should be synchronized
* externally. This is typically accomplished by synchronizing on some
* object that naturally encapsulates the enum set. If no such object exists,
* the set should be "wrapped" using the {@link Collections#synchronizedSet}
* method. This is best done at creation time, to prevent accidental
* unsynchronized access:
*
* <pre>
* Set&lt;MyEnum&gt; s = Collections.synchronizedSet(EnumSet.noneOf(MyEnum.class));
* </pre>
*
* <p>Implementation note: All basic operations execute in constant time.
* They are likely (though not guaranteed) to be much faster than their
* {@link HashSet} counterparts. Even bulk operations execute in
* constant time if their argument is also an enum set.
*
* <p>This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch
* @since 1.5
* @see EnumMap
* @serial exclude
*/
@SuppressWarnings("serial") // No serialVersionUID due to usage of
// serial proxy pattern
public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
implements Cloneable, java.io.Serializable
{
/**
* The class of all the elements of this set.
*/
final Class<E> elementType;
/**
* All of the values comprising T. (Cached for performance.)
*/
final Enum<?>[] universe;
EnumSet(Class<E>elementType, Enum<?>[] universe) {
this.elementType = elementType;
this.universe = universe;
}
/**
* Creates an empty enum set with the specified element type.
*
* @param <E> The class of the elements in the set
* @param elementType the class object of the element type for this enum
* set
* @return An empty enum set of the specified type.
* @throws NullPointerException if {@code elementType} is null
*/
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
Enum<?>[] universe = getUniverse(elementType);
if (universe == null)
throw new ClassCastException(elementType + " not an enum");
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
/**
* Creates an enum set containing all of the elements in the specified
* element type.
*
* @param <E> The class of the elements in the set
* @param elementType the class object of the element type for this enum
* set
* @return An enum set containing all the elements in the specified type.
* @throws NullPointerException if {@code elementType} is null
*/
public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
EnumSet<E> result = noneOf(elementType);
result.addAll();
return result;
}
/**
* Adds all of the elements from the appropriate enum type to this enum
* set, which is empty prior to the call.
*/
abstract void addAll();
/**
* Creates an enum set with the same element type as the specified enum
* set, initially containing the same elements (if any).
*
* @param <E> The class of the elements in the set
* @param s the enum set from which to initialize this enum set
* @return A copy of the specified enum set.
* @throws NullPointerException if {@code s} is null
*/
public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
return s.clone();
}
/**
* Creates an enum set initialized from the specified collection. If
* the specified collection is an {@code EnumSet} instance, this static
* factory method behaves identically to {@link #copyOf(EnumSet)}.
* Otherwise, the specified collection must contain at least one element
* (in order to determine the new enum set's element type).
*
* @param <E> The class of the elements in the collection
* @param c the collection from which to initialize this enum set
* @return An enum set initialized from the given collection.
* @throws IllegalArgumentException if {@code c} is not an
* {@code EnumSet} instance and contains no elements
* @throws NullPointerException if {@code c} is null
*/
public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
if (c instanceof EnumSet) {
return ((EnumSet<E>)c).clone();
} else {
if (c.isEmpty())
throw new IllegalArgumentException("Collection is empty");
Iterator<E> i = c.iterator();
E first = i.next();
EnumSet<E> result = EnumSet.of(first);
while (i.hasNext())
result.add(i.next());
return result;
}
}
/**
* Creates an enum set with the same element type as the specified enum
* set, initially containing all the elements of this type that are
* <i>not</i> contained in the specified set.
*
* @param <E> The class of the elements in the enum set
* @param s the enum set from whose complement to initialize this enum set
* @return The complement of the specified set in this set
* @throws NullPointerException if {@code s} is null
*/
public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
EnumSet<E> result = copyOf(s);
result.complement();
return result;
}
/**
* Creates an enum set initially containing the specified element.
*
* Overloadings of this method exist to initialize an enum set with
* one through five elements. A sixth overloading is provided that
* uses the varargs feature. This overloading may be used to create
* an enum set initially containing an arbitrary number of elements, but
* is likely to run slower than the overloadings that do not use varargs.
*
* @param <E> The class of the specified element and of the set
* @param e the element that this set is to contain initially
* @throws NullPointerException if {@code e} is null
* @return an enum set initially containing the specified element
*/
public static <E extends Enum<E>> EnumSet<E> of(E e) {
EnumSet<E> result = noneOf(e.getDeclaringClass());
result.add(e);
return result;
}
/**
* Creates an enum set initially containing the specified elements.
*
* Overloadings of this method exist to initialize an enum set with
* one through five elements. A sixth overloading is provided that
* uses the varargs feature. This overloading may be used to create
* an enum set initially containing an arbitrary number of elements, but
* is likely to run slower than the overloadings that do not use varargs.
*
* @param <E> The class of the parameter elements and of the set
* @param e1 an element that this set is to contain initially
* @param e2 another element that this set is to contain initially
* @throws NullPointerException if any parameters are null
* @return an enum set initially containing the specified elements
*/
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) {
EnumSet<E> result = noneOf(e1.getDeclaringClass());
result.add(e1);
result.add(e2);
return result;
}
/**
* Creates an enum set initially containing the specified elements.
*
* Overloadings of this method exist to initialize an enum set with
* one through five elements. A sixth overloading is provided that
* uses the varargs feature. This overloading may be used to create
* an enum set initially containing an arbitrary number of elements, but
* is likely to run slower than the overloadings that do not use varargs.
*
* @param <E> The class of the parameter elements and of the set
* @param e1 an element that this set is to contain initially
* @param e2 another element that this set is to contain initially
* @param e3 another element that this set is to contain initially
* @throws NullPointerException if any parameters are null
* @return an enum set initially containing the specified elements
*/
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) {
EnumSet<E> result = noneOf(e1.getDeclaringClass());
result.add(e1);
result.add(e2);
result.add(e3);
return result;
}
/**
* Creates an enum set initially containing the specified elements.
*
* Overloadings of this method exist to initialize an enum set with
* one through five elements. A sixth overloading is provided that
* uses the varargs feature. This overloading may be used to create
* an enum set initially containing an arbitrary number of elements, but
* is likely to run slower than the overloadings that do not use varargs.
*
* @param <E> The class of the parameter elements and of the set
* @param e1 an element that this set is to contain initially
* @param e2 another element that this set is to contain initially
* @param e3 another element that this set is to contain initially
* @param e4 another element that this set is to contain initially
* @throws NullPointerException if any parameters are null
* @return an enum set initially containing the specified elements
*/
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) {
EnumSet<E> result = noneOf(e1.getDeclaringClass());
result.add(e1);
result.add(e2);
result.add(e3);
result.add(e4);
return result;
}
/**
* Creates an enum set initially containing the specified elements.
*
* Overloadings of this method exist to initialize an enum set with
* one through five elements. A sixth overloading is provided that
* uses the varargs feature. This overloading may be used to create
* an enum set initially containing an arbitrary number of elements, but
* is likely to run slower than the overloadings that do not use varargs.
*
* @param <E> The class of the parameter elements and of the set
* @param e1 an element that this set is to contain initially
* @param e2 another element that this set is to contain initially
* @param e3 another element that this set is to contain initially
* @param e4 another element that this set is to contain initially
* @param e5 another element that this set is to contain initially
* @throws NullPointerException if any parameters are null
* @return an enum set initially containing the specified elements
*/
public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4,
E e5)
{
EnumSet<E> result = noneOf(e1.getDeclaringClass());
result.add(e1);
result.add(e2);
result.add(e3);
result.add(e4);
result.add(e5);
return result;
}
/**
* Creates an enum set initially containing the specified elements.
* This factory, whose parameter list uses the varargs feature, may
* be used to create an enum set initially containing an arbitrary
* number of elements, but it is likely to run slower than the overloadings
* that do not use varargs.
*
* @param <E> The class of the parameter elements and of the set
* @param first an element that the set is to contain initially
* @param rest the remaining elements the set is to contain initially
* @throws NullPointerException if any of the specified elements are null,
* or if {@code rest} is null
* @return an enum set initially containing the specified elements
*/
@SafeVarargs
public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
EnumSet<E> result = noneOf(first.getDeclaringClass());
result.add(first);
for (E e : rest)
result.add(e);
return result;
}
/**
* Creates an enum set initially containing all of the elements in the
* range defined by the two specified endpoints. The returned set will
* contain the endpoints themselves, which may be identical but must not
* be out of order.
*
* @param <E> The class of the parameter elements and of the set
* @param from the first element in the range
* @param to the last element in the range
* @throws NullPointerException if {@code from} or {@code to} are null
* @throws IllegalArgumentException if {@code from.compareTo(to) > 0}
* @return an enum set initially containing all of the elements in the
* range defined by the two specified endpoints
*/
public static <E extends Enum<E>> EnumSet<E> range(E from, E to) {
if (from.compareTo(to) > 0)
throw new IllegalArgumentException(from + " > " + to);
EnumSet<E> result = noneOf(from.getDeclaringClass());
result.addRange(from, to);
return result;
}
/**
* Adds the specified range to this enum set, which is empty prior
* to the call.
*/
abstract void addRange(E from, E to);
/**
* Returns a copy of this set.
*
* @return a copy of this set
*/
@SuppressWarnings("unchecked")
public EnumSet<E> clone() {
try {
return (EnumSet<E>) super.clone();
} catch(CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
/**
* Complements the contents of this enum set.
*/
abstract void complement();
/**
* Throws an exception if e is not of the correct type for this enum set.
*/
final void typeCheck(E e) {
Class<?> eClass = e.getClass();
if (eClass != elementType && eClass.getSuperclass() != elementType)
throw new ClassCastException(eClass + " != " + elementType);
}
/**
* Returns all of the values comprising E.
* The result is uncloned, cached, and shared by all callers.
*/
private static <E extends Enum<E>> E[] getUniverse(Class<E> elementType) {
return SharedSecrets.getJavaLangAccess()
.getEnumConstantsShared(elementType);
}
/**
* This class is used to serialize all EnumSet instances, regardless of
* implementation type. It captures their "logical contents" and they
* are reconstructed using public static factories. This is necessary
* to ensure that the existence of a particular implementation type is
* an implementation detail.
*
* @serial include
*/
private static class SerializationProxy <E extends Enum<E>>
implements java.io.Serializable
{
private static final Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
/**
* The element type of this enum set.
*
* @serial
*/
private final Class<E> elementType;
/**
* The elements contained in this enum set.
*
* @serial
*/
private final Enum<?>[] elements;
SerializationProxy(EnumSet<E> set) {
elementType = set.elementType;
elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY);
}
// instead of cast to E, we should perhaps use elementType.cast()
// to avoid injection of forged stream, but it will slow the implementation
@SuppressWarnings("unchecked")
private Object readResolve() {
EnumSet<E> result = EnumSet.noneOf(elementType);
for (Enum<?> e : elements)
result.add((E)e);
return result;
}
private static final long serialVersionUID = 362491234563181265L;
}
Object writeReplace() {
return new SerializationProxy<>(this);
}
// readObject method for the serialization proxy pattern
// See Effective Java, Second Ed., Item 78.
private void readObject(java.io.ObjectInputStream stream)
throws java.io.InvalidObjectException {
throw new java.io.InvalidObjectException("Proxy required");
}
}

View file

@ -0,0 +1,127 @@
/*
* Copyright (c) 1994, 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 object that implements the Enumeration interface generates a
* series of elements, one at a time. Successive calls to the
* {@code nextElement} method return successive elements of the
* series.
* <p>
* For example, to print all elements of a {@code Vector<E>} <i>v</i>:
* <pre>
* for (Enumeration&lt;E&gt; e = v.elements(); e.hasMoreElements();)
* System.out.println(e.nextElement());</pre>
* <p>
* Methods are provided to enumerate through the elements of a
* vector, the keys of a hashtable, and the values in a hashtable.
* Enumerations are also used to specify the input streams to a
* {@code SequenceInputStream}.
*
* @apiNote
* The functionality of this interface is duplicated by the {@link Iterator}
* interface. In addition, {@code Iterator} adds an optional remove operation,
* and has shorter method names. New implementations should consider using
* {@code Iterator} in preference to {@code Enumeration}. It is possible to
* adapt an {@code Enumeration} to an {@code Iterator} by using the
* {@link #asIterator} method.
*
* @see java.util.Iterator
* @see java.io.SequenceInputStream
* @see java.util.Enumeration#nextElement()
* @see java.util.Hashtable
* @see java.util.Hashtable#elements()
* @see java.util.Hashtable#keys()
* @see java.util.Vector
* @see java.util.Vector#elements()
*
* @author Lee Boynton
* @since 1.0
*/
public interface Enumeration<E> {
/**
* Tests if this enumeration contains more elements.
*
* @return {@code true} if and only if this enumeration object
* contains at least one more element to provide;
* {@code false} otherwise.
*/
boolean hasMoreElements();
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
E nextElement();
/**
* Returns an {@link Iterator} that traverses the remaining elements
* covered by this enumeration. Traversal is undefined if any methods
* are called on this enumeration after the call to {@code asIterator}.
*
* @apiNote
* This method is intended to help adapt code that produces
* {@code Enumeration} instances to code that consumes {@code Iterator}
* instances. For example, the {@link java.util.jar.JarFile#entries
* JarFile.entries()} method returns an {@code Enumeration<JarEntry>}.
* This can be turned into an {@code Iterator}, and then the
* {@code forEachRemaining()} method can be used:
*
* <pre>{@code
* JarFile jarFile = ... ;
* jarFile.entries().asIterator().forEachRemaining(entry -> { ... });
* }</pre>
*
* (Note that there is also a {@link java.util.jar.JarFile#stream
* JarFile.stream()} method that returns a {@code Stream} of entries,
* which may be more convenient in some cases.)
*
* @implSpec
* The default implementation returns an {@code Iterator} whose
* {@link Iterator#hasNext hasNext} method calls this Enumeration's
* {@code hasMoreElements} method, whose {@link Iterator#next next}
* method calls this Enumeration's {@code nextElement} method, and
* whose {@link Iterator#remove remove} method throws
* {@code UnsupportedOperationException}.
*
* @return an Iterator representing the remaining elements of this Enumeration
*
* @since 9
*/
default Iterator<E> asIterator() {
return new Iterator<>() {
@Override public boolean hasNext() {
return hasMoreElements();
}
@Override public E next() {
return nextElement();
}
};
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 1996, 1999, 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;
/**
* A tagging interface that all event listener interfaces must extend.
* @since 1.1
*/
public interface EventListener {
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2000, 2004, 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 abstract wrapper class for an {@code EventListener} class
* which associates a set of additional parameters with the listener.
* Subclasses must provide the storage and accessor methods
* for the additional arguments or parameters.
* <p>
* For example, a bean which supports named properties
* would have a two argument method signature for adding
* a {@code PropertyChangeListener} for a property:
* <pre>
* public void addPropertyChangeListener(String propertyName,
* PropertyChangeListener listener)
* </pre>
* If the bean also implemented the zero argument get listener method:
* <pre>
* public PropertyChangeListener[] getPropertyChangeListeners()
* </pre>
* then the array may contain inner {@code PropertyChangeListeners}
* which are also {@code PropertyChangeListenerProxy} objects.
* <p>
* If the calling method is interested in retrieving the named property
* then it would have to test the element to see if it is a proxy class.
*
* @since 1.4
*/
public abstract class EventListenerProxy<T extends EventListener>
implements EventListener {
private final T listener;
/**
* Creates a proxy for the specified listener.
*
* @param listener the listener object
*/
public EventListenerProxy(T listener) {
this.listener = listener;
}
/**
* Returns the listener associated with the proxy.
*
* @return the listener associated with the proxy
*/
public T getListener() {
return this.listener;
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 1996, 2003, 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;
/**
* <p>
* The root class from which all event state objects shall be derived.
* <p>
* All Events are constructed with a reference to the object, the "source",
* that is logically deemed to be the object upon which the Event in question
* initially occurred upon.
*
* @since 1.1
*/
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID = 5516075349620653480L;
/**
* The object on which the Event initially occurred.
*/
protected transient Object source;
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @exception IllegalArgumentException if source is null.
*/
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
/**
* The object on which the Event initially occurred.
*
* @return The object on which the Event initially occurred.
*/
public Object getSource() {
return source;
}
/**
* Returns a String representation of this EventObject.
*
* @return A a String representation of this EventObject.
*/
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2003, 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;
/**
* Unchecked exception thrown when a conversion and flag are incompatible.
*
* <p> Unless otherwise specified, passing a {@code null} argument to any
* method or constructor in this class will cause a {@link
* NullPointerException} to be thrown.
*
* @since 1.5
*/
public class FormatFlagsConversionMismatchException
extends IllegalFormatException
{
private static final long serialVersionUID = 19120414L;
private String f;
private char c;
/**
* Constructs an instance of this class with the specified flag
* and conversion.
*
* @param f
* The flag
*
* @param c
* The conversion
*/
public FormatFlagsConversionMismatchException(String f, char c) {
if (f == null)
throw new NullPointerException();
this.f = f;
this.c = c;
}
/**
* Returns the incompatible flag.
*
* @return The flag
*/
public String getFlags() {
return f;
}
/**
* Returns the incompatible conversion.
*
* @return The conversion
*/
public char getConversion() {
return c;
}
public String getMessage() {
return "Conversion = " + c + ", Flags = " + f;
}
}

View file

@ -0,0 +1,164 @@
/*
* Copyright (c) 2003, 2013, 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;
import java.io.IOException;
/**
* The {@code Formattable} interface must be implemented by any class that
* needs to perform custom formatting using the {@code 's'} conversion
* specifier of {@link java.util.Formatter}. This interface allows basic
* control for formatting arbitrary objects.
*
* For example, the following class prints out different representations of a
* stock's name depending on the flags and length constraints:
*
* <pre> {@code
* import java.nio.CharBuffer;
* import java.util.Formatter;
* import java.util.Formattable;
* import java.util.Locale;
* import static java.util.FormattableFlags.*;
*
* ...
*
* public class StockName implements Formattable {
* private String symbol, companyName, frenchCompanyName;
* public StockName(String symbol, String companyName,
* String frenchCompanyName) {
* ...
* }
*
* ...
*
* public void formatTo(Formatter fmt, int f, int width, int precision) {
* StringBuilder sb = new StringBuilder();
*
* // decide form of name
* String name = companyName;
* if (fmt.locale().equals(Locale.FRANCE))
* name = frenchCompanyName;
* boolean alternate = (f & ALTERNATE) == ALTERNATE;
* boolean usesymbol = alternate || (precision != -1 && precision < 10);
* String out = (usesymbol ? symbol : name);
*
* // apply precision
* if (precision == -1 || out.length() < precision) {
* // write it all
* sb.append(out);
* } else {
* sb.append(out.substring(0, precision - 1)).append('*');
* }
*
* // apply width and justification
* int len = sb.length();
* if (len < width)
* for (int i = 0; i < width - len; i++)
* if ((f & LEFT_JUSTIFY) == LEFT_JUSTIFY)
* sb.append(' ');
* else
* sb.insert(0, ' ');
*
* fmt.format(sb.toString());
* }
*
* public String toString() {
* return String.format("%s - %s", symbol, companyName);
* }
* }
* }</pre>
*
* <p> When used in conjunction with the {@link java.util.Formatter}, the above
* class produces the following output for various format strings.
*
* <pre> {@code
* Formatter fmt = new Formatter();
* StockName sn = new StockName("HUGE", "Huge Fruit, Inc.",
* "Fruit Titanesque, Inc.");
* fmt.format("%s", sn); // -> "Huge Fruit, Inc."
* fmt.format("%s", sn.toString()); // -> "HUGE - Huge Fruit, Inc."
* fmt.format("%#s", sn); // -> "HUGE"
* fmt.format("%-10.8s", sn); // -> "HUGE "
* fmt.format("%.12s", sn); // -> "Huge Fruit,*"
* fmt.format(Locale.FRANCE, "%25s", sn); // -> " Fruit Titanesque, Inc."
* }</pre>
*
* <p> Formattables are not necessarily safe for multithreaded access. Thread
* safety is optional and may be enforced by classes that extend and implement
* this interface.
*
* <p> Unless otherwise specified, passing a {@code null} argument to
* any method in this interface will cause a {@link
* NullPointerException} to be thrown.
*
* @since 1.5
*/
public interface Formattable {
/**
* Formats the object using the provided {@link Formatter formatter}.
*
* @param formatter
* The {@link Formatter formatter}. Implementing classes may call
* {@link Formatter#out() formatter.out()} or {@link
* Formatter#locale() formatter.locale()} to obtain the {@link
* Appendable} or {@link Locale} used by this
* {@code formatter} respectively.
*
* @param flags
* The flags modify the output format. The value is interpreted as
* a bitmask. Any combination of the following flags may be set:
* {@link FormattableFlags#LEFT_JUSTIFY}, {@link
* FormattableFlags#UPPERCASE}, and {@link
* FormattableFlags#ALTERNATE}. If no flags are set, the default
* formatting of the implementing class will apply.
*
* @param width
* The minimum number of characters to be written to the output.
* If the length of the converted value is less than the
* {@code width} then the output will be padded by
* <code>'&nbsp;&nbsp;'</code> until the total number of characters
* equals width. The padding is at the beginning by default. If
* the {@link FormattableFlags#LEFT_JUSTIFY} flag is set then the
* padding will be at the end. If {@code width} is {@code -1}
* then there is no minimum.
*
* @param precision
* The maximum number of characters to be written to the output.
* The precision is applied before the width, thus the output will
* be truncated to {@code precision} characters even if the
* {@code width} is greater than the {@code precision}. If
* {@code precision} is {@code -1} then there is no explicit
* limit on the number of characters.
*
* @throws IllegalFormatException
* If any of the parameters are invalid. For specification of all
* possible formatting errors, see the <a
* href="../util/Formatter.html#detail">Details</a> section of the
* formatter class specification.
*/
void formatTo(Formatter formatter, int flags, int width, int precision);
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2004, 2010, 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;
/**
* FomattableFlags are passed to the {@link Formattable#formatTo
* Formattable.formatTo()} method and modify the output format for {@linkplain
* Formattable Formattables}. Implementations of {@link Formattable} are
* responsible for interpreting and validating any flags.
*
* @since 1.5
*/
public class FormattableFlags {
// Explicit instantiation of this class is prohibited.
private FormattableFlags() {}
/**
* Left-justifies the output. Spaces (<code>'&#92;u0020'</code>) will be added
* at the end of the converted value as required to fill the minimum width
* of the field. If this flag is not set then the output will be
* right-justified.
*
* <p> This flag corresponds to {@code '-'} (<code>'&#92;u002d'</code>) in
* the format specifier.
*/
public static final int LEFT_JUSTIFY = 1<<0; // '-'
/**
* Converts the output to upper case according to the rules of the
* {@linkplain java.util.Locale locale} given during creation of the
* {@code formatter} argument of the {@link Formattable#formatTo
* formatTo()} method. The output should be equivalent the following
* invocation of {@link String#toUpperCase(java.util.Locale)}
*
* <pre>
* out.toUpperCase() </pre>
*
* <p> This flag corresponds to {@code 'S'} (<code>'&#92;u0053'</code>) in
* the format specifier.
*/
public static final int UPPERCASE = 1<<1; // 'S'
/**
* Requires the output to use an alternate form. The definition of the
* form is specified by the {@code Formattable}.
*
* <p> This flag corresponds to {@code '#'} (<code>'&#92;u0023'</code>) in
* the format specifier.
*/
public static final int ALTERNATE = 1<<2; // '#'
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2003, 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;
/**
* Unchecked exception thrown when the formatter has been closed.
*
* <p> Unless otherwise specified, passing a {@code null} argument to any
* method or constructor in this class will cause a {@link
* NullPointerException} to be thrown.
*
* @since 1.5
*/
public class FormatterClosedException extends IllegalStateException {
private static final long serialVersionUID = 18111216L;
/**
* Constructs an instance of this class.
*/
public FormatterClosedException() { }
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,353 @@
/*
* Copyright (c) 1997, 2013, 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;
import java.io.InvalidObjectException;
/**
* This class implements the {@code Set} interface, backed by a hash table
* (actually a {@code HashMap} instance). It makes no guarantees as to the
* iteration order of the set; in particular, it does not guarantee that the
* order will remain constant over time. This class permits the {@code null}
* element.
*
* <p>This class offers constant time performance for the basic operations
* ({@code add}, {@code remove}, {@code contains} and {@code size}),
* assuming the hash function disperses the elements properly among the
* buckets. Iterating over this set requires time proportional to the sum of
* the {@code HashSet} instance's size (the number of elements) plus the
* "capacity" of the backing {@code HashMap} instance (the number of
* buckets). Thus, it's very important not to set the initial capacity too
* high (or the load factor too low) if iteration performance is important.
*
* <p><strong>Note that this implementation is not synchronized.</strong>
* If multiple threads access a hash set concurrently, and at least one of
* the threads modifies the set, it <i>must</i> be synchronized externally.
* This is typically accomplished by synchronizing on some object that
* naturally encapsulates the set.
*
* If no such object exists, the set should be "wrapped" using the
* {@link Collections#synchronizedSet Collections.synchronizedSet}
* method. This is best done at creation time, to prevent accidental
* unsynchronized access to the set:<pre>
* Set s = Collections.synchronizedSet(new HashSet(...));</pre>
*
* <p>The iterators returned by this class's {@code iterator} method are
* <i>fail-fast</i>: if the set is modified at any time after the iterator is
* created, in any way except through the iterator's own {@code remove}
* method, the Iterator throws a {@link ConcurrentModificationException}.
* Thus, in the face of concurrent modification, the iterator fails quickly
* and cleanly, rather than risking arbitrary, non-deterministic behavior at
* an undetermined time in the future.
*
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
* as it is, generally speaking, impossible to make any hard guarantees in the
* presence of unsynchronized concurrent modification. Fail-fast iterators
* throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>the fail-fast behavior of iterators
* should be used only to detect bugs.</i>
*
* <p>This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <E> the type of elements maintained by this set
*
* @author Josh Bloch
* @author Neal Gafter
* @see Collection
* @see Set
* @see TreeSet
* @see HashMap
* @since 1.2
*/
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
static final long serialVersionUID = -5024744406713321676L;
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
/**
* Constructs a new, empty set; the backing {@code HashMap} instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}
/**
* Constructs a new set containing the elements in the specified
* collection. The {@code HashMap} is created with default load factor
* (0.75) and an initial capacity sufficient to contain the elements in
* the specified collection.
*
* @param c the collection whose elements are to be placed into this set
* @throws NullPointerException if the specified collection is null
*/
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
/**
* Constructs a new, empty set; the backing {@code HashMap} instance has
* the specified initial capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the hash map
* @param loadFactor the load factor of the hash map
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
/**
* Constructs a new, empty set; the backing {@code HashMap} instance has
* the specified initial capacity and default load factor (0.75).
*
* @param initialCapacity the initial capacity of the hash table
* @throws IllegalArgumentException if the initial capacity is less
* than zero
*/
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
/**
* Constructs a new, empty linked hash set. (This package private
* constructor is only used by LinkedHashSet.) The backing
* HashMap instance is a LinkedHashMap with the specified initial
* capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the hash map
* @param loadFactor the load factor of the hash map
* @param dummy ignored (distinguishes this
* constructor from other int, float constructor.)
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
/**
* Returns an iterator over the elements in this set. The elements
* are returned in no particular order.
*
* @return an Iterator over the elements in this set
* @see ConcurrentModificationException
*/
public Iterator<E> iterator() {
return map.keySet().iterator();
}
/**
* Returns the number of elements in this set (its cardinality).
*
* @return the number of elements in this set (its cardinality)
*/
public int size() {
return map.size();
}
/**
* Returns {@code true} if this set contains no elements.
*
* @return {@code true} if this set contains no elements
*/
public boolean isEmpty() {
return map.isEmpty();
}
/**
* Returns {@code true} if this set contains the specified element.
* More formally, returns {@code true} if and only if this set
* contains an element {@code e} such that
* {@code Objects.equals(o, e)}.
*
* @param o element whose presence in this set is to be tested
* @return {@code true} if this set contains the specified element
*/
public boolean contains(Object o) {
return map.containsKey(o);
}
/**
* Adds the specified element to this set if it is not already present.
* More formally, adds the specified element {@code e} to this set if
* this set contains no element {@code e2} such that
* {@code Objects.equals(e, e2)}.
* If this set already contains the element, the call leaves the set
* unchanged and returns {@code false}.
*
* @param e element to be added to this set
* @return {@code true} if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
/**
* Removes the specified element from this set if it is present.
* More formally, removes an element {@code e} such that
* {@code Objects.equals(o, e)},
* if this set contains such an element. Returns {@code true} if
* this set contained the element (or equivalently, if this set
* changed as a result of the call). (This set will not contain the
* element once the call returns.)
*
* @param o object to be removed from this set, if present
* @return {@code true} if the set contained the specified element
*/
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
/**
* Removes all of the elements from this set.
* The set will be empty after this call returns.
*/
public void clear() {
map.clear();
}
/**
* Returns a shallow copy of this {@code HashSet} instance: the elements
* themselves are not cloned.
*
* @return a shallow copy of this set
*/
@SuppressWarnings("unchecked")
public Object clone() {
try {
HashSet<E> newSet = (HashSet<E>) super.clone();
newSet.map = (HashMap<E, Object>) map.clone();
return newSet;
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
/**
* Save the state of this {@code HashSet} instance to a stream (that is,
* serialize it).
*
* @serialData The capacity of the backing {@code HashMap} instance
* (int), and its load factor (float) are emitted, followed by
* the size of the set (the number of elements it contains)
* (int), followed by all of its elements (each an Object) in
* no particular order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
s.defaultWriteObject();
// Write out HashMap capacity and load factor
s.writeInt(map.capacity());
s.writeFloat(map.loadFactor());
// Write out size
s.writeInt(map.size());
// Write out all elements in the proper order.
for (E e : map.keySet())
s.writeObject(e);
}
/**
* Reconstitute the {@code HashSet} instance from a stream (that is,
* deserialize it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject();
// Read capacity and verify non-negative.
int capacity = s.readInt();
if (capacity < 0) {
throw new InvalidObjectException("Illegal capacity: " +
capacity);
}
// Read load factor and verify positive and non NaN.
float loadFactor = s.readFloat();
if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
throw new InvalidObjectException("Illegal load factor: " +
loadFactor);
}
// Read size and verify non-negative.
int size = s.readInt();
if (size < 0) {
throw new InvalidObjectException("Illegal size: " +
size);
}
// Set the capacity according to the size and load factor ensuring that
// the HashMap is at least 25% full but clamping to maximum capacity.
capacity = (int) Math.min(size * Math.min(1 / loadFactor, 4.0f),
HashMap.MAXIMUM_CAPACITY);
// Create backing HashMap
map = (((HashSet<?>)this) instanceof LinkedHashSet ?
new LinkedHashMap<>(capacity, loadFactor) :
new HashMap<>(capacity, loadFactor));
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
@SuppressWarnings("unchecked")
E e = (E) s.readObject();
map.put(e, PRESENT);
}
}
/**
* Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
* and <em>fail-fast</em> {@link Spliterator} over the elements in this
* set.
*
* <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and
* {@link Spliterator#DISTINCT}. Overriding implementations should document
* the reporting of additional characteristic values.
*
* @return a {@code Spliterator} over the elements in this set
* @since 1.8
*/
public Spliterator<E> spliterator() {
return new HashMap.KeySpliterator<>(map, 0, -1, 0, 0);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2003, 2005, 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;
/**
* Unchecked exception thrown when a character with an invalid Unicode code
* point as defined by {@link Character#isValidCodePoint} is passed to the
* {@link Formatter}.
*
* <p> Unless otherwise specified, passing a {@code null} argument to any
* method or constructor in this class will cause a {@link
* NullPointerException} to be thrown.
*
* @since 1.5
*/
public class IllegalFormatCodePointException extends IllegalFormatException {
private static final long serialVersionUID = 19080630L;
private int c;
/**
* Constructs an instance of this class with the specified illegal code
* point as defined by {@link Character#isValidCodePoint}.
*
* @param c
* The illegal Unicode code point
*/
public IllegalFormatCodePointException(int c) {
this.c = c;
}
/**
* Returns the illegal code point as defined by {@link
* Character#isValidCodePoint}.
*
* @return The illegal Unicode code point
*/
public int getCodePoint() {
return c;
}
public String getMessage() {
return String.format("Code point = %#x", c);
}
}

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2003, 2012, 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;
/**
* Unchecked exception thrown when the argument corresponding to the format
* specifier is of an incompatible type.
*
* <p> Unless otherwise specified, passing a {@code null} argument to any
* method or constructor in this class will cause a {@link
* NullPointerException} to be thrown.
*
* @since 1.5
*/
public class IllegalFormatConversionException extends IllegalFormatException {
private static final long serialVersionUID = 17000126L;
private char c;
private Class<?> arg;
/**
* Constructs an instance of this class with the mismatched conversion and
* the corresponding argument class.
*
* @param c
* Inapplicable conversion
*
* @param arg
* Class of the mismatched argument
*/
public IllegalFormatConversionException(char c, Class<?> arg) {
if (arg == null)
throw new NullPointerException();
this.c = c;
this.arg = arg;
}
/**
* Returns the inapplicable conversion.
*
* @return The inapplicable conversion
*/
public char getConversion() {
return c;
}
/**
* Returns the class of the mismatched argument.
*
* @return The class of the mismatched argument
*/
public Class<?> getArgumentClass() {
return arg;
}
// javadoc inherited from Throwable.java
public String getMessage() {
return String.format("%c != %s", c, arg.getName());
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2003, 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;
/**
* Unchecked exception thrown when a format string contains an illegal syntax
* or a format specifier that is incompatible with the given arguments. Only
* explicit subtypes of this exception which correspond to specific errors
* should be instantiated.
*
* @since 1.5
*/
public class IllegalFormatException extends IllegalArgumentException {
private static final long serialVersionUID = 18830826L;
// package-private to prevent explicit instantiation
IllegalFormatException() { }
}

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2003, 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;
/**
* Unchecked exception thrown when an illegal combination flags is given.
*
* <p> Unless otherwise specified, passing a {@code null} argument to any
* method or constructor in this class will cause a {@link
* NullPointerException} to be thrown.
*
* @since 1.5
*/
public class IllegalFormatFlagsException extends IllegalFormatException {
private static final long serialVersionUID = 790824L;
private String flags;
/**
* Constructs an instance of this class with the specified flags.
*
* @param f
* The set of format flags which contain an illegal combination
*/
public IllegalFormatFlagsException(String f) {
if (f == null)
throw new NullPointerException();
this.flags = f;
}
/**
* Returns the set of flags which contains an illegal combination.
*
* @return The flags
*/
public String getFlags() {
return flags;
}
public String getMessage() {
return "Flags = '" + flags + "'";
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2003, 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;
/**
* Unchecked exception thrown when the precision is a negative value other than
* {@code -1}, the conversion does not support a precision, or the value is
* otherwise unsupported.
*
* @since 1.5
*/
public class IllegalFormatPrecisionException extends IllegalFormatException {
private static final long serialVersionUID = 18711008L;
private int p;
/**
* Constructs an instance of this class with the specified precision.
*
* @param p
* The precision
*/
public IllegalFormatPrecisionException(int p) {
this.p = p;
}
/**
* Returns the precision
*
* @return The precision
*/
public int getPrecision() {
return p;
}
public String getMessage() {
return Integer.toString(p);
}
}

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2003, 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;
/**
* Unchecked exception thrown when the format width is a negative value other
* than {@code -1} or is otherwise unsupported.
*
* @since 1.5
*/
public class IllegalFormatWidthException extends IllegalFormatException {
private static final long serialVersionUID = 16660902L;
private int w;
/**
* Constructs an instance of this class with the specified width.
*
* @param w
* The width
*/
public IllegalFormatWidthException(int w) {
this.w = w;
}
/**
* Returns the width
*
* @return The width
*/
public int getWidth() {
return w;
}
public String getMessage() {
return Integer.toString(w);
}
}

View file

@ -0,0 +1,90 @@
/*
* Copyright (c) 2010, 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.
*/
/*
*******************************************************************************
* Copyright (C) 2009-2010, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package java.util;
/**
* Thrown by methods in {@link Locale} and {@link Locale.Builder} to
* indicate that an argument is not a well-formed BCP 47 tag.
*
* @see Locale
* @since 1.7
*/
public class IllformedLocaleException extends RuntimeException {
private static final long serialVersionUID = -5245986824925681401L;
private int _errIdx = -1;
/**
* Constructs a new <code>IllformedLocaleException</code> with no
* detail message and -1 as the error index.
*/
public IllformedLocaleException() {
super();
}
/**
* Constructs a new <code>IllformedLocaleException</code> with the
* given message and -1 as the error index.
*
* @param message the message
*/
public IllformedLocaleException(String message) {
super(message);
}
/**
* Constructs a new <code>IllformedLocaleException</code> with the
* given message and the error index. The error index is the approximate
* offset from the start of the ill-formed value to the point where the
* parse first detected an error. A negative error index value indicates
* either the error index is not applicable or unknown.
*
* @param message the message
* @param errorIndex the index
*/
public IllformedLocaleException(String message, int errorIndex) {
super(message + ((errorIndex < 0) ? "" : " [at index " + errorIndex + "]"));
_errIdx = errorIndex;
}
/**
* Returns the index where the error was found. A negative value indicates
* either the error index is not applicable or unknown.
*
* @return the error index
*/
public int getErrorIndex() {
return _errIdx;
}
}

View file

@ -0,0 +1,964 @@
/*
* Copyright (c) 2016, 2017, 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;
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.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(); }
// ---------- List Implementations ----------
abstract static class AbstractImmutableList<E> extends AbstractList<E>
implements RandomAccess, Serializable {
@Override public boolean add(E e) { throw uoe(); }
@Override public boolean addAll(Collection<? extends E> c) { throw uoe(); }
@Override public boolean addAll(int index, 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 void replaceAll(UnaryOperator<E> operator) { throw uoe(); }
@Override public boolean retainAll(Collection<?> c) { throw uoe(); }
@Override public void sort(Comparator<? super E> c) { throw uoe(); }
}
static final class List0<E> extends AbstractImmutableList<E> {
private static final List0<?> INSTANCE = new List0<>();
@SuppressWarnings("unchecked")
static <T> List0<T> instance() {
return (List0<T>) INSTANCE;
}
private List0() { }
@Override
public int size() {
return 0;
}
@Override
public E get(int index) {
Objects.checkIndex(index, 0); // always throws IndexOutOfBoundsException
return null; // but the compiler doesn't know this
}
@Override
public Iterator<E> iterator() {
return Collections.emptyIterator();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST);
}
@Override
public boolean contains(Object o) {
Objects.requireNonNull(o);
return false;
}
@Override
public boolean containsAll(Collection<?> o) {
return o.isEmpty(); // implicit nullcheck of o
}
@Override
public int hashCode() {
return 1;
}
}
static final class List1<E> extends AbstractImmutableList<E> {
@Stable
private final E e0;
List1(E e0) {
this.e0 = Objects.requireNonNull(e0);
}
@Override
public int size() {
return 1;
}
@Override
public E get(int index) {
Objects.checkIndex(index, 1);
return e0;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST, e0);
}
@Override
public boolean contains(Object o) {
return o.equals(e0); // implicit nullcheck of o
}
@Override
public int hashCode() {
return 31 + e0.hashCode();
}
}
static final class List2<E> extends AbstractImmutableList<E> {
@Stable
private final E e0;
@Stable
private final E e1;
List2(E e0, E e1) {
this.e0 = Objects.requireNonNull(e0);
this.e1 = Objects.requireNonNull(e1);
}
@Override
public int size() {
return 2;
}
@Override
public E get(int index) {
Objects.checkIndex(index, 2);
if (index == 0) {
return e0;
} else { // index == 1
return e1;
}
}
@Override
public boolean contains(Object o) {
return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
}
@Override
public int hashCode() {
int hash = 31 + e0.hashCode();
return 31 * hash + e1.hashCode();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST, e0, e1);
}
}
static final class ListN<E> extends AbstractImmutableList<E> {
@Stable
private final E[] elements;
@SafeVarargs
ListN(E... input) {
// copy and check manually to avoid TOCTOU
@SuppressWarnings("unchecked")
E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input
for (int i = 0; i < input.length; i++) {
tmp[i] = Objects.requireNonNull(input[i]);
}
this.elements = tmp;
}
@Override
public int size() {
return elements.length;
}
@Override
public E get(int index) {
Objects.checkIndex(index, elements.length);
return elements[index];
}
@Override
public boolean contains(Object o) {
for (E e : elements) {
if (o.equals(e)) { // implicit nullcheck of o
return true;
}
}
return false;
}
@Override
public int hashCode() {
int hash = 1;
for (E e : elements) {
hash = 31 * hash + e.hashCode();
}
return hash;
}
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 ----------
abstract static class AbstractImmutableSet<E> extends AbstractSet<E> implements Serializable {
@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(); }
}
static final class Set0<E> extends AbstractImmutableSet<E> {
private static final Set0<?> INSTANCE = new Set0<>();
@SuppressWarnings("unchecked")
static <T> Set0<T> instance() {
return (Set0<T>) INSTANCE;
}
private Set0() { }
@Override
public int size() {
return 0;
}
@Override
public boolean contains(Object o) {
Objects.requireNonNull(o);
return false;
}
@Override
public boolean containsAll(Collection<?> o) {
return o.isEmpty(); // implicit nullcheck of o
}
@Override
public Iterator<E> iterator() {
return Collections.emptyIterator();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_SET);
}
@Override
public int hashCode() {
return 0;
}
}
static final class Set1<E> extends AbstractImmutableSet<E> {
@Stable
private final E e0;
Set1(E e0) {
this.e0 = Objects.requireNonNull(e0);
}
@Override
public int size() {
return 1;
}
@Override
public boolean contains(Object o) {
return o.equals(e0); // implicit nullcheck of o
}
@Override
public Iterator<E> iterator() {
return Collections.singletonIterator(e0);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_SET, e0);
}
@Override
public int hashCode() {
return e0.hashCode();
}
}
static final class Set2<E> extends AbstractImmutableSet<E> {
@Stable
final E e0;
@Stable
final E e1;
Set2(E e0, E e1) {
if (e0.equals(Objects.requireNonNull(e1))) { // implicit nullcheck of e0
throw new IllegalArgumentException("duplicate element: " + e0);
}
if (SALT >= 0) {
this.e0 = e0;
this.e1 = e1;
} else {
this.e0 = e1;
this.e1 = e0;
}
}
@Override
public int size() {
return 2;
}
@Override
public boolean contains(Object o) {
return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
}
@Override
public int hashCode() {
return e0.hashCode() + e1.hashCode();
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
private int idx = 0;
@Override
public boolean hasNext() {
return idx < 2;
}
@Override
public E next() {
if (idx == 0) {
idx = 1;
return e0;
} else if (idx == 1) {
idx = 2;
return e1;
} else {
throw new NoSuchElementException();
}
}
};
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
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> {
@Stable
final E[] elements;
@Stable
final int size;
@SafeVarargs
@SuppressWarnings("unchecked")
SetN(E... input) {
size = input.length; // implicit nullcheck of input
elements = (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 e
if (idx >= 0) {
throw new IllegalArgumentException("duplicate element: " + e);
} else {
elements[-(idx + 1)] = e;
}
}
}
@Override
public int size() {
return size;
}
@Override
public boolean contains(Object o) {
return probe(o) >= 0; // implicit nullcheck of o
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
private int idx = 0;
@Override
public boolean hasNext() {
while (idx < elements.length) {
if (elements[idx] != null)
return true;
idx++;
}
return false;
}
@Override
public E next() {
if (! hasNext()) {
throw new NoSuchElementException();
}
return elements[idx++];
}
};
}
@Override
public 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 pe
private int probe(Object pe) {
int idx = Math.floorMod(pe.hashCode() ^ SALT, 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 ----------
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 Map0<K,V> extends AbstractImmutableMap<K,V> {
private static final Map0<?,?> INSTANCE = new Map0<>();
@SuppressWarnings("unchecked")
static <K,V> Map0<K,V> instance() {
return (Map0<K,V>) INSTANCE;
}
private Map0() { }
@Override
public Set<Map.Entry<K,V>> entrySet() {
return Set.of();
}
@Override
public boolean containsKey(Object o) {
Objects.requireNonNull(o);
return false;
}
@Override
public boolean containsValue(Object o) {
Objects.requireNonNull(o);
return false;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_MAP);
}
@Override
public int hashCode() {
return 0;
}
}
static final class Map1<K,V> extends AbstractImmutableMap<K,V> {
@Stable
private final K k0;
@Stable
private final V v0;
Map1(K k0, V v0) {
this.k0 = Objects.requireNonNull(k0);
this.v0 = Objects.requireNonNull(v0);
}
@Override
public Set<Map.Entry<K,V>> entrySet() {
return Set.of(new KeyValueHolder<>(k0, v0));
}
@Override
public boolean containsKey(Object o) {
return o.equals(k0); // implicit nullcheck of o
}
@Override
public 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);
}
@Override
public 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> {
@Stable
final Object[] table; // pairs of key, value
@Stable
final int size; // number of pairs
MapN(Object... input) {
if ((input.length & 1) != 0) { // implicit nullcheck of input
throw new InternalError("length is odd");
}
size = input.length >> 1;
int len = EXPAND_FACTOR * input.length;
len = (len + 1) & ~1; // ensure table is even length
table = 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;
}
}
}
@Override
public boolean containsKey(Object o) {
return probe(o) >= 0; // implicit nullcheck of o
}
@Override
public boolean containsValue(Object o) {
for (int i = 1; i < table.length; i += 2) {
Object v = table[i];
if (v != null && o.equals(v)) { // implicit nullcheck of o
return true;
}
}
return false;
}
@Override
public 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) {
int i = probe(o);
if (i >= 0) {
return (V)table[i+1];
} else {
return null;
}
}
@Override
public int size() {
return size;
}
@Override
public Set<Map.Entry<K,V>> entrySet() {
return new AbstractSet<Map.Entry<K,V>>() {
@Override
public int size() {
return MapN.this.size;
}
@Override
public Iterator<Map.Entry<K,V>> iterator() {
return new Iterator<Map.Entry<K,V>>() {
int idx = 0;
@Override
public boolean hasNext() {
while (idx < table.length) {
if (table[idx] != null)
return true;
idx += 2;
}
return false;
}
@Override
public Map.Entry<K,V> next() {
if (hasNext()) {
@SuppressWarnings("unchecked")
Map.Entry<K,V> e =
new KeyValueHolder<>((K)table[idx], (V)table[idx+1]);
idx += 2;
return e;
} else {
throw new NoSuchElementException();
}
}
};
}
};
}
// 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() ^ SALT, 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);
}
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 bits
switch (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.Map0.instance();
} 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;
}
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2003, 2008, 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;
/**
* Thrown by a {@code Scanner} to indicate that the token
* retrieved does not match the pattern for the expected type, or
* that the token is out of range for the expected type.
*
* @author unascribed
* @see java.util.Scanner
* @since 1.5
*/
public
class InputMismatchException extends NoSuchElementException {
private static final long serialVersionUID = 8811230760997066428L;
/**
* Constructs an {@code InputMismatchException} with {@code null}
* as its error message string.
*/
public InputMismatchException() {
super();
}
/**
* Constructs an {@code InputMismatchException}, saving a reference
* to the error message string {@code s} for later retrieval by the
* {@code getMessage} method.
*
* @param s the detail message.
*/
public InputMismatchException(String s) {
super(s);
}
}

View file

@ -0,0 +1,169 @@
/*
* Copyright (c) 2012, 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;
import java.util.function.IntConsumer;
import java.util.stream.Collector;
/**
* A state object for collecting statistics such as count, min, max, sum, and
* average.
*
* <p>This class is designed to work with (though does not require)
* {@linkplain java.util.stream streams}. For example, you can compute
* summary statistics on a stream of ints with:
* <pre> {@code
* IntSummaryStatistics stats = intStream.collect(IntSummaryStatistics::new,
* IntSummaryStatistics::accept,
* IntSummaryStatistics::combine);
* }</pre>
*
* <p>{@code IntSummaryStatistics} can be used as a
* {@linkplain java.util.stream.Stream#collect(Collector) reduction}
* target for a {@linkplain java.util.stream.Stream stream}. For example:
*
* <pre> {@code
* IntSummaryStatistics stats = people.stream()
* .collect(Collectors.summarizingInt(Person::getDependents));
*}</pre>
*
* This computes, in a single pass, the count of people, as well as the minimum,
* maximum, sum, and average of their number of dependents.
*
* @implNote This implementation is not thread safe. However, it is safe to use
* {@link java.util.stream.Collectors#summarizingInt(java.util.function.ToIntFunction)
* Collectors.summarizingInt()} on a parallel stream, because the parallel
* implementation of {@link java.util.stream.Stream#collect Stream.collect()}
* provides the necessary partitioning, isolation, and merging of results for
* safe and efficient parallel execution.
*
* <p>This implementation does not check for overflow of the sum.
* @since 1.8
*/
public class IntSummaryStatistics implements IntConsumer {
private long count;
private long sum;
private int min = Integer.MAX_VALUE;
private int max = Integer.MIN_VALUE;
/**
* Construct an empty instance with zero count, zero sum,
* {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero
* average.
*/
public IntSummaryStatistics() { }
/**
* Records a new value into the summary information
*
* @param value the input value
*/
@Override
public void accept(int value) {
++count;
sum += value;
min = Math.min(min, value);
max = Math.max(max, value);
}
/**
* Combines the state of another {@code IntSummaryStatistics} into this one.
*
* @param other another {@code IntSummaryStatistics}
* @throws NullPointerException if {@code other} is null
*/
public void combine(IntSummaryStatistics other) {
count += other.count;
sum += other.sum;
min = Math.min(min, other.min);
max = Math.max(max, other.max);
}
/**
* Returns the count of values recorded.
*
* @return the count of values
*/
public final long getCount() {
return count;
}
/**
* Returns the sum of values recorded, or zero if no values have been
* recorded.
*
* @return the sum of values, or zero if none
*/
public final long getSum() {
return sum;
}
/**
* Returns the minimum value recorded, or {@code Integer.MAX_VALUE} if no
* values have been recorded.
*
* @return the minimum value, or {@code Integer.MAX_VALUE} if none
*/
public final int getMin() {
return min;
}
/**
* Returns the maximum value recorded, or {@code Integer.MIN_VALUE} if no
* values have been recorded.
*
* @return the maximum value, or {@code Integer.MIN_VALUE} if none
*/
public final int getMax() {
return max;
}
/**
* Returns the arithmetic mean of values recorded, or zero if no values have been
* recorded.
*
* @return the arithmetic mean of values, or zero if none
*/
public final double getAverage() {
return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
}
/**
* Returns a non-empty string representation of this object suitable for
* debugging. The exact presentation format is unspecified and may vary
* between implementations and versions.
*/
@Override
public String toString() {
return String.format(
"%s{count=%d, sum=%d, min=%d, average=%f, max=%d}",
this.getClass().getSimpleName(),
getCount(),
getSum(),
getMin(),
getAverage(),
getMax());
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2003, 2012, 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;
import java.io.NotSerializableException;
import java.io.IOException;
/**
* Thrown to indicate that an operation could not complete because
* the input did not conform to the appropriate XML document type
* for a collection of properties, as per the {@link Properties}
* specification.<p>
*
* Note, that although InvalidPropertiesFormatException inherits Serializable
* interface from Exception, it is not intended to be Serializable. Appropriate
* serialization methods are implemented to throw NotSerializableException.
*
* @see Properties
* @since 1.5
* @serial exclude
*/
public class InvalidPropertiesFormatException extends IOException {
private static final long serialVersionUID = 7763056076009360219L;
/**
* Constructs an InvalidPropertiesFormatException with the specified
* cause.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link Throwable#getCause()} method).
*/
public InvalidPropertiesFormatException(Throwable cause) {
super(cause==null ? null : cause.toString());
this.initCause(cause);
}
/**
* Constructs an InvalidPropertiesFormatException with the specified
* detail message.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link Throwable#getMessage()} method.
*/
public InvalidPropertiesFormatException(String message) {
super(message);
}
/**
* Throws NotSerializableException, since InvalidPropertiesFormatException
* objects are not intended to be serializable.
*/
private void writeObject(java.io.ObjectOutputStream out)
throws NotSerializableException
{
throw new NotSerializableException("Not serializable.");
}
/**
* Throws NotSerializableException, since InvalidPropertiesFormatException
* objects are not intended to be serializable.
*/
private void readObject(java.io.ObjectInputStream in)
throws NotSerializableException
{
throw new NotSerializableException("Not serializable.");
}
}

View file

@ -0,0 +1,135 @@
/*
* 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
* 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;
import java.util.function.Consumer;
/**
* An iterator over a collection. {@code Iterator} takes the place of
* {@link Enumeration} in the Java Collections Framework. Iterators
* differ from enumerations in two ways:
*
* <ul>
* <li> Iterators allow the caller to remove elements from the
* underlying collection during the iteration with well-defined
* semantics.
* <li> Method names have been improved.
* </ul>
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @apiNote
* An {@link Enumeration} can be converted into an {@code Iterator} by
* using the {@link Enumeration#asIterator} method.
*
* @param <E> the type of elements returned by this iterator
*
* @author Josh Bloch
* @see Collection
* @see ListIterator
* @see Iterable
* @since 1.2
*/
public interface Iterator<E> {
/**
* Returns {@code true} if the iteration has more elements.
* (In other words, returns {@code true} if {@link #next} would
* return an element rather than throwing an exception.)
*
* @return {@code true} if the iteration has more elements
*/
boolean hasNext();
/**
* Returns the next element in the iteration.
*
* @return the next element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
E next();
/**
* Removes from the underlying collection the last element returned
* by this iterator (optional operation). This method can be called
* only once per call to {@link #next}.
* <p>
* The behavior of an iterator is unspecified if the underlying collection
* is modified while the iteration is in progress in any way other than by
* calling this method, unless an overriding class has specified a
* concurrent modification policy.
* <p>
* The behavior of an iterator is unspecified if this method is called
* after a call to the {@link #forEachRemaining forEachRemaining} method.
*
* @implSpec
* The default implementation throws an instance of
* {@link UnsupportedOperationException} and performs no other action.
*
* @throws UnsupportedOperationException if the {@code remove}
* operation is not supported by this iterator
*
* @throws IllegalStateException if the {@code next} method has not
* yet been called, or the {@code remove} method has already
* been called after the last call to the {@code next}
* method
*/
default void remove() {
throw new UnsupportedOperationException("remove");
}
/**
* Performs the given action for each remaining element until all elements
* have been processed or the action throws an exception. Actions are
* performed in the order of iteration, if that order is specified.
* Exceptions thrown by the action are relayed to the caller.
* <p>
* The behavior of an iterator is unspecified if the action modifies the
* collection in any way (even by calling the {@link #remove remove} method
* or other mutator methods of {@code Iterator} subtypes),
* unless an overriding class has specified a concurrent modification policy.
* <p>
* Subsequent behavior of an iterator is unspecified if the action throws an
* exception.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* while (hasNext())
* action.accept(next());
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
* @since 1.8
*/
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,379 @@
/*
* Copyright (c) 2003, 2012, 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;
/**
* Private implementation class for EnumSet, for "jumbo" enum types
* (i.e., those with more than 64 elements).
*
* @author Josh Bloch
* @since 1.5
* @serial exclude
*/
class JumboEnumSet<E extends Enum<E>> extends EnumSet<E> {
private static final long serialVersionUID = 334349849919042784L;
/**
* Bit vector representation of this set. The ith bit of the jth
* element of this array represents the presence of universe[64*j +i]
* in this set.
*/
private long elements[];
// Redundant - maintained for performance
private int size = 0;
JumboEnumSet(Class<E>elementType, Enum<?>[] universe) {
super(elementType, universe);
elements = new long[(universe.length + 63) >>> 6];
}
void addRange(E from, E to) {
int fromIndex = from.ordinal() >>> 6;
int toIndex = to.ordinal() >>> 6;
if (fromIndex == toIndex) {
elements[fromIndex] = (-1L >>> (from.ordinal() - to.ordinal() - 1))
<< from.ordinal();
} else {
elements[fromIndex] = (-1L << from.ordinal());
for (int i = fromIndex + 1; i < toIndex; i++)
elements[i] = -1;
elements[toIndex] = -1L >>> (63 - to.ordinal());
}
size = to.ordinal() - from.ordinal() + 1;
}
void addAll() {
for (int i = 0; i < elements.length; i++)
elements[i] = -1;
elements[elements.length - 1] >>>= -universe.length;
size = universe.length;
}
void complement() {
for (int i = 0; i < elements.length; i++)
elements[i] = ~elements[i];
elements[elements.length - 1] &= (-1L >>> -universe.length);
size = universe.length - size;
}
/**
* Returns an iterator over the elements contained in this set. The
* iterator traverses the elements in their <i>natural order</i> (which is
* the order in which the enum constants are declared). The returned
* Iterator is a "weakly consistent" iterator that will never throw {@link
* ConcurrentModificationException}.
*
* @return an iterator over the elements contained in this set
*/
public Iterator<E> iterator() {
return new EnumSetIterator<>();
}
private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
/**
* A bit vector representing the elements in the current "word"
* of the set not yet returned by this iterator.
*/
long unseen;
/**
* The index corresponding to unseen in the elements array.
*/
int unseenIndex = 0;
/**
* The bit representing the last element returned by this iterator
* but not removed, or zero if no such element exists.
*/
long lastReturned = 0;
/**
* The index corresponding to lastReturned in the elements array.
*/
int lastReturnedIndex = 0;
EnumSetIterator() {
unseen = elements[0];
}
@Override
public boolean hasNext() {
while (unseen == 0 && unseenIndex < elements.length - 1)
unseen = elements[++unseenIndex];
return unseen != 0;
}
@Override
@SuppressWarnings("unchecked")
public E next() {
if (!hasNext())
throw new NoSuchElementException();
lastReturned = unseen & -unseen;
lastReturnedIndex = unseenIndex;
unseen -= lastReturned;
return (E) universe[(lastReturnedIndex << 6)
+ Long.numberOfTrailingZeros(lastReturned)];
}
@Override
public void remove() {
if (lastReturned == 0)
throw new IllegalStateException();
final long oldElements = elements[lastReturnedIndex];
elements[lastReturnedIndex] &= ~lastReturned;
if (oldElements != elements[lastReturnedIndex]) {
size--;
}
lastReturned = 0;
}
}
/**
* Returns the number of elements in this set.
*
* @return the number of elements in this set
*/
public int size() {
return size;
}
/**
* Returns {@code true} if this set contains no elements.
*
* @return {@code true} if this set contains no elements
*/
public boolean isEmpty() {
return size == 0;
}
/**
* Returns {@code true} if this set contains the specified element.
*
* @param e element to be checked for containment in this collection
* @return {@code true} if this set contains the specified element
*/
public boolean contains(Object e) {
if (e == null)
return false;
Class<?> eClass = e.getClass();
if (eClass != elementType && eClass.getSuperclass() != elementType)
return false;
int eOrdinal = ((Enum<?>)e).ordinal();
return (elements[eOrdinal >>> 6] & (1L << eOrdinal)) != 0;
}
// Modification Operations
/**
* Adds the specified element to this set if it is not already present.
*
* @param e element to be added to this set
* @return {@code true} if the set changed as a result of the call
*
* @throws NullPointerException if {@code e} is null
*/
public boolean add(E e) {
typeCheck(e);
int eOrdinal = e.ordinal();
int eWordNum = eOrdinal >>> 6;
long oldElements = elements[eWordNum];
elements[eWordNum] |= (1L << eOrdinal);
boolean result = (elements[eWordNum] != oldElements);
if (result)
size++;
return result;
}
/**
* Removes the specified element from this set if it is present.
*
* @param e element to be removed from this set, if present
* @return {@code true} if the set contained the specified element
*/
public boolean remove(Object e) {
if (e == null)
return false;
Class<?> eClass = e.getClass();
if (eClass != elementType && eClass.getSuperclass() != elementType)
return false;
int eOrdinal = ((Enum<?>)e).ordinal();
int eWordNum = eOrdinal >>> 6;
long oldElements = elements[eWordNum];
elements[eWordNum] &= ~(1L << eOrdinal);
boolean result = (elements[eWordNum] != oldElements);
if (result)
size--;
return result;
}
// Bulk Operations
/**
* Returns {@code true} if this set contains all of the elements
* in the specified collection.
*
* @param c collection to be checked for containment in this set
* @return {@code true} if this set contains all of the elements
* in the specified collection
* @throws NullPointerException if the specified collection is null
*/
public boolean containsAll(Collection<?> c) {
if (!(c instanceof JumboEnumSet))
return super.containsAll(c);
JumboEnumSet<?> es = (JumboEnumSet<?>)c;
if (es.elementType != elementType)
return es.isEmpty();
for (int i = 0; i < elements.length; i++)
if ((es.elements[i] & ~elements[i]) != 0)
return false;
return true;
}
/**
* Adds all of the elements in the specified collection to this set.
*
* @param c collection whose elements are to be added to this set
* @return {@code true} if this set changed as a result of the call
* @throws NullPointerException if the specified collection or any of
* its elements are null
*/
public boolean addAll(Collection<? extends E> c) {
if (!(c instanceof JumboEnumSet))
return super.addAll(c);
JumboEnumSet<?> es = (JumboEnumSet<?>)c;
if (es.elementType != elementType) {
if (es.isEmpty())
return false;
else
throw new ClassCastException(
es.elementType + " != " + elementType);
}
for (int i = 0; i < elements.length; i++)
elements[i] |= es.elements[i];
return recalculateSize();
}
/**
* Removes from this set all of its elements that are contained in
* the specified collection.
*
* @param c elements to be removed from this set
* @return {@code true} if this set changed as a result of the call
* @throws NullPointerException if the specified collection is null
*/
public boolean removeAll(Collection<?> c) {
if (!(c instanceof JumboEnumSet))
return super.removeAll(c);
JumboEnumSet<?> es = (JumboEnumSet<?>)c;
if (es.elementType != elementType)
return false;
for (int i = 0; i < elements.length; i++)
elements[i] &= ~es.elements[i];
return recalculateSize();
}
/**
* Retains only the elements in this set that are contained in the
* specified collection.
*
* @param c elements to be retained in this set
* @return {@code true} if this set changed as a result of the call
* @throws NullPointerException if the specified collection is null
*/
public boolean retainAll(Collection<?> c) {
if (!(c instanceof JumboEnumSet))
return super.retainAll(c);
JumboEnumSet<?> es = (JumboEnumSet<?>)c;
if (es.elementType != elementType) {
boolean changed = (size != 0);
clear();
return changed;
}
for (int i = 0; i < elements.length; i++)
elements[i] &= es.elements[i];
return recalculateSize();
}
/**
* Removes all of the elements from this set.
*/
public void clear() {
Arrays.fill(elements, 0);
size = 0;
}
/**
* Compares the specified object with this set for equality. Returns
* {@code true} if the given object is also a set, the two sets have
* the same size, and every member of the given set is contained in
* this set.
*
* @param o object to be compared for equality with this set
* @return {@code true} if the specified object is equal to this set
*/
public boolean equals(Object o) {
if (!(o instanceof JumboEnumSet))
return super.equals(o);
JumboEnumSet<?> es = (JumboEnumSet<?>)o;
if (es.elementType != elementType)
return size == 0 && es.size == 0;
return Arrays.equals(es.elements, elements);
}
/**
* Recalculates the size of the set. Returns true if it's changed.
*/
private boolean recalculateSize() {
int oldSize = size;
size = 0;
for (long elt : elements)
size += Long.bitCount(elt);
return size != oldSize;
}
public EnumSet<E> clone() {
JumboEnumSet<E> result = (JumboEnumSet<E>) super.clone();
result.elements = result.elements.clone();
return result;
}
}

View file

@ -0,0 +1,130 @@
/*
* Copyright (c) 2015, 2017, 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;
import jdk.internal.vm.annotation.Stable;
/**
* 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> {
@Stable
final K key;
@Stable
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

@ -0,0 +1,755 @@
/*
* Copyright (c) 1997, 2013, 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;
import java.util.function.Consumer;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.io.IOException;
/**
* <p>Hash table and linked list implementation of the {@code Map} interface,
* with predictable iteration order. This implementation differs from
* {@code HashMap} in that it maintains a doubly-linked list running through
* all of its entries. This linked list defines the iteration ordering,
* which is normally the order in which keys were inserted into the map
* (<i>insertion-order</i>). Note that insertion order is not affected
* if a key is <i>re-inserted</i> into the map. (A key {@code k} is
* reinserted into a map {@code m} if {@code m.put(k, v)} is invoked when
* {@code m.containsKey(k)} would return {@code true} immediately prior to
* the invocation.)
*
* <p>This implementation spares its clients from the unspecified, generally
* chaotic ordering provided by {@link HashMap} (and {@link Hashtable}),
* without incurring the increased cost associated with {@link TreeMap}. It
* can be used to produce a copy of a map that has the same order as the
* original, regardless of the original map's implementation:
* <pre>
* void foo(Map m) {
* Map copy = new LinkedHashMap(m);
* ...
* }
* </pre>
* This technique is particularly useful if a module takes a map on input,
* copies it, and later returns results whose order is determined by that of
* the copy. (Clients generally appreciate having things returned in the same
* order they were presented.)
*
* <p>A special {@link #LinkedHashMap(int,float,boolean) constructor} is
* provided to create a linked hash map whose order of iteration is the order
* in which its entries were last accessed, from least-recently accessed to
* most-recently (<i>access-order</i>). This kind of map is well-suited to
* building LRU caches. Invoking the {@code put}, {@code putIfAbsent},
* {@code get}, {@code getOrDefault}, {@code compute}, {@code computeIfAbsent},
* {@code computeIfPresent}, or {@code merge} methods results
* in an access to the corresponding entry (assuming it exists after the
* invocation completes). The {@code replace} methods only result in an access
* of the entry if the value is replaced. The {@code putAll} method generates one
* entry access for each mapping in the specified map, in the order that
* key-value mappings are provided by the specified map's entry set iterator.
* <i>No other methods generate entry accesses.</i> In particular, operations
* on collection-views do <i>not</i> affect the order of iteration of the
* backing map.
*
* <p>The {@link #removeEldestEntry(Map.Entry)} method may be overridden to
* impose a policy for removing stale mappings automatically when new mappings
* are added to the map.
*
* <p>This class provides all of the optional {@code Map} operations, and
* permits null elements. Like {@code HashMap}, it provides constant-time
* performance for the basic operations ({@code add}, {@code contains} and
* {@code remove}), assuming the hash function disperses elements
* properly among the buckets. Performance is likely to be just slightly
* below that of {@code HashMap}, due to the added expense of maintaining the
* linked list, with one exception: Iteration over the collection-views
* of a {@code LinkedHashMap} requires time proportional to the <i>size</i>
* of the map, regardless of its capacity. Iteration over a {@code HashMap}
* is likely to be more expensive, requiring time proportional to its
* <i>capacity</i>.
*
* <p>A linked hash map has two parameters that affect its performance:
* <i>initial capacity</i> and <i>load factor</i>. They are defined precisely
* as for {@code HashMap}. Note, however, that the penalty for choosing an
* excessively high value for initial capacity is less severe for this class
* than for {@code HashMap}, as iteration times for this class are unaffected
* by capacity.
*
* <p><strong>Note that this implementation is not synchronized.</strong>
* If multiple threads access a linked hash map concurrently, and at least
* one of the threads modifies the map structurally, it <em>must</em> be
* synchronized externally. This is typically accomplished by
* synchronizing on some object that naturally encapsulates the map.
*
* If no such object exists, the map should be "wrapped" using the
* {@link Collections#synchronizedMap Collections.synchronizedMap}
* method. This is best done at creation time, to prevent accidental
* unsynchronized access to the map:<pre>
* Map m = Collections.synchronizedMap(new LinkedHashMap(...));</pre>
*
* A structural modification is any operation that adds or deletes one or more
* mappings or, in the case of access-ordered linked hash maps, affects
* iteration order. In insertion-ordered linked hash maps, merely changing
* the value associated with a key that is already contained in the map is not
* a structural modification. <strong>In access-ordered linked hash maps,
* merely querying the map with {@code get} is a structural modification.
* </strong>)
*
* <p>The iterators returned by the {@code iterator} method of the collections
* returned by all of this class's collection view methods are
* <em>fail-fast</em>: if the map is structurally modified at any time after
* the iterator is created, in any way except through the iterator's own
* {@code remove} method, the iterator will throw a {@link
* ConcurrentModificationException}. Thus, in the face of concurrent
* modification, the iterator fails quickly and cleanly, rather than risking
* arbitrary, non-deterministic behavior at an undetermined time in the future.
*
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
* as it is, generally speaking, impossible to make any hard guarantees in the
* presence of unsynchronized concurrent modification. Fail-fast iterators
* throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>the fail-fast behavior of iterators
* should be used only to detect bugs.</i>
*
* <p>The spliterators returned by the spliterator method of the collections
* returned by all of this class's collection view methods are
* <em><a href="Spliterator.html#binding">late-binding</a></em>,
* <em>fail-fast</em>, and additionally report {@link Spliterator#ORDERED}.
*
* <p>This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @implNote
* The spliterators returned by the spliterator method of the collections
* returned by all of this class's collection view methods are created from
* the iterators of the corresponding collections.
*
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
*
* @author Josh Bloch
* @see Object#hashCode()
* @see Collection
* @see Map
* @see HashMap
* @see TreeMap
* @see Hashtable
* @since 1.4
*/
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
{
/*
* Implementation note. A previous version of this class was
* internally structured a little differently. Because superclass
* HashMap now uses trees for some of its nodes, class
* LinkedHashMap.Entry is now treated as intermediary node class
* that can also be converted to tree form. The name of this
* class, LinkedHashMap.Entry, is confusing in several ways in its
* current context, but cannot be changed. Otherwise, even though
* it is not exported outside this package, some existing source
* code is known to have relied on a symbol resolution corner case
* rule in calls to removeEldestEntry that suppressed compilation
* errors due to ambiguous usages. So, we keep the name to
* preserve unmodified compilability.
*
* The changes in node classes also require using two fields
* (head, tail) rather than a pointer to a header node to maintain
* the doubly-linked before/after list. This class also
* previously used a different style of callback methods upon
* access, insertion, and removal.
*/
/**
* HashMap.Node subclass for normal LinkedHashMap entries.
*/
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
private static final long serialVersionUID = 3801124242820219131L;
/**
* The head (eldest) of the doubly linked list.
*/
transient LinkedHashMap.Entry<K,V> head;
/**
* The tail (youngest) of the doubly linked list.
*/
transient LinkedHashMap.Entry<K,V> tail;
/**
* The iteration ordering method for this linked hash map: {@code true}
* for access-order, {@code false} for insertion-order.
*
* @serial
*/
final boolean accessOrder;
// internal utilities
// link at the end of list
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}
// apply src's links to dst
private void transferLinks(LinkedHashMap.Entry<K,V> src,
LinkedHashMap.Entry<K,V> dst) {
LinkedHashMap.Entry<K,V> b = dst.before = src.before;
LinkedHashMap.Entry<K,V> a = dst.after = src.after;
if (b == null)
head = dst;
else
b.after = dst;
if (a == null)
tail = dst;
else
a.before = dst;
}
// overrides of HashMap hook methods
void reinitialize() {
super.reinitialize();
head = tail = null;
}
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
LinkedHashMap.Entry<K,V> p =
new LinkedHashMap.Entry<>(hash, key, value, e);
linkNodeLast(p);
return p;
}
Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {
LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p;
LinkedHashMap.Entry<K,V> t =
new LinkedHashMap.Entry<>(q.hash, q.key, q.value, next);
transferLinks(q, t);
return t;
}
TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
TreeNode<K,V> p = new TreeNode<>(hash, key, value, next);
linkNodeLast(p);
return p;
}
TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p;
TreeNode<K,V> t = new TreeNode<>(q.hash, q.key, q.value, next);
transferLinks(q, t);
return t;
}
void afterNodeRemoval(Node<K,V> e) { // unlink
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
p.before = p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a == null)
tail = b;
else
a.before = b;
}
void afterNodeInsertion(boolean evict) { // possibly remove eldest
LinkedHashMap.Entry<K,V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}
void afterNodeAccess(Node<K,V> e) { // move node to last
LinkedHashMap.Entry<K,V> last;
if (accessOrder && (last = tail) != e) {
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a != null)
a.before = b;
else
last = b;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}
void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
s.writeObject(e.key);
s.writeObject(e.value);
}
}
/**
* Constructs an empty insertion-ordered {@code LinkedHashMap} instance
* with the specified initial capacity and load factor.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
/**
* Constructs an empty insertion-ordered {@code LinkedHashMap} instance
* with the specified initial capacity and a default load factor (0.75).
*
* @param initialCapacity the initial capacity
* @throws IllegalArgumentException if the initial capacity is negative
*/
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
/**
* Constructs an empty insertion-ordered {@code LinkedHashMap} instance
* with the default initial capacity (16) and load factor (0.75).
*/
public LinkedHashMap() {
super();
accessOrder = false;
}
/**
* Constructs an insertion-ordered {@code LinkedHashMap} instance with
* the same mappings as the specified map. The {@code LinkedHashMap}
* instance is created with a default load factor (0.75) and an initial
* capacity sufficient to hold the mappings in the specified map.
*
* @param m the map whose mappings are to be placed in this map
* @throws NullPointerException if the specified map is null
*/
public LinkedHashMap(Map<? extends K, ? extends V> m) {
super();
accessOrder = false;
putMapEntries(m, false);
}
/**
* Constructs an empty {@code LinkedHashMap} instance with the
* specified initial capacity, load factor and ordering mode.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @param accessOrder the ordering mode - {@code true} for
* access-order, {@code false} for insertion-order
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
/**
* Returns {@code true} if this map maps one or more keys to the
* specified value.
*
* @param value value whose presence in this map is to be tested
* @return {@code true} if this map maps one or more keys to the
* specified value
*/
public boolean containsValue(Object value) {
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
V v = e.value;
if (v == value || (value != null && value.equals(v)))
return true;
}
return false;
}
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*
* <p>More formally, if this map contains a mapping from a key
* {@code k} to a value {@code v} such that {@code (key==null ? k==null :
* key.equals(k))}, then this method returns {@code v}; otherwise
* it returns {@code null}. (There can be at most one such mapping.)
*
* <p>A return value of {@code null} does not <i>necessarily</i>
* indicate that the map contains no mapping for the key; it's also
* possible that the map explicitly maps the key to {@code null}.
* The {@link #containsKey containsKey} operation may be used to
* distinguish these two cases.
*/
public V get(Object key) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
/**
* {@inheritDoc}
*/
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return defaultValue;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
/**
* {@inheritDoc}
*/
public void clear() {
super.clear();
head = tail = null;
}
/**
* Returns {@code true} if this map should remove its eldest entry.
* This method is invoked by {@code put} and {@code putAll} after
* inserting a new entry into the map. It provides the implementor
* with the opportunity to remove the eldest entry each time a new one
* is added. This is useful if the map represents a cache: it allows
* the map to reduce memory consumption by deleting stale entries.
*
* <p>Sample use: this override will allow the map to grow up to 100
* entries and then delete the eldest entry each time a new entry is
* added, maintaining a steady state of 100 entries.
* <pre>
* private static final int MAX_ENTRIES = 100;
*
* protected boolean removeEldestEntry(Map.Entry eldest) {
* return size() &gt; MAX_ENTRIES;
* }
* </pre>
*
* <p>This method typically does not modify the map in any way,
* instead allowing the map to modify itself as directed by its
* return value. It <i>is</i> permitted for this method to modify
* the map directly, but if it does so, it <i>must</i> return
* {@code false} (indicating that the map should not attempt any
* further modification). The effects of returning {@code true}
* after modifying the map from within this method are unspecified.
*
* <p>This implementation merely returns {@code false} (so that this
* map acts like a normal map - the eldest element is never removed).
*
* @param eldest The least recently inserted entry in the map, or if
* this is an access-ordered map, the least recently accessed
* entry. This is the entry that will be removed it this
* method returns {@code true}. If the map was empty prior
* to the {@code put} or {@code putAll} invocation resulting
* in this invocation, this will be the entry that was just
* inserted; in other words, if the map contains a single
* entry, the eldest entry is also the newest.
* @return {@code true} if the eldest entry should be removed
* from the map; {@code false} if it should be retained.
*/
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
/**
* Returns a {@link Set} view of the keys contained in this map.
* The set is backed by the map, so changes to the map are
* reflected in the set, and vice-versa. If the map is modified
* while an iteration over the set is in progress (except through
* the iterator's own {@code remove} operation), the results of
* the iteration are undefined. The set supports element removal,
* which removes the corresponding mapping from the map, via the
* {@code Iterator.remove}, {@code Set.remove},
* {@code removeAll}, {@code retainAll}, and {@code clear}
* operations. It does not support the {@code add} or {@code addAll}
* operations.
* Its {@link Spliterator} typically provides faster sequential
* performance but much poorer parallel performance than that of
* {@code HashMap}.
*
* @return a set view of the keys contained in this map
*/
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new LinkedKeySet();
keySet = ks;
}
return ks;
}
final class LinkedKeySet extends AbstractSet<K> {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator<K> iterator() {
return new LinkedKeyIterator();
}
public final boolean contains(Object o) { return containsKey(o); }
public final boolean remove(Object key) {
return removeNode(hash(key), key, null, false, true) != null;
}
public final Spliterator<K> spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED |
Spliterator.ORDERED |
Spliterator.DISTINCT);
}
public final void forEach(Consumer<? super K> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
action.accept(e.key);
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
/**
* Returns a {@link Collection} view of the values contained in this map.
* The collection is backed by the map, so changes to the map are
* reflected in the collection, and vice-versa. If the map is
* modified while an iteration over the collection is in progress
* (except through the iterator's own {@code remove} operation),
* the results of the iteration are undefined. The collection
* supports element removal, which removes the corresponding
* mapping from the map, via the {@code Iterator.remove},
* {@code Collection.remove}, {@code removeAll},
* {@code retainAll} and {@code clear} operations. It does not
* support the {@code add} or {@code addAll} operations.
* Its {@link Spliterator} typically provides faster sequential
* performance but much poorer parallel performance than that of
* {@code HashMap}.
*
* @return a view of the values contained in this map
*/
public Collection<V> values() {
Collection<V> vs = values;
if (vs == null) {
vs = new LinkedValues();
values = vs;
}
return vs;
}
final class LinkedValues extends AbstractCollection<V> {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator<V> iterator() {
return new LinkedValueIterator();
}
public final boolean contains(Object o) { return containsValue(o); }
public final Spliterator<V> spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED |
Spliterator.ORDERED);
}
public final void forEach(Consumer<? super V> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
action.accept(e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
/**
* Returns a {@link Set} view of the mappings contained in this map.
* The set is backed by the map, so changes to the map are
* reflected in the set, and vice-versa. If the map is modified
* while an iteration over the set is in progress (except through
* the iterator's own {@code remove} operation, or through the
* {@code setValue} operation on a map entry returned by the
* iterator) the results of the iteration are undefined. The set
* supports element removal, which removes the corresponding
* mapping from the map, via the {@code Iterator.remove},
* {@code Set.remove}, {@code removeAll}, {@code retainAll} and
* {@code clear} operations. It does not support the
* {@code add} or {@code addAll} operations.
* Its {@link Spliterator} typically provides faster sequential
* performance but much poorer parallel performance than that of
* {@code HashMap}.
*
* @return a set view of the mappings contained in this map
*/
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
}
final class LinkedEntrySet extends AbstractSet<Map.Entry<K,V>> {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator<Map.Entry<K,V>> iterator() {
return new LinkedEntryIterator();
}
public final boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Node<K,V> candidate = getNode(hash(key), key);
return candidate != null && candidate.equals(e);
}
public final boolean remove(Object o) {
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Object value = e.getValue();
return removeNode(hash(key), key, value, true, true) != null;
}
return false;
}
public final Spliterator<Map.Entry<K,V>> spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED |
Spliterator.ORDERED |
Spliterator.DISTINCT);
}
public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
action.accept(e);
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
// Map overrides
public void forEach(BiConsumer<? super K, ? super V> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
action.accept(e.key, e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
if (function == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
e.value = function.apply(e.key, e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
// Iterators
abstract class LinkedHashIterator {
LinkedHashMap.Entry<K,V> next;
LinkedHashMap.Entry<K,V> current;
int expectedModCount;
LinkedHashIterator() {
next = head;
expectedModCount = modCount;
current = null;
}
public final boolean hasNext() {
return next != null;
}
final LinkedHashMap.Entry<K,V> nextNode() {
LinkedHashMap.Entry<K,V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
current = e;
next = e.after;
return e;
}
public final void remove() {
Node<K,V> p = current;
if (p == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
current = null;
removeNode(p.hash, p.key, null, false, false);
expectedModCount = modCount;
}
}
final class LinkedKeyIterator extends LinkedHashIterator
implements Iterator<K> {
public final K next() { return nextNode().getKey(); }
}
final class LinkedValueIterator extends LinkedHashIterator
implements Iterator<V> {
public final V next() { return nextNode().value; }
}
final class LinkedEntryIterator extends LinkedHashIterator
implements Iterator<Map.Entry<K,V>> {
public final Map.Entry<K,V> next() { return nextNode(); }
}
}

View file

@ -0,0 +1,195 @@
/*
* Copyright (c) 2000, 2013, 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;
/**
* <p>Hash table and linked list implementation of the {@code Set} interface,
* with predictable iteration order. This implementation differs from
* {@code HashSet} in that it maintains a doubly-linked list running through
* all of its entries. This linked list defines the iteration ordering,
* which is the order in which elements were inserted into the set
* (<i>insertion-order</i>). Note that insertion order is <i>not</i> affected
* if an element is <i>re-inserted</i> into the set. (An element {@code e}
* is reinserted into a set {@code s} if {@code s.add(e)} is invoked when
* {@code s.contains(e)} would return {@code true} immediately prior to
* the invocation.)
*
* <p>This implementation spares its clients from the unspecified, generally
* chaotic ordering provided by {@link HashSet}, without incurring the
* increased cost associated with {@link TreeSet}. It can be used to
* produce a copy of a set that has the same order as the original, regardless
* of the original set's implementation:
* <pre>
* void foo(Set s) {
* Set copy = new LinkedHashSet(s);
* ...
* }
* </pre>
* This technique is particularly useful if a module takes a set on input,
* copies it, and later returns results whose order is determined by that of
* the copy. (Clients generally appreciate having things returned in the same
* order they were presented.)
*
* <p>This class provides all of the optional {@code Set} operations, and
* permits null elements. Like {@code HashSet}, it provides constant-time
* performance for the basic operations ({@code add}, {@code contains} and
* {@code remove}), assuming the hash function disperses elements
* properly among the buckets. Performance is likely to be just slightly
* below that of {@code HashSet}, due to the added expense of maintaining the
* linked list, with one exception: Iteration over a {@code LinkedHashSet}
* requires time proportional to the <i>size</i> of the set, regardless of
* its capacity. Iteration over a {@code HashSet} is likely to be more
* expensive, requiring time proportional to its <i>capacity</i>.
*
* <p>A linked hash set has two parameters that affect its performance:
* <i>initial capacity</i> and <i>load factor</i>. They are defined precisely
* as for {@code HashSet}. Note, however, that the penalty for choosing an
* excessively high value for initial capacity is less severe for this class
* than for {@code HashSet}, as iteration times for this class are unaffected
* by capacity.
*
* <p><strong>Note that this implementation is not synchronized.</strong>
* If multiple threads access a linked hash set concurrently, and at least
* one of the threads modifies the set, it <em>must</em> be synchronized
* externally. This is typically accomplished by synchronizing on some
* object that naturally encapsulates the set.
*
* If no such object exists, the set should be "wrapped" using the
* {@link Collections#synchronizedSet Collections.synchronizedSet}
* method. This is best done at creation time, to prevent accidental
* unsynchronized access to the set: <pre>
* Set s = Collections.synchronizedSet(new LinkedHashSet(...));</pre>
*
* <p>The iterators returned by this class's {@code iterator} method are
* <em>fail-fast</em>: if the set is modified at any time after the iterator
* is created, in any way except through the iterator's own {@code remove}
* method, the iterator will throw a {@link ConcurrentModificationException}.
* Thus, in the face of concurrent modification, the iterator fails quickly
* and cleanly, rather than risking arbitrary, non-deterministic behavior at
* an undetermined time in the future.
*
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
* as it is, generally speaking, impossible to make any hard guarantees in the
* presence of unsynchronized concurrent modification. Fail-fast iterators
* throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>the fail-fast behavior of iterators
* should be used only to detect bugs.</i>
*
* <p>This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <E> the type of elements maintained by this set
*
* @author Josh Bloch
* @see Object#hashCode()
* @see Collection
* @see Set
* @see HashSet
* @see TreeSet
* @see Hashtable
* @since 1.4
*/
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
private static final long serialVersionUID = -2851667679971038690L;
/**
* Constructs a new, empty linked hash set with the specified initial
* capacity and load factor.
*
* @param initialCapacity the initial capacity of the linked hash set
* @param loadFactor the load factor of the linked hash set
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
/**
* Constructs a new, empty linked hash set with the specified initial
* capacity and the default load factor (0.75).
*
* @param initialCapacity the initial capacity of the LinkedHashSet
* @throws IllegalArgumentException if the initial capacity is less
* than zero
*/
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
/**
* Constructs a new, empty linked hash set with the default initial
* capacity (16) and load factor (0.75).
*/
public LinkedHashSet() {
super(16, .75f, true);
}
/**
* Constructs a new linked hash set with the same elements as the
* specified collection. The linked hash set is created with an initial
* capacity sufficient to hold the elements in the specified collection
* and the default load factor (0.75).
*
* @param c the collection whose elements are to be placed into
* this set
* @throws NullPointerException if the specified collection is null
*/
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
/**
* Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
* and <em>fail-fast</em> {@code Spliterator} over the elements in this set.
*
* <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
* {@link Spliterator#DISTINCT}, and {@code ORDERED}. Implementations
* should document the reporting of additional characteristic values.
*
* @implNote
* The implementation creates a
* <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator
* from the set's {@code Iterator}. The spliterator inherits the
* <em>fail-fast</em> properties of the set's iterator.
* The created {@code Spliterator} additionally reports
* {@link Spliterator#SUBSIZED}.
*
* @return a {@code Spliterator} over the elements in this set
* @since 1.8
*/
@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,195 @@
/*
* Copyright (c) 1997, 2011, 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 iterator for lists that allows the programmer
* to traverse the list in either direction, modify
* the list during iteration, and obtain the iterator's
* current position in the list. A {@code ListIterator}
* has no current element; its <I>cursor position</I> always
* lies between the element that would be returned by a call
* to {@code previous()} and the element that would be
* returned by a call to {@code next()}.
* An iterator for a list of length {@code n} has {@code n+1} possible
* cursor positions, as illustrated by the carets ({@code ^}) below:
* <PRE>
* Element(0) Element(1) Element(2) ... Element(n-1)
* cursor positions: ^ ^ ^ ^ ^
* </PRE>
* Note that the {@link #remove} and {@link #set(Object)} methods are
* <i>not</i> defined in terms of the cursor position; they are defined to
* operate on the last element returned by a call to {@link #next} or
* {@link #previous()}.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch
* @see Collection
* @see List
* @see Iterator
* @see Enumeration
* @see List#listIterator()
* @since 1.2
*/
public interface ListIterator<E> extends Iterator<E> {
// Query Operations
/**
* Returns {@code true} if this list iterator has more elements when
* traversing the list in the forward direction. (In other words,
* returns {@code true} if {@link #next} would return an element rather
* than throwing an exception.)
*
* @return {@code true} if the list iterator has more elements when
* traversing the list in the forward direction
*/
boolean hasNext();
/**
* Returns the next element in the list and advances the cursor position.
* This method may be called repeatedly to iterate through the list,
* or intermixed with calls to {@link #previous} to go back and forth.
* (Note that alternating calls to {@code next} and {@code previous}
* will return the same element repeatedly.)
*
* @return the next element in the list
* @throws NoSuchElementException if the iteration has no next element
*/
E next();
/**
* Returns {@code true} if this list iterator has more elements when
* traversing the list in the reverse direction. (In other words,
* returns {@code true} if {@link #previous} would return an element
* rather than throwing an exception.)
*
* @return {@code true} if the list iterator has more elements when
* traversing the list in the reverse direction
*/
boolean hasPrevious();
/**
* Returns the previous element in the list and moves the cursor
* position backwards. This method may be called repeatedly to
* iterate through the list backwards, or intermixed with calls to
* {@link #next} to go back and forth. (Note that alternating calls
* to {@code next} and {@code previous} will return the same
* element repeatedly.)
*
* @return the previous element in the list
* @throws NoSuchElementException if the iteration has no previous
* element
*/
E previous();
/**
* Returns the index of the element that would be returned by a
* subsequent call to {@link #next}. (Returns list size if the list
* iterator is at the end of the list.)
*
* @return the index of the element that would be returned by a
* subsequent call to {@code next}, or list size if the list
* iterator is at the end of the list
*/
int nextIndex();
/**
* Returns the index of the element that would be returned by a
* subsequent call to {@link #previous}. (Returns -1 if the list
* iterator is at the beginning of the list.)
*
* @return the index of the element that would be returned by a
* subsequent call to {@code previous}, or -1 if the list
* iterator is at the beginning of the list
*/
int previousIndex();
// Modification Operations
/**
* Removes from the list the last element that was returned by {@link
* #next} or {@link #previous} (optional operation). This call can
* only be made once per call to {@code next} or {@code previous}.
* It can be made only if {@link #add} has not been
* called after the last call to {@code next} or {@code previous}.
*
* @throws UnsupportedOperationException if the {@code remove}
* operation is not supported by this list iterator
* @throws IllegalStateException if neither {@code next} nor
* {@code previous} have been called, or {@code remove} or
* {@code add} have been called after the last call to
* {@code next} or {@code previous}
*/
void remove();
/**
* Replaces the last element returned by {@link #next} or
* {@link #previous} with the specified element (optional operation).
* This call can be made only if neither {@link #remove} nor {@link
* #add} have been called after the last call to {@code next} or
* {@code previous}.
*
* @param e the element with which to replace the last element returned by
* {@code next} or {@code previous}
* @throws UnsupportedOperationException if the {@code set} operation
* is not supported by this list iterator
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this list
* @throws IllegalArgumentException if some aspect of the specified
* element prevents it from being added to this list
* @throws IllegalStateException if neither {@code next} nor
* {@code previous} have been called, or {@code remove} or
* {@code add} have been called after the last call to
* {@code next} or {@code previous}
*/
void set(E e);
/**
* Inserts the specified element into the list (optional operation).
* The element is inserted immediately before the element that
* would be returned by {@link #next}, if any, and after the element
* that would be returned by {@link #previous}, if any. (If the
* list contains no elements, the new element becomes the sole element
* on the list.) The new element is inserted before the implicit
* cursor: a subsequent call to {@code next} would be unaffected, and a
* subsequent call to {@code previous} would return the new element.
* (This call increases by one the value that would be returned by a
* call to {@code nextIndex} or {@code previousIndex}.)
*
* @param e the element to insert
* @throws UnsupportedOperationException if the {@code add} method is
* not supported by this list iterator
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this list
* @throws IllegalArgumentException if some aspect of this element
* prevents it from being added to this list
*/
void add(E e);
}

View file

@ -0,0 +1,210 @@
/*
* Copyright (c) 1996, 2016, 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.
*/
/*
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
*
* The original version of this source code and documentation
* is copyrighted and owned by Taligent, Inc., a wholly-owned
* subsidiary of IBM. These materials are provided under terms
* of a License Agreement between Taligent and Sun. This technology
* is protected by multiple US and International patents.
*
* This notice and attribution to Taligent may not be removed.
* Taligent is a registered trademark of Taligent, Inc.
*
*/
package java.util;
import sun.util.ResourceBundleEnumeration;
/**
* <code>ListResourceBundle</code> is an abstract subclass of
* <code>ResourceBundle</code> that manages resources for a locale
* in a convenient and easy to use list. See <code>ResourceBundle</code> for
* more information about resource bundles in general.
*
* <P>
* Subclasses must override <code>getContents</code> and provide an array,
* where each item in the array is a pair of objects.
* The first element of each pair is the key, which must be a
* <code>String</code>, and the second element is the value associated with
* that key.
*
* <p>
* The following <a id="sample">example</a> shows two members of a resource
* bundle family with the base name "MyResources".
* "MyResources" is the default member of the bundle family, and
* "MyResources_fr" is the French member.
* These members are based on <code>ListResourceBundle</code>
* (a related <a href="PropertyResourceBundle.html#sample">example</a> shows
* how you can add a bundle to this family that's based on a properties file).
* The keys in this example are of the form "s1" etc. The actual
* keys are entirely up to your choice, so long as they are the same as
* the keys you use in your program to retrieve the objects from the bundle.
* Keys are case-sensitive.
* <blockquote>
* <pre>
*
* public class MyResources extends ListResourceBundle {
* protected Object[][] getContents() {
* return new Object[][] {
* // LOCALIZE THIS
* {"s1", "The disk \"{1}\" contains {0}."}, // MessageFormat pattern
* {"s2", "1"}, // location of {0} in pattern
* {"s3", "My Disk"}, // sample disk name
* {"s4", "no files"}, // first ChoiceFormat choice
* {"s5", "one file"}, // second ChoiceFormat choice
* {"s6", "{0,number} files"}, // third ChoiceFormat choice
* {"s7", "3 Mar 96"}, // sample date
* {"s8", new Dimension(1,5)} // real object, not just string
* // END OF MATERIAL TO LOCALIZE
* };
* }
* }
*
* public class MyResources_fr extends ListResourceBundle {
* protected Object[][] getContents() {
* return new Object[][] {
* // LOCALIZE THIS
* {"s1", "Le disque \"{1}\" {0}."}, // MessageFormat pattern
* {"s2", "1"}, // location of {0} in pattern
* {"s3", "Mon disque"}, // sample disk name
* {"s4", "ne contient pas de fichiers"}, // first ChoiceFormat choice
* {"s5", "contient un fichier"}, // second ChoiceFormat choice
* {"s6", "contient {0,number} fichiers"}, // third ChoiceFormat choice
* {"s7", "3 mars 1996"}, // sample date
* {"s8", new Dimension(1,3)} // real object, not just string
* // END OF MATERIAL TO LOCALIZE
* };
* }
* }
* </pre>
* </blockquote>
*
* <p>
* The implementation of a {@code ListResourceBundle} subclass must be thread-safe
* if it's simultaneously used by multiple threads. The default implementations
* of the methods in this class are thread-safe.
*
* @see ResourceBundle
* @see PropertyResourceBundle
* @since 1.1
*/
public abstract class ListResourceBundle extends ResourceBundle {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
public ListResourceBundle() {
}
// Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
public final Object handleGetObject(String key) {
// lazily load the lookup hashtable.
if (lookup == null) {
loadLookup();
}
if (key == null) {
throw new NullPointerException();
}
return lookup.get(key); // this class ignores locales
}
/**
* Returns an <code>Enumeration</code> of the keys contained in
* this <code>ResourceBundle</code> and its parent bundles.
*
* @return an <code>Enumeration</code> of the keys contained in
* this <code>ResourceBundle</code> and its parent bundles.
* @see #keySet()
*/
public Enumeration<String> getKeys() {
// lazily load the lookup hashtable.
if (lookup == null) {
loadLookup();
}
ResourceBundle parent = this.parent;
return new ResourceBundleEnumeration(lookup.keySet(),
(parent != null) ? parent.getKeys() : null);
}
/**
* Returns a <code>Set</code> of the keys contained
* <em>only</em> in this <code>ResourceBundle</code>.
*
* @return a <code>Set</code> of the keys contained only in this
* <code>ResourceBundle</code>
* @since 1.6
* @see #keySet()
*/
protected Set<String> handleKeySet() {
if (lookup == null) {
loadLookup();
}
return lookup.keySet();
}
/**
* Returns an array in which each item is a pair of objects in an
* <code>Object</code> array. The first element of each pair is
* the key, which must be a <code>String</code>, and the second
* element is the value associated with that key. See the class
* description for details.
*
* @return an array of an <code>Object</code> array representing a
* key-value pair.
*/
protected abstract Object[][] getContents();
// ==================privates====================
/**
* We lazily load the lookup hashtable. This function does the
* loading.
*/
private synchronized void loadLookup() {
if (lookup != null)
return;
Object[][] contents = getContents();
HashMap<String,Object> temp = new HashMap<>(contents.length);
for (Object[] content : contents) {
// key must be non-null String, value must be non-null
String key = (String) content[0];
Object value = content[1];
if (key == null || value == null) {
throw new NullPointerException();
}
temp.put(key, value);
}
lookup = temp;
}
private volatile Map<String,Object> lookup = null;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,505 @@
/*
* Copyright (c) 2005, 2016, 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;
class LocaleISOData {
/**
* The 2- and 3-letter ISO 639 language codes.
*/
static final String isoLanguageTable =
"aa" + "aar" // Afar
+ "ab" + "abk" // Abkhazian
+ "ae" + "ave" // Avestan
+ "af" + "afr" // Afrikaans
+ "ak" + "aka" // Akan
+ "am" + "amh" // Amharic
+ "an" + "arg" // Aragonese
+ "ar" + "ara" // Arabic
+ "as" + "asm" // Assamese
+ "av" + "ava" // Avaric
+ "ay" + "aym" // Aymara
+ "az" + "aze" // Azerbaijani
+ "ba" + "bak" // Bashkir
+ "be" + "bel" // Belarusian
+ "bg" + "bul" // Bulgarian
+ "bh" + "bih" // Bihari
+ "bi" + "bis" // Bislama
+ "bm" + "bam" // Bambara
+ "bn" + "ben" // Bengali
+ "bo" + "bod" // Tibetan
+ "br" + "bre" // Breton
+ "bs" + "bos" // Bosnian
+ "ca" + "cat" // Catalan
+ "ce" + "che" // Chechen
+ "ch" + "cha" // Chamorro
+ "co" + "cos" // Corsican
+ "cr" + "cre" // Cree
+ "cs" + "ces" // Czech
+ "cu" + "chu" // Church Slavic
+ "cv" + "chv" // Chuvash
+ "cy" + "cym" // Welsh
+ "da" + "dan" // Danish
+ "de" + "deu" // German
+ "dv" + "div" // Divehi
+ "dz" + "dzo" // Dzongkha
+ "ee" + "ewe" // Ewe
+ "el" + "ell" // Greek
+ "en" + "eng" // English
+ "eo" + "epo" // Esperanto
+ "es" + "spa" // Spanish
+ "et" + "est" // Estonian
+ "eu" + "eus" // Basque
+ "fa" + "fas" // Persian
+ "ff" + "ful" // Fulah
+ "fi" + "fin" // Finnish
+ "fj" + "fij" // Fijian
+ "fo" + "fao" // Faroese
+ "fr" + "fra" // French
+ "fy" + "fry" // Frisian
+ "ga" + "gle" // Irish
+ "gd" + "gla" // Scottish Gaelic
+ "gl" + "glg" // Gallegan
+ "gn" + "grn" // Guarani
+ "gu" + "guj" // Gujarati
+ "gv" + "glv" // Manx
+ "ha" + "hau" // Hausa
+ "he" + "heb" // Hebrew
+ "hi" + "hin" // Hindi
+ "ho" + "hmo" // Hiri Motu
+ "hr" + "hrv" // Croatian
+ "ht" + "hat" // Haitian
+ "hu" + "hun" // Hungarian
+ "hy" + "hye" // Armenian
+ "hz" + "her" // Herero
+ "ia" + "ina" // Interlingua
+ "id" + "ind" // Indonesian
+ "ie" + "ile" // Interlingue
+ "ig" + "ibo" // Igbo
+ "ii" + "iii" // Sichuan Yi
+ "ik" + "ipk" // Inupiaq
+ "in" + "ind" // Indonesian (old)
+ "io" + "ido" // Ido
+ "is" + "isl" // Icelandic
+ "it" + "ita" // Italian
+ "iu" + "iku" // Inuktitut
+ "iw" + "heb" // Hebrew (old)
+ "ja" + "jpn" // Japanese
+ "ji" + "yid" // Yiddish (old)
+ "jv" + "jav" // Javanese
+ "ka" + "kat" // Georgian
+ "kg" + "kon" // Kongo
+ "ki" + "kik" // Kikuyu
+ "kj" + "kua" // Kwanyama
+ "kk" + "kaz" // Kazakh
+ "kl" + "kal" // Greenlandic
+ "km" + "khm" // Khmer
+ "kn" + "kan" // Kannada
+ "ko" + "kor" // Korean
+ "kr" + "kau" // Kanuri
+ "ks" + "kas" // Kashmiri
+ "ku" + "kur" // Kurdish
+ "kv" + "kom" // Komi
+ "kw" + "cor" // Cornish
+ "ky" + "kir" // Kirghiz
+ "la" + "lat" // Latin
+ "lb" + "ltz" // Luxembourgish
+ "lg" + "lug" // Ganda
+ "li" + "lim" // Limburgish
+ "ln" + "lin" // Lingala
+ "lo" + "lao" // Lao
+ "lt" + "lit" // Lithuanian
+ "lu" + "lub" // Luba-Katanga
+ "lv" + "lav" // Latvian
+ "mg" + "mlg" // Malagasy
+ "mh" + "mah" // Marshallese
+ "mi" + "mri" // Maori
+ "mk" + "mkd" // Macedonian
+ "ml" + "mal" // Malayalam
+ "mn" + "mon" // Mongolian
+ "mo" + "mol" // Moldavian
+ "mr" + "mar" // Marathi
+ "ms" + "msa" // Malay
+ "mt" + "mlt" // Maltese
+ "my" + "mya" // Burmese
+ "na" + "nau" // Nauru
+ "nb" + "nob" // Norwegian Bokm?l
+ "nd" + "nde" // North Ndebele
+ "ne" + "nep" // Nepali
+ "ng" + "ndo" // Ndonga
+ "nl" + "nld" // Dutch
+ "nn" + "nno" // Norwegian Nynorsk
+ "no" + "nor" // Norwegian
+ "nr" + "nbl" // South Ndebele
+ "nv" + "nav" // Navajo
+ "ny" + "nya" // Nyanja
+ "oc" + "oci" // Occitan
+ "oj" + "oji" // Ojibwa
+ "om" + "orm" // Oromo
+ "or" + "ori" // Oriya
+ "os" + "oss" // Ossetian
+ "pa" + "pan" // Panjabi
+ "pi" + "pli" // Pali
+ "pl" + "pol" // Polish
+ "ps" + "pus" // Pushto
+ "pt" + "por" // Portuguese
+ "qu" + "que" // Quechua
+ "rm" + "roh" // Raeto-Romance
+ "rn" + "run" // Rundi
+ "ro" + "ron" // Romanian
+ "ru" + "rus" // Russian
+ "rw" + "kin" // Kinyarwanda
+ "sa" + "san" // Sanskrit
+ "sc" + "srd" // Sardinian
+ "sd" + "snd" // Sindhi
+ "se" + "sme" // Northern Sami
+ "sg" + "sag" // Sango
+ "si" + "sin" // Sinhalese
+ "sk" + "slk" // Slovak
+ "sl" + "slv" // Slovenian
+ "sm" + "smo" // Samoan
+ "sn" + "sna" // Shona
+ "so" + "som" // Somali
+ "sq" + "sqi" // Albanian
+ "sr" + "srp" // Serbian
+ "ss" + "ssw" // Swati
+ "st" + "sot" // Southern Sotho
+ "su" + "sun" // Sundanese
+ "sv" + "swe" // Swedish
+ "sw" + "swa" // Swahili
+ "ta" + "tam" // Tamil
+ "te" + "tel" // Telugu
+ "tg" + "tgk" // Tajik
+ "th" + "tha" // Thai
+ "ti" + "tir" // Tigrinya
+ "tk" + "tuk" // Turkmen
+ "tl" + "tgl" // Tagalog
+ "tn" + "tsn" // Tswana
+ "to" + "ton" // Tonga
+ "tr" + "tur" // Turkish
+ "ts" + "tso" // Tsonga
+ "tt" + "tat" // Tatar
+ "tw" + "twi" // Twi
+ "ty" + "tah" // Tahitian
+ "ug" + "uig" // Uighur
+ "uk" + "ukr" // Ukrainian
+ "ur" + "urd" // Urdu
+ "uz" + "uzb" // Uzbek
+ "ve" + "ven" // Venda
+ "vi" + "vie" // Vietnamese
+ "vo" + "vol" // Volap?k
+ "wa" + "wln" // Walloon
+ "wo" + "wol" // Wolof
+ "xh" + "xho" // Xhosa
+ "yi" + "yid" // Yiddish
+ "yo" + "yor" // Yoruba
+ "za" + "zha" // Zhuang
+ "zh" + "zho" // Chinese
+ "zu" + "zul" // Zulu
;
/**
* The 2- and 3-letter ISO 3166 country codes.
*/
static final String isoCountryTable =
"AD" + "AND" // Andorra, Principality of
+ "AE" + "ARE" // United Arab Emirates
+ "AF" + "AFG" // Afghanistan
+ "AG" + "ATG" // Antigua and Barbuda
+ "AI" + "AIA" // Anguilla
+ "AL" + "ALB" // Albania, People's Socialist Republic of
+ "AM" + "ARM" // Armenia
// + "AN" + "ANT" // Netherlands Antilles
+ "AO" + "AGO" // Angola, Republic of
+ "AQ" + "ATA" // Antarctica (the territory South of 60 deg S)
+ "AR" + "ARG" // Argentina, Argentine Republic
+ "AS" + "ASM" // American Samoa
+ "AT" + "AUT" // Austria, Republic of
+ "AU" + "AUS" // Australia, Commonwealth of
+ "AW" + "ABW" // Aruba
+ "AX" + "ALA" // \u00c5land Islands
+ "AZ" + "AZE" // Azerbaijan, Republic of
+ "BA" + "BIH" // Bosnia and Herzegovina
+ "BB" + "BRB" // Barbados
+ "BD" + "BGD" // Bangladesh, People's Republic of
+ "BE" + "BEL" // Belgium, Kingdom of
+ "BF" + "BFA" // Burkina Faso
+ "BG" + "BGR" // Bulgaria, People's Republic of
+ "BH" + "BHR" // Bahrain, Kingdom of
+ "BI" + "BDI" // Burundi, Republic of
+ "BJ" + "BEN" // Benin, People's Republic of
+ "BL" + "BLM" // Saint Barth\u00e9lemy
+ "BM" + "BMU" // Bermuda
+ "BN" + "BRN" // Brunei Darussalam
+ "BO" + "BOL" // Bolivia, Republic of
+ "BQ" + "BES" // Bonaire, Sint Eustatius and Saba
+ "BR" + "BRA" // Brazil, Federative Republic of
+ "BS" + "BHS" // Bahamas, Commonwealth of the
+ "BT" + "BTN" // Bhutan, Kingdom of
+ "BV" + "BVT" // Bouvet Island (Bouvetoya)
+ "BW" + "BWA" // Botswana, Republic of
+ "BY" + "BLR" // Belarus
+ "BZ" + "BLZ" // Belize
+ "CA" + "CAN" // Canada
+ "CC" + "CCK" // Cocos (Keeling) Islands
+ "CD" + "COD" // Congo, Democratic Republic of
+ "CF" + "CAF" // Central African Republic
+ "CG" + "COG" // Congo, People's Republic of
+ "CH" + "CHE" // Switzerland, Swiss Confederation
+ "CI" + "CIV" // Cote D'Ivoire, Ivory Coast, Republic of the
+ "CK" + "COK" // Cook Islands
+ "CL" + "CHL" // Chile, Republic of
+ "CM" + "CMR" // Cameroon, United Republic of
+ "CN" + "CHN" // China, People's Republic of
+ "CO" + "COL" // Colombia, Republic of
+ "CR" + "CRI" // Costa Rica, Republic of
// + "CS" + "SCG" // Serbia and Montenegro
+ "CU" + "CUB" // Cuba, Republic of
+ "CV" + "CPV" // Cape Verde, Republic of
+ "CW" + "CUW" // Cura\u00e7ao
+ "CX" + "CXR" // Christmas Island
+ "CY" + "CYP" // Cyprus, Republic of
+ "CZ" + "CZE" // Czech Republic
+ "DE" + "DEU" // Germany
+ "DJ" + "DJI" // Djibouti, Republic of
+ "DK" + "DNK" // Denmark, Kingdom of
+ "DM" + "DMA" // Dominica, Commonwealth of
+ "DO" + "DOM" // Dominican Republic
+ "DZ" + "DZA" // Algeria, People's Democratic Republic of
+ "EC" + "ECU" // Ecuador, Republic of
+ "EE" + "EST" // Estonia
+ "EG" + "EGY" // Egypt, Arab Republic of
+ "EH" + "ESH" // Western Sahara
+ "ER" + "ERI" // Eritrea
+ "ES" + "ESP" // Spain, Spanish State
+ "ET" + "ETH" // Ethiopia
+ "FI" + "FIN" // Finland, Republic of
+ "FJ" + "FJI" // Fiji, Republic of the Fiji Islands
+ "FK" + "FLK" // Falkland Islands (Malvinas)
+ "FM" + "FSM" // Micronesia, Federated States of
+ "FO" + "FRO" // Faeroe Islands
+ "FR" + "FRA" // France, French Republic
+ "GA" + "GAB" // Gabon, Gabonese Republic
+ "GB" + "GBR" // United Kingdom of Great Britain & N. Ireland
+ "GD" + "GRD" // Grenada
+ "GE" + "GEO" // Georgia
+ "GF" + "GUF" // French Guiana
+ "GG" + "GGY" // Guernsey
+ "GH" + "GHA" // Ghana, Republic of
+ "GI" + "GIB" // Gibraltar
+ "GL" + "GRL" // Greenland
+ "GM" + "GMB" // Gambia, Republic of the
+ "GN" + "GIN" // Guinea, Revolutionary People's Rep'c of
+ "GP" + "GLP" // Guadaloupe
+ "GQ" + "GNQ" // Equatorial Guinea, Republic of
+ "GR" + "GRC" // Greece, Hellenic Republic
+ "GS" + "SGS" // South Georgia and the South Sandwich Islands
+ "GT" + "GTM" // Guatemala, Republic of
+ "GU" + "GUM" // Guam
+ "GW" + "GNB" // Guinea-Bissau, Republic of
+ "GY" + "GUY" // Guyana, Republic of
+ "HK" + "HKG" // Hong Kong, Special Administrative Region of China
+ "HM" + "HMD" // Heard and McDonald Islands
+ "HN" + "HND" // Honduras, Republic of
+ "HR" + "HRV" // Hrvatska (Croatia)
+ "HT" + "HTI" // Haiti, Republic of
+ "HU" + "HUN" // Hungary, Hungarian People's Republic
+ "ID" + "IDN" // Indonesia, Republic of
+ "IE" + "IRL" // Ireland
+ "IL" + "ISR" // Israel, State of
+ "IM" + "IMN" // Isle of Man
+ "IN" + "IND" // India, Republic of
+ "IO" + "IOT" // British Indian Ocean Territory (Chagos Archipelago)
+ "IQ" + "IRQ" // Iraq, Republic of
+ "IR" + "IRN" // Iran, Islamic Republic of
+ "IS" + "ISL" // Iceland, Republic of
+ "IT" + "ITA" // Italy, Italian Republic
+ "JE" + "JEY" // Jersey
+ "JM" + "JAM" // Jamaica
+ "JO" + "JOR" // Jordan, Hashemite Kingdom of
+ "JP" + "JPN" // Japan
+ "KE" + "KEN" // Kenya, Republic of
+ "KG" + "KGZ" // Kyrgyz Republic
+ "KH" + "KHM" // Cambodia, Kingdom of
+ "KI" + "KIR" // Kiribati, Republic of
+ "KM" + "COM" // Comoros, Union of the
+ "KN" + "KNA" // St. Kitts and Nevis
+ "KP" + "PRK" // Korea, Democratic People's Republic of
+ "KR" + "KOR" // Korea, Republic of
+ "KW" + "KWT" // Kuwait, State of
+ "KY" + "CYM" // Cayman Islands
+ "KZ" + "KAZ" // Kazakhstan, Republic of
+ "LA" + "LAO" // Lao People's Democratic Republic
+ "LB" + "LBN" // Lebanon, Lebanese Republic
+ "LC" + "LCA" // St. Lucia
+ "LI" + "LIE" // Liechtenstein, Principality of
+ "LK" + "LKA" // Sri Lanka, Democratic Socialist Republic of
+ "LR" + "LBR" // Liberia, Republic of
+ "LS" + "LSO" // Lesotho, Kingdom of
+ "LT" + "LTU" // Lithuania
+ "LU" + "LUX" // Luxembourg, Grand Duchy of
+ "LV" + "LVA" // Latvia
+ "LY" + "LBY" // Libyan Arab Jamahiriya
+ "MA" + "MAR" // Morocco, Kingdom of
+ "MC" + "MCO" // Monaco, Principality of
+ "MD" + "MDA" // Moldova, Republic of
+ "ME" + "MNE" // Montenegro, Republic of
+ "MF" + "MAF" // Saint Martin
+ "MG" + "MDG" // Madagascar, Republic of
+ "MH" + "MHL" // Marshall Islands
+ "MK" + "MKD" // Macedonia, the former Yugoslav Republic of
+ "ML" + "MLI" // Mali, Republic of
+ "MM" + "MMR" // Myanmar
+ "MN" + "MNG" // Mongolia, Mongolian People's Republic
+ "MO" + "MAC" // Macao, Special Administrative Region of China
+ "MP" + "MNP" // Northern Mariana Islands
+ "MQ" + "MTQ" // Martinique
+ "MR" + "MRT" // Mauritania, Islamic Republic of
+ "MS" + "MSR" // Montserrat
+ "MT" + "MLT" // Malta, Republic of
+ "MU" + "MUS" // Mauritius
+ "MV" + "MDV" // Maldives, Republic of
+ "MW" + "MWI" // Malawi, Republic of
+ "MX" + "MEX" // Mexico, United Mexican States
+ "MY" + "MYS" // Malaysia
+ "MZ" + "MOZ" // Mozambique, People's Republic of
+ "NA" + "NAM" // Namibia
+ "NC" + "NCL" // New Caledonia
+ "NE" + "NER" // Niger, Republic of the
+ "NF" + "NFK" // Norfolk Island
+ "NG" + "NGA" // Nigeria, Federal Republic of
+ "NI" + "NIC" // Nicaragua, Republic of
+ "NL" + "NLD" // Netherlands, Kingdom of the
+ "NO" + "NOR" // Norway, Kingdom of
+ "NP" + "NPL" // Nepal, Kingdom of
+ "NR" + "NRU" // Nauru, Republic of
+ "NU" + "NIU" // Niue, Republic of
+ "NZ" + "NZL" // New Zealand
+ "OM" + "OMN" // Oman, Sultanate of
+ "PA" + "PAN" // Panama, Republic of
+ "PE" + "PER" // Peru, Republic of
+ "PF" + "PYF" // French Polynesia
+ "PG" + "PNG" // Papua New Guinea
+ "PH" + "PHL" // Philippines, Republic of the
+ "PK" + "PAK" // Pakistan, Islamic Republic of
+ "PL" + "POL" // Poland, Republic of Poland
+ "PM" + "SPM" // St. Pierre and Miquelon
+ "PN" + "PCN" // Pitcairn Island
+ "PR" + "PRI" // Puerto Rico
+ "PS" + "PSE" // Palestinian Territory, Occupied
+ "PT" + "PRT" // Portugal, Portuguese Republic
+ "PW" + "PLW" // Palau
+ "PY" + "PRY" // Paraguay, Republic of
+ "QA" + "QAT" // Qatar, State of
+ "RE" + "REU" // Reunion
+ "RO" + "ROU" // Romania, Socialist Republic of
+ "RS" + "SRB" // Serbia, Republic of
+ "RU" + "RUS" // Russian Federation
+ "RW" + "RWA" // Rwanda, Rwandese Republic
+ "SA" + "SAU" // Saudi Arabia, Kingdom of
+ "SB" + "SLB" // Solomon Islands
+ "SC" + "SYC" // Seychelles, Republic of
+ "SD" + "SDN" // Sudan, Democratic Republic of the
+ "SE" + "SWE" // Sweden, Kingdom of
+ "SG" + "SGP" // Singapore, Republic of
+ "SH" + "SHN" // St. Helena
+ "SI" + "SVN" // Slovenia
+ "SJ" + "SJM" // Svalbard & Jan Mayen Islands
+ "SK" + "SVK" // Slovakia (Slovak Republic)
+ "SL" + "SLE" // Sierra Leone, Republic of
+ "SM" + "SMR" // San Marino, Republic of
+ "SN" + "SEN" // Senegal, Republic of
+ "SO" + "SOM" // Somalia, Somali Republic
+ "SR" + "SUR" // Suriname, Republic of
+ "SS" + "SSD" // South Sudan
+ "ST" + "STP" // Sao Tome and Principe, Democratic Republic of
+ "SV" + "SLV" // El Salvador, Republic of
+ "SX" + "SXM" // Sint Maarten (Dutch part)
+ "SY" + "SYR" // Syrian Arab Republic
+ "SZ" + "SWZ" // Swaziland, Kingdom of
+ "TC" + "TCA" // Turks and Caicos Islands
+ "TD" + "TCD" // Chad, Republic of
+ "TF" + "ATF" // French Southern Territories
+ "TG" + "TGO" // Togo, Togolese Republic
+ "TH" + "THA" // Thailand, Kingdom of
+ "TJ" + "TJK" // Tajikistan
+ "TK" + "TKL" // Tokelau (Tokelau Islands)
+ "TL" + "TLS" // Timor-Leste, Democratic Republic of
+ "TM" + "TKM" // Turkmenistan
+ "TN" + "TUN" // Tunisia, Republic of
+ "TO" + "TON" // Tonga, Kingdom of
+ "TR" + "TUR" // Turkey, Republic of
+ "TT" + "TTO" // Trinidad and Tobago, Republic of
+ "TV" + "TUV" // Tuvalu
+ "TW" + "TWN" // Taiwan, Province of China
+ "TZ" + "TZA" // Tanzania, United Republic of
+ "UA" + "UKR" // Ukraine
+ "UG" + "UGA" // Uganda, Republic of
+ "UM" + "UMI" // United States Minor Outlying Islands
+ "US" + "USA" // United States of America
+ "UY" + "URY" // Uruguay, Eastern Republic of
+ "UZ" + "UZB" // Uzbekistan
+ "VA" + "VAT" // Holy See (Vatican City State)
+ "VC" + "VCT" // St. Vincent and the Grenadines
+ "VE" + "VEN" // Venezuela, Bolivarian Republic of
+ "VG" + "VGB" // British Virgin Islands
+ "VI" + "VIR" // US Virgin Islands
+ "VN" + "VNM" // Viet Nam, Socialist Republic of
+ "VU" + "VUT" // Vanuatu
+ "WF" + "WLF" // Wallis and Futuna Islands
+ "WS" + "WSM" // Samoa, Independent State of
+ "YE" + "YEM" // Yemen
+ "YT" + "MYT" // Mayotte
+ "ZA" + "ZAF" // South Africa, Republic of
+ "ZM" + "ZMB" // Zambia, Republic of
+ "ZW" + "ZWE" // Zimbabwe
;
/**
* Array to hold country codes for ISO3166-3.
*/
static final String[] ISO3166_3 = {
"AIDJ", "ANHH", "BQAQ", "BUMM", "BYAA", "CSHH", "CSXX", "CTKI", "DDDE",
"DYBJ", "FQHH", "FXFR", "GEHH", "HVBF", "JTUM", "MIUM", "NHVU", "NQAQ",
"NTHH", "PCHH", "PUUM", "PZPA", "RHZW", "SKIN", "SUHH", "TPTL", "VDVN",
"WKUM", "YDYE", "YUCS", "ZRCD"
};
/**
* This method computes a set of ISO3166-1 alpha-3 country codes from
* existing isoCountryTable.
*/
static Set<String> computeISO3166_1Alpha3Countries() {
int tableLength = isoCountryTable.length();
String[] isoTable = new String[tableLength / 5];
for (int i = 0, index = 0; index < tableLength; i++, index += 5) {
isoTable[i] = isoCountryTable.substring(index + 2, index + 5);
}
return Set.of(isoTable);
}
private LocaleISOData() {
}
}

View file

@ -0,0 +1,181 @@
/*
* Copyright (c) 2012, 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;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
import java.util.stream.Collector;
/**
* A state object for collecting statistics such as count, min, max, sum, and
* average.
*
* <p>This class is designed to work with (though does not require)
* {@linkplain java.util.stream streams}. For example, you can compute
* summary statistics on a stream of longs with:
* <pre> {@code
* LongSummaryStatistics stats = longStream.collect(LongSummaryStatistics::new,
* LongSummaryStatistics::accept,
* LongSummaryStatistics::combine);
* }</pre>
*
* <p>{@code LongSummaryStatistics} can be used as a
* {@linkplain java.util.stream.Stream#collect(Collector) reduction}
* target for a {@linkplain java.util.stream.Stream stream}. For example:
*
* <pre> {@code
* LongSummaryStatistics stats = people.stream()
* .collect(Collectors.summarizingLong(Person::getAge));
*}</pre>
*
* This computes, in a single pass, the count of people, as well as the minimum,
* maximum, sum, and average of their ages.
*
* @implNote This implementation is not thread safe. However, it is safe to use
* {@link java.util.stream.Collectors#summarizingLong(java.util.function.ToLongFunction)
* Collectors.summarizingLong()} on a parallel stream, because the parallel
* implementation of {@link java.util.stream.Stream#collect Stream.collect()}
* provides the necessary partitioning, isolation, and merging of results for
* safe and efficient parallel execution.
*
* <p>This implementation does not check for overflow of the sum.
* @since 1.8
*/
public class LongSummaryStatistics implements LongConsumer, IntConsumer {
private long count;
private long sum;
private long min = Long.MAX_VALUE;
private long max = Long.MIN_VALUE;
/**
* Construct an empty instance with zero count, zero sum,
* {@code Long.MAX_VALUE} min, {@code Long.MIN_VALUE} max and zero
* average.
*/
public LongSummaryStatistics() { }
/**
* Records a new {@code int} value into the summary information.
*
* @param value the input value
*/
@Override
public void accept(int value) {
accept((long) value);
}
/**
* Records a new {@code long} value into the summary information.
*
* @param value the input value
*/
@Override
public void accept(long value) {
++count;
sum += value;
min = Math.min(min, value);
max = Math.max(max, value);
}
/**
* Combines the state of another {@code LongSummaryStatistics} into this
* one.
*
* @param other another {@code LongSummaryStatistics}
* @throws NullPointerException if {@code other} is null
*/
public void combine(LongSummaryStatistics other) {
count += other.count;
sum += other.sum;
min = Math.min(min, other.min);
max = Math.max(max, other.max);
}
/**
* Returns the count of values recorded.
*
* @return the count of values
*/
public final long getCount() {
return count;
}
/**
* Returns the sum of values recorded, or zero if no values have been
* recorded.
*
* @return the sum of values, or zero if none
*/
public final long getSum() {
return sum;
}
/**
* Returns the minimum value recorded, or {@code Long.MAX_VALUE} if no
* values have been recorded.
*
* @return the minimum value, or {@code Long.MAX_VALUE} if none
*/
public final long getMin() {
return min;
}
/**
* Returns the maximum value recorded, or {@code Long.MIN_VALUE} if no
* values have been recorded
*
* @return the maximum value, or {@code Long.MIN_VALUE} if none
*/
public final long getMax() {
return max;
}
/**
* Returns the arithmetic mean of values recorded, or zero if no values have been
* recorded.
*
* @return The arithmetic mean of values, or zero if none
*/
public final double getAverage() {
return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
}
/**
* Returns a non-empty string representation of this object suitable for
* debugging. The exact presentation format is unspecified and may vary
* between implementations and versions.
*/
@Override
public String toString() {
return String.format(
"%s{count=%d, sum=%d, min=%d, average=%f, max=%d}",
this.getClass().getSimpleName(),
getCount(),
getSum(),
getMin(),
getAverage(),
getMax());
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2003, 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;
/**
* Unchecked exception thrown when there is a format specifier which does not
* have a corresponding argument or if an argument index refers to an argument
* that does not exist.
*
* <p> Unless otherwise specified, passing a {@code null} argument to any
* method or constructor in this class will cause a {@link
* NullPointerException} to be thrown.
*
* @since 1.5
*/
public class MissingFormatArgumentException extends IllegalFormatException {
private static final long serialVersionUID = 19190115L;
private String s;
/**
* Constructs an instance of this class with the unmatched format
* specifier.
*
* @param s
* Format specifier which does not have a corresponding argument
*/
public MissingFormatArgumentException(String s) {
if (s == null)
throw new NullPointerException();
this.s = s;
}
/**
* Returns the unmatched format specifier.
*
* @return The unmatched format specifier
*/
public String getFormatSpecifier() {
return s;
}
public String getMessage() {
return "Format specifier '" + s + "'";
}
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2003, 2013, 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;
/**
* Unchecked exception thrown when the format width is required.
*
* <p> Unless otherwise specified, passing a {@code null} argument to any
* method or constructor in this class will cause a {@link
* NullPointerException} to be thrown.
*
* @since 1.5
*/
public class MissingFormatWidthException extends IllegalFormatException {
private static final long serialVersionUID = 15560123L;
private String s;
/**
* Constructs an instance of this class with the specified format
* specifier.
*
* @param s
* The format specifier which does not have a width
*/
public MissingFormatWidthException(String s) {
if (s == null)
throw new NullPointerException();
this.s = s;
}
/**
* Returns the format specifier which does not have a width.
*
* @return The format specifier which does not have a width
*/
public String getFormatSpecifier() {
return s;
}
public String getMessage() {
return s;
}
}

View file

@ -0,0 +1,124 @@
/*
* Copyright (c) 1996, 2005, 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.
*/
/*
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
*
* The original version of this source code and documentation
* is copyrighted and owned by Taligent, Inc., a wholly-owned
* subsidiary of IBM. These materials are provided under terms
* of a License Agreement between Taligent and Sun. This technology
* is protected by multiple US and International patents.
*
* This notice and attribution to Taligent may not be removed.
* Taligent is a registered trademark of Taligent, Inc.
*
*/
package java.util;
/**
* Signals that a resource is missing.
* @see java.lang.Exception
* @see ResourceBundle
* @author Mark Davis
* @since 1.1
*/
public
class MissingResourceException extends RuntimeException {
/**
* Constructs a MissingResourceException with the specified information.
* A detail message is a String that describes this particular exception.
* @param s the detail message
* @param className the name of the resource class
* @param key the key for the missing resource.
*/
public MissingResourceException(String s, String className, String key) {
super(s);
this.className = className;
this.key = key;
}
/**
* Constructs a {@code MissingResourceException} with
* {@code message}, {@code className}, {@code key},
* and {@code cause}. This constructor is package private for
* use by {@code ResourceBundle.getBundle}.
*
* @param message
* the detail message
* @param className
* the name of the resource class
* @param key
* the key for the missing resource.
* @param cause
* the cause (which is saved for later retrieval by the
* {@link Throwable.getCause()} method). (A null value is
* permitted, and indicates that the cause is nonexistent
* or unknown.)
*/
MissingResourceException(String message, String className, String key, Throwable cause) {
super(message, cause);
this.className = className;
this.key = key;
}
/**
* Gets parameter passed by constructor.
*
* @return the name of the resource class
*/
public String getClassName() {
return className;
}
/**
* Gets parameter passed by constructor.
*
* @return the key for the missing resource
*/
public String getKey() {
return key;
}
//============ privates ============
// serialization compatibility with JDK1.1
private static final long serialVersionUID = -4876345176062000401L;
/**
* The class name of the resource bundle requested by the user.
* @serial
*/
private String className;
/**
* The name of the specific resource requested by the user.
* @serial
*/
private String key;
}

View file

@ -0,0 +1,426 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Written by Doug Lea and Josh Bloch with assistance from members of JCP
* JSR-166 Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
package java.util;
/**
* A {@link SortedMap} extended with navigation methods returning the
* closest matches for given search targets. Methods
* {@link #lowerEntry}, {@link #floorEntry}, {@link #ceilingEntry},
* and {@link #higherEntry} return {@code Map.Entry} objects
* associated with keys respectively less than, less than or equal,
* greater than or equal, and greater than a given key, returning
* {@code null} if there is no such key. Similarly, methods
* {@link #lowerKey}, {@link #floorKey}, {@link #ceilingKey}, and
* {@link #higherKey} return only the associated keys. All of these
* methods are designed for locating, not traversing entries.
*
* <p>A {@code NavigableMap} may be accessed and traversed in either
* ascending or descending key order. The {@link #descendingMap}
* method returns a view of the map with the senses of all relational
* and directional methods inverted. The performance of ascending
* operations and views is likely to be faster than that of descending
* ones. Methods
* {@link #subMap(Object, boolean, Object, boolean) subMap(K, boolean, K, boolean)},
* {@link #headMap(Object, boolean) headMap(K, boolean)}, and
* {@link #tailMap(Object, boolean) tailMap(K, boolean)}
* differ from the like-named {@code SortedMap} methods in accepting
* additional arguments describing whether lower and upper bounds are
* inclusive versus exclusive. Submaps of any {@code NavigableMap}
* must implement the {@code NavigableMap} interface.
*
* <p>This interface additionally defines methods {@link #firstEntry},
* {@link #pollFirstEntry}, {@link #lastEntry}, and
* {@link #pollLastEntry} that return and/or remove the least and
* greatest mappings, if any exist, else returning {@code null}.
*
* <p>Implementations of entry-returning methods are expected to
* return {@code Map.Entry} pairs representing snapshots of mappings
* at the time they were produced, and thus generally do <em>not</em>
* support the optional {@code Entry.setValue} method. Note however
* that it is possible to change mappings in the associated map using
* method {@code put}.
*
* <p>Methods
* {@link #subMap(Object, Object) subMap(K, K)},
* {@link #headMap(Object) headMap(K)}, and
* {@link #tailMap(Object) tailMap(K)}
* are specified to return {@code SortedMap} to allow existing
* implementations of {@code SortedMap} to be compatibly retrofitted to
* implement {@code NavigableMap}, but extensions and implementations
* of this interface are encouraged to override these methods to return
* {@code NavigableMap}. Similarly,
* {@link #keySet()} can be overridden to return {@link NavigableSet}.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Doug Lea
* @author Josh Bloch
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
* @since 1.6
*/
public interface NavigableMap<K,V> extends SortedMap<K,V> {
/**
* Returns a key-value mapping associated with the greatest key
* strictly less than the given key, or {@code null} if there is
* no such key.
*
* @param key the key
* @return an entry with the greatest key less than {@code key},
* or {@code null} if there is no such key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map does not permit null keys
*/
Map.Entry<K,V> lowerEntry(K key);
/**
* Returns the greatest key strictly less than the given key, or
* {@code null} if there is no such key.
*
* @param key the key
* @return the greatest key less than {@code key},
* or {@code null} if there is no such key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map does not permit null keys
*/
K lowerKey(K key);
/**
* Returns a key-value mapping associated with the greatest key
* less than or equal to the given key, or {@code null} if there
* is no such key.
*
* @param key the key
* @return an entry with the greatest key less than or equal to
* {@code key}, or {@code null} if there is no such key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map does not permit null keys
*/
Map.Entry<K,V> floorEntry(K key);
/**
* Returns the greatest key less than or equal to the given key,
* or {@code null} if there is no such key.
*
* @param key the key
* @return the greatest key less than or equal to {@code key},
* or {@code null} if there is no such key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map does not permit null keys
*/
K floorKey(K key);
/**
* Returns a key-value mapping associated with the least key
* greater than or equal to the given key, or {@code null} if
* there is no such key.
*
* @param key the key
* @return an entry with the least key greater than or equal to
* {@code key}, or {@code null} if there is no such key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map does not permit null keys
*/
Map.Entry<K,V> ceilingEntry(K key);
/**
* Returns the least key greater than or equal to the given key,
* or {@code null} if there is no such key.
*
* @param key the key
* @return the least key greater than or equal to {@code key},
* or {@code null} if there is no such key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map does not permit null keys
*/
K ceilingKey(K key);
/**
* Returns a key-value mapping associated with the least key
* strictly greater than the given key, or {@code null} if there
* is no such key.
*
* @param key the key
* @return an entry with the least key greater than {@code key},
* or {@code null} if there is no such key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map does not permit null keys
*/
Map.Entry<K,V> higherEntry(K key);
/**
* Returns the least key strictly greater than the given key, or
* {@code null} if there is no such key.
*
* @param key the key
* @return the least key greater than {@code key},
* or {@code null} if there is no such key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map does not permit null keys
*/
K higherKey(K key);
/**
* Returns a key-value mapping associated with the least
* key in this map, or {@code null} if the map is empty.
*
* @return an entry with the least key,
* or {@code null} if this map is empty
*/
Map.Entry<K,V> firstEntry();
/**
* Returns a key-value mapping associated with the greatest
* key in this map, or {@code null} if the map is empty.
*
* @return an entry with the greatest key,
* or {@code null} if this map is empty
*/
Map.Entry<K,V> lastEntry();
/**
* Removes and returns a key-value mapping associated with
* the least key in this map, or {@code null} if the map is empty.
*
* @return the removed first entry of this map,
* or {@code null} if this map is empty
*/
Map.Entry<K,V> pollFirstEntry();
/**
* Removes and returns a key-value mapping associated with
* the greatest key in this map, or {@code null} if the map is empty.
*
* @return the removed last entry of this map,
* or {@code null} if this map is empty
*/
Map.Entry<K,V> pollLastEntry();
/**
* Returns a reverse order view of the mappings contained in this map.
* The descending map is backed by this map, so changes to the map are
* reflected in the descending map, and vice-versa. If either map is
* modified while an iteration over a collection view of either map
* is in progress (except through the iterator's own {@code remove}
* operation), the results of the iteration are undefined.
*
* <p>The returned map has an ordering equivalent to
* {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
* The expression {@code m.descendingMap().descendingMap()} returns a
* view of {@code m} essentially equivalent to {@code m}.
*
* @return a reverse order view of this map
*/
NavigableMap<K,V> descendingMap();
/**
* Returns a {@link NavigableSet} view of the keys contained in this map.
* The set's iterator returns the keys in ascending order.
* The set is backed by the map, so changes to the map are reflected in
* the set, and vice-versa. If the map is modified while an iteration
* over the set is in progress (except through the iterator's own {@code
* remove} operation), the results of the iteration are undefined. The
* set supports element removal, which removes the corresponding mapping
* from the map, via the {@code Iterator.remove}, {@code Set.remove},
* {@code removeAll}, {@code retainAll}, and {@code clear} operations.
* It does not support the {@code add} or {@code addAll} operations.
*
* @return a navigable set view of the keys in this map
*/
NavigableSet<K> navigableKeySet();
/**
* Returns a reverse order {@link NavigableSet} view of the keys contained in this map.
* The set's iterator returns the keys in descending order.
* The set is backed by the map, so changes to the map are reflected in
* the set, and vice-versa. If the map is modified while an iteration
* over the set is in progress (except through the iterator's own {@code
* remove} operation), the results of the iteration are undefined. The
* set supports element removal, which removes the corresponding mapping
* from the map, via the {@code Iterator.remove}, {@code Set.remove},
* {@code removeAll}, {@code retainAll}, and {@code clear} operations.
* It does not support the {@code add} or {@code addAll} operations.
*
* @return a reverse order navigable set view of the keys in this map
*/
NavigableSet<K> descendingKeySet();
/**
* Returns a view of the portion of this map whose keys range from
* {@code fromKey} to {@code toKey}. If {@code fromKey} and
* {@code toKey} are equal, the returned map is empty unless
* {@code fromInclusive} and {@code toInclusive} are both true. The
* returned map is backed by this map, so changes in the returned map are
* reflected in this map, and vice-versa. The returned map supports all
* optional map operations that this map supports.
*
* <p>The returned map will throw an {@code IllegalArgumentException}
* on an attempt to insert a key outside of its range, or to construct a
* submap either of whose endpoints lie outside its range.
*
* @param fromKey low endpoint of the keys in the returned map
* @param fromInclusive {@code true} if the low endpoint
* is to be included in the returned view
* @param toKey high endpoint of the keys in the returned map
* @param toInclusive {@code true} if the high endpoint
* is to be included in the returned view
* @return a view of the portion of this map whose keys range from
* {@code fromKey} to {@code toKey}
* @throws ClassCastException if {@code fromKey} and {@code toKey}
* cannot be compared to one another using this map's comparator
* (or, if the map has no comparator, using natural ordering).
* Implementations may, but are not required to, throw this
* exception if {@code fromKey} or {@code toKey}
* cannot be compared to keys currently in the map.
* @throws NullPointerException if {@code fromKey} or {@code toKey}
* is null and this map does not permit null keys
* @throws IllegalArgumentException if {@code fromKey} is greater than
* {@code toKey}; or if this map itself has a restricted
* range, and {@code fromKey} or {@code toKey} lies
* outside the bounds of the range
*/
NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
K toKey, boolean toInclusive);
/**
* Returns a view of the portion of this map whose keys are less than (or
* equal to, if {@code inclusive} is true) {@code toKey}. The returned
* map is backed by this map, so changes in the returned map are reflected
* in this map, and vice-versa. The returned map supports all optional
* map operations that this map supports.
*
* <p>The returned map will throw an {@code IllegalArgumentException}
* on an attempt to insert a key outside its range.
*
* @param toKey high endpoint of the keys in the returned map
* @param inclusive {@code true} if the high endpoint
* is to be included in the returned view
* @return a view of the portion of this map whose keys are less than
* (or equal to, if {@code inclusive} is true) {@code toKey}
* @throws ClassCastException if {@code toKey} is not compatible
* with this map's comparator (or, if the map has no comparator,
* if {@code toKey} does not implement {@link Comparable}).
* Implementations may, but are not required to, throw this
* exception if {@code toKey} cannot be compared to keys
* currently in the map.
* @throws NullPointerException if {@code toKey} is null
* and this map does not permit null keys
* @throws IllegalArgumentException if this map itself has a
* restricted range, and {@code toKey} lies outside the
* bounds of the range
*/
NavigableMap<K,V> headMap(K toKey, boolean inclusive);
/**
* Returns a view of the portion of this map whose keys are greater than (or
* equal to, if {@code inclusive} is true) {@code fromKey}. The returned
* map is backed by this map, so changes in the returned map are reflected
* in this map, and vice-versa. The returned map supports all optional
* map operations that this map supports.
*
* <p>The returned map will throw an {@code IllegalArgumentException}
* on an attempt to insert a key outside its range.
*
* @param fromKey low endpoint of the keys in the returned map
* @param inclusive {@code true} if the low endpoint
* is to be included in the returned view
* @return a view of the portion of this map whose keys are greater than
* (or equal to, if {@code inclusive} is true) {@code fromKey}
* @throws ClassCastException if {@code fromKey} is not compatible
* with this map's comparator (or, if the map has no comparator,
* if {@code fromKey} does not implement {@link Comparable}).
* Implementations may, but are not required to, throw this
* exception if {@code fromKey} cannot be compared to keys
* currently in the map.
* @throws NullPointerException if {@code fromKey} is null
* and this map does not permit null keys
* @throws IllegalArgumentException if this map itself has a
* restricted range, and {@code fromKey} lies outside the
* bounds of the range
*/
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
/**
* {@inheritDoc}
*
* <p>Equivalent to {@code subMap(fromKey, true, toKey, false)}.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
SortedMap<K,V> subMap(K fromKey, K toKey);
/**
* {@inheritDoc}
*
* <p>Equivalent to {@code headMap(toKey, false)}.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
SortedMap<K,V> headMap(K toKey);
/**
* {@inheritDoc}
*
* <p>Equivalent to {@code tailMap(fromKey, true)}.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
SortedMap<K,V> tailMap(K fromKey);
}

View file

@ -0,0 +1,323 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Written by Doug Lea and Josh Bloch with assistance from members of JCP
* JSR-166 Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
package java.util;
/**
* A {@link SortedSet} extended with navigation methods reporting
* closest matches for given search targets. Methods {@link #lower},
* {@link #floor}, {@link #ceiling}, and {@link #higher} return elements
* respectively less than, less than or equal, greater than or equal,
* and greater than a given element, returning {@code null} if there
* is no such element.
*
* <p>A {@code NavigableSet} may be accessed and traversed in either
* ascending or descending order. The {@link #descendingSet} method
* returns a view of the set with the senses of all relational and
* directional methods inverted. The performance of ascending
* operations and views is likely to be faster than that of descending
* ones. This interface additionally defines methods {@link
* #pollFirst} and {@link #pollLast} that return and remove the lowest
* and highest element, if one exists, else returning {@code null}.
* Methods
* {@link #subSet(Object, boolean, Object, boolean) subSet(E, boolean, E, boolean)},
* {@link #headSet(Object, boolean) headSet(E, boolean)}, and
* {@link #tailSet(Object, boolean) tailSet(E, boolean)}
* differ from the like-named {@code SortedSet} methods in accepting
* additional arguments describing whether lower and upper bounds are
* inclusive versus exclusive. Subsets of any {@code NavigableSet}
* must implement the {@code NavigableSet} interface.
*
* <p>The return values of navigation methods may be ambiguous in
* implementations that permit {@code null} elements. However, even
* in this case the result can be disambiguated by checking
* {@code contains(null)}. To avoid such issues, implementations of
* this interface are encouraged to <em>not</em> permit insertion of
* {@code null} elements. (Note that sorted sets of {@link
* Comparable} elements intrinsically do not permit {@code null}.)
*
* <p>Methods
* {@link #subSet(Object, Object) subSet(E, E)},
* {@link #headSet(Object) headSet(E)}, and
* {@link #tailSet(Object) tailSet(E)}
* are specified to return {@code SortedSet} to allow existing
* implementations of {@code SortedSet} to be compatibly retrofitted to
* implement {@code NavigableSet}, but extensions and implementations
* of this interface are encouraged to override these methods to return
* {@code NavigableSet}.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Doug Lea
* @author Josh Bloch
* @param <E> the type of elements maintained by this set
* @since 1.6
*/
public interface NavigableSet<E> extends SortedSet<E> {
/**
* Returns the greatest element in this set strictly less than the
* given element, or {@code null} if there is no such element.
*
* @param e the value to match
* @return the greatest element less than {@code e},
* or {@code null} if there is no such element
* @throws ClassCastException if the specified element cannot be
* compared with the elements currently in the set
* @throws NullPointerException if the specified element is null
* and this set does not permit null elements
*/
E lower(E e);
/**
* Returns the greatest element in this set less than or equal to
* the given element, or {@code null} if there is no such element.
*
* @param e the value to match
* @return the greatest element less than or equal to {@code e},
* or {@code null} if there is no such element
* @throws ClassCastException if the specified element cannot be
* compared with the elements currently in the set
* @throws NullPointerException if the specified element is null
* and this set does not permit null elements
*/
E floor(E e);
/**
* Returns the least element in this set greater than or equal to
* the given element, or {@code null} if there is no such element.
*
* @param e the value to match
* @return the least element greater than or equal to {@code e},
* or {@code null} if there is no such element
* @throws ClassCastException if the specified element cannot be
* compared with the elements currently in the set
* @throws NullPointerException if the specified element is null
* and this set does not permit null elements
*/
E ceiling(E e);
/**
* Returns the least element in this set strictly greater than the
* given element, or {@code null} if there is no such element.
*
* @param e the value to match
* @return the least element greater than {@code e},
* or {@code null} if there is no such element
* @throws ClassCastException if the specified element cannot be
* compared with the elements currently in the set
* @throws NullPointerException if the specified element is null
* and this set does not permit null elements
*/
E higher(E e);
/**
* Retrieves and removes the first (lowest) element,
* or returns {@code null} if this set is empty.
*
* @return the first element, or {@code null} if this set is empty
*/
E pollFirst();
/**
* Retrieves and removes the last (highest) element,
* or returns {@code null} if this set is empty.
*
* @return the last element, or {@code null} if this set is empty
*/
E pollLast();
/**
* Returns an iterator over the elements in this set, in ascending order.
*
* @return an iterator over the elements in this set, in ascending order
*/
Iterator<E> iterator();
/**
* Returns a reverse order view of the elements contained in this set.
* The descending set is backed by this set, so changes to the set are
* reflected in the descending set, and vice-versa. If either set is
* modified while an iteration over either set is in progress (except
* through the iterator's own {@code remove} operation), the results of
* the iteration are undefined.
*
* <p>The returned set has an ordering equivalent to
* {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
* The expression {@code s.descendingSet().descendingSet()} returns a
* view of {@code s} essentially equivalent to {@code s}.
*
* @return a reverse order view of this set
*/
NavigableSet<E> descendingSet();
/**
* Returns an iterator over the elements in this set, in descending order.
* Equivalent in effect to {@code descendingSet().iterator()}.
*
* @return an iterator over the elements in this set, in descending order
*/
Iterator<E> descendingIterator();
/**
* Returns a view of the portion of this set whose elements range from
* {@code fromElement} to {@code toElement}. If {@code fromElement} and
* {@code toElement} are equal, the returned set is empty unless {@code
* fromInclusive} and {@code toInclusive} are both true. The returned set
* is backed by this set, so changes in the returned set are reflected in
* this set, and vice-versa. The returned set supports all optional set
* operations that this set supports.
*
* <p>The returned set will throw an {@code IllegalArgumentException}
* on an attempt to insert an element outside its range.
*
* @param fromElement low endpoint of the returned set
* @param fromInclusive {@code true} if the low endpoint
* is to be included in the returned view
* @param toElement high endpoint of the returned set
* @param toInclusive {@code true} if the high endpoint
* is to be included in the returned view
* @return a view of the portion of this set whose elements range from
* {@code fromElement}, inclusive, to {@code toElement}, exclusive
* @throws ClassCastException if {@code fromElement} and
* {@code toElement} cannot be compared to one another using this
* set's comparator (or, if the set has no comparator, using
* natural ordering). Implementations may, but are not required
* to, throw this exception if {@code fromElement} or
* {@code toElement} cannot be compared to elements currently in
* the set.
* @throws NullPointerException if {@code fromElement} or
* {@code toElement} is null and this set does
* not permit null elements
* @throws IllegalArgumentException if {@code fromElement} is
* greater than {@code toElement}; or if this set itself
* has a restricted range, and {@code fromElement} or
* {@code toElement} lies outside the bounds of the range.
*/
NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
E toElement, boolean toInclusive);
/**
* Returns a view of the portion of this set whose elements are less than
* (or equal to, if {@code inclusive} is true) {@code toElement}. The
* returned set is backed by this set, so changes in the returned set are
* reflected in this set, and vice-versa. The returned set supports all
* optional set operations that this set supports.
*
* <p>The returned set will throw an {@code IllegalArgumentException}
* on an attempt to insert an element outside its range.
*
* @param toElement high endpoint of the returned set
* @param inclusive {@code true} if the high endpoint
* is to be included in the returned view
* @return a view of the portion of this set whose elements are less than
* (or equal to, if {@code inclusive} is true) {@code toElement}
* @throws ClassCastException if {@code toElement} is not compatible
* with this set's comparator (or, if the set has no comparator,
* if {@code toElement} does not implement {@link Comparable}).
* Implementations may, but are not required to, throw this
* exception if {@code toElement} cannot be compared to elements
* currently in the set.
* @throws NullPointerException if {@code toElement} is null and
* this set does not permit null elements
* @throws IllegalArgumentException if this set itself has a
* restricted range, and {@code toElement} lies outside the
* bounds of the range
*/
NavigableSet<E> headSet(E toElement, boolean inclusive);
/**
* Returns a view of the portion of this set whose elements are greater
* than (or equal to, if {@code inclusive} is true) {@code fromElement}.
* The returned set is backed by this set, so changes in the returned set
* are reflected in this set, and vice-versa. The returned set supports
* all optional set operations that this set supports.
*
* <p>The returned set will throw an {@code IllegalArgumentException}
* on an attempt to insert an element outside its range.
*
* @param fromElement low endpoint of the returned set
* @param inclusive {@code true} if the low endpoint
* is to be included in the returned view
* @return a view of the portion of this set whose elements are greater
* than or equal to {@code fromElement}
* @throws ClassCastException if {@code fromElement} is not compatible
* with this set's comparator (or, if the set has no comparator,
* if {@code fromElement} does not implement {@link Comparable}).
* Implementations may, but are not required to, throw this
* exception if {@code fromElement} cannot be compared to elements
* currently in the set.
* @throws NullPointerException if {@code fromElement} is null
* and this set does not permit null elements
* @throws IllegalArgumentException if this set itself has a
* restricted range, and {@code fromElement} lies outside the
* bounds of the range
*/
NavigableSet<E> tailSet(E fromElement, boolean inclusive);
/**
* {@inheritDoc}
*
* <p>Equivalent to {@code subSet(fromElement, true, toElement, false)}.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
SortedSet<E> subSet(E fromElement, E toElement);
/**
* {@inheritDoc}
*
* <p>Equivalent to {@code headSet(toElement, false)}.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
SortedSet<E> headSet(E toElement);
/**
* {@inheritDoc}
*
* <p>Equivalent to {@code tailSet(fromElement, true)}.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
SortedSet<E> tailSet(E fromElement);
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 1994, 2012, 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;
/**
* Thrown by various accessor methods to indicate that the element being requested
* does not exist.
*
* @author unascribed
* @see java.util.Enumeration#nextElement()
* @see java.util.Iterator#next()
* @since 1.0
*/
public
class NoSuchElementException extends RuntimeException {
private static final long serialVersionUID = 6769829250639411880L;
/**
* Constructs a {@code NoSuchElementException} with {@code null}
* as its error message string.
*/
public NoSuchElementException() {
super();
}
/**
* Constructs a {@code NoSuchElementException}, saving a reference
* to the error message string {@code s} for later retrieval by the
* {@code getMessage} method.
*
* @param s the detail message.
*/
public NoSuchElementException(String s) {
super(s);
}
}

View file

@ -0,0 +1,427 @@
/*
* Copyright (c) 2009, 2016, 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;
import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.ForceInline;
import java.util.function.Supplier;
/**
* This class consists of {@code static} utility methods for operating
* on objects, or checking certain conditions before operation. These utilities
* include {@code null}-safe or {@code null}-tolerant methods for computing the
* hash code of an object, returning a string for an object, comparing two
* objects, and checking if indexes or sub-range values are out-of-bounds.
*
* @apiNote
* Static methods such as {@link Objects#checkIndex},
* {@link Objects#checkFromToIndex}, and {@link Objects#checkFromIndexSize} are
* provided for the convenience of checking if values corresponding to indexes
* and sub-ranges are out-of-bounds.
* Variations of these static methods support customization of the runtime
* exception, and corresponding exception detail message, that is thrown when
* values are out-of-bounds. Such methods accept a functional interface
* argument, instances of {@code BiFunction}, that maps out-of-bound values to a
* runtime exception. Care should be taken when using such methods in
* combination with an argument that is a lambda expression, method reference or
* class that capture values. In such cases the cost of capture, related to
* functional interface allocation, may exceed the cost of checking bounds.
*
* @since 1.7
*/
public final class Objects {
private Objects() {
throw new AssertionError("No java.util.Objects instances for you!");
}
/**
* Returns {@code true} if the arguments are equal to each other
* and {@code false} otherwise.
* Consequently, if both arguments are {@code null}, {@code true}
* is returned and if exactly one argument is {@code null}, {@code
* false} is returned. Otherwise, equality is determined by using
* the {@link Object#equals equals} method of the first
* argument.
*
* @param a an object
* @param b an object to be compared with {@code a} for equality
* @return {@code true} if the arguments are equal to each other
* and {@code false} otherwise
* @see Object#equals(Object)
*/
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
/**
* Returns {@code true} if the arguments are deeply equal to each other
* and {@code false} otherwise.
*
* Two {@code null} values are deeply equal. If both arguments are
* arrays, the algorithm in {@link Arrays#deepEquals(Object[],
* Object[]) Arrays.deepEquals} is used to determine equality.
* Otherwise, equality is determined by using the {@link
* Object#equals equals} method of the first argument.
*
* @param a an object
* @param b an object to be compared with {@code a} for deep equality
* @return {@code true} if the arguments are deeply equal to each other
* and {@code false} otherwise
* @see Arrays#deepEquals(Object[], Object[])
* @see Objects#equals(Object, Object)
*/
public static boolean deepEquals(Object a, Object b) {
if (a == b)
return true;
else if (a == null || b == null)
return false;
else
return Arrays.deepEquals0(a, b);
}
/**
* Returns the hash code of a non-{@code null} argument and 0 for
* a {@code null} argument.
*
* @param o an object
* @return the hash code of a non-{@code null} argument and 0 for
* a {@code null} argument
* @see Object#hashCode
*/
public static int hashCode(Object o) {
return o != null ? o.hashCode() : 0;
}
/**
* Generates a hash code for a sequence of input values. The hash
* code is generated as if all the input values were placed into an
* array, and that array were hashed by calling {@link
* Arrays#hashCode(Object[])}.
*
* <p>This method is useful for implementing {@link
* Object#hashCode()} on objects containing multiple fields. For
* example, if an object that has three fields, {@code x}, {@code
* y}, and {@code z}, one could write:
*
* <blockquote><pre>
* &#064;Override public int hashCode() {
* return Objects.hash(x, y, z);
* }
* </pre></blockquote>
*
* <b>Warning: When a single object reference is supplied, the returned
* value does not equal the hash code of that object reference.</b> This
* value can be computed by calling {@link #hashCode(Object)}.
*
* @param values the values to be hashed
* @return a hash value of the sequence of input values
* @see Arrays#hashCode(Object[])
* @see List#hashCode
*/
public static int hash(Object... values) {
return Arrays.hashCode(values);
}
/**
* Returns the result of calling {@code toString} for a non-{@code
* null} argument and {@code "null"} for a {@code null} argument.
*
* @param o an object
* @return the result of calling {@code toString} for a non-{@code
* null} argument and {@code "null"} for a {@code null} argument
* @see Object#toString
* @see String#valueOf(Object)
*/
public static String toString(Object o) {
return String.valueOf(o);
}
/**
* Returns the result of calling {@code toString} on the first
* argument if the first argument is not {@code null} and returns
* the second argument otherwise.
*
* @param o an object
* @param nullDefault string to return if the first argument is
* {@code null}
* @return the result of calling {@code toString} on the first
* argument if it is not {@code null} and the second argument
* otherwise.
* @see Objects#toString(Object)
*/
public static String toString(Object o, String nullDefault) {
return (o != null) ? o.toString() : nullDefault;
}
/**
* Returns 0 if the arguments are identical and {@code
* c.compare(a, b)} otherwise.
* Consequently, if both arguments are {@code null} 0
* is returned.
*
* <p>Note that if one of the arguments is {@code null}, a {@code
* NullPointerException} may or may not be thrown depending on
* what ordering policy, if any, the {@link Comparator Comparator}
* chooses to have for {@code null} values.
*
* @param <T> the type of the objects being compared
* @param a an object
* @param b an object to be compared with {@code a}
* @param c the {@code Comparator} to compare the first two arguments
* @return 0 if the arguments are identical and {@code
* c.compare(a, b)} otherwise.
* @see Comparable
* @see Comparator
*/
public static <T> int compare(T a, T b, Comparator<? super T> c) {
return (a == b) ? 0 : c.compare(a, b);
}
/**
* Checks that the specified object reference is not {@code null}. This
* method is designed primarily for doing parameter validation in methods
* and constructors, as demonstrated below:
* <blockquote><pre>
* public Foo(Bar bar) {
* this.bar = Objects.requireNonNull(bar);
* }
* </pre></blockquote>
*
* @param obj the object reference to check for nullity
* @param <T> the type of the reference
* @return {@code obj} if not {@code null}
* @throws NullPointerException if {@code obj} is {@code null}
*/
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
/**
* Checks that the specified object reference is not {@code null} and
* throws a customized {@link NullPointerException} if it is. This method
* is designed primarily for doing parameter validation in methods and
* constructors with multiple parameters, as demonstrated below:
* <blockquote><pre>
* public Foo(Bar bar, Baz baz) {
* this.bar = Objects.requireNonNull(bar, "bar must not be null");
* this.baz = Objects.requireNonNull(baz, "baz must not be null");
* }
* </pre></blockquote>
*
* @param obj the object reference to check for nullity
* @param message detail message to be used in the event that a {@code
* NullPointerException} is thrown
* @param <T> the type of the reference
* @return {@code obj} if not {@code null}
* @throws NullPointerException if {@code obj} is {@code null}
*/
public static <T> T requireNonNull(T obj, String message) {
if (obj == null)
throw new NullPointerException(message);
return obj;
}
/**
* Returns {@code true} if the provided reference is {@code null} otherwise
* returns {@code false}.
*
* @apiNote This method exists to be used as a
* {@link java.util.function.Predicate}, {@code filter(Objects::isNull)}
*
* @param obj a reference to be checked against {@code null}
* @return {@code true} if the provided reference is {@code null} otherwise
* {@code false}
*
* @see java.util.function.Predicate
* @since 1.8
*/
public static boolean isNull(Object obj) {
return obj == null;
}
/**
* Returns {@code true} if the provided reference is non-{@code null}
* otherwise returns {@code false}.
*
* @apiNote This method exists to be used as a
* {@link java.util.function.Predicate}, {@code filter(Objects::nonNull)}
*
* @param obj a reference to be checked against {@code null}
* @return {@code true} if the provided reference is non-{@code null}
* otherwise {@code false}
*
* @see java.util.function.Predicate
* @since 1.8
*/
public static boolean nonNull(Object obj) {
return obj != null;
}
/**
* Returns the first argument if it is non-{@code null} and
* otherwise returns the non-{@code null} second argument.
*
* @param obj an object
* @param defaultObj a non-{@code null} object to return if the first argument
* is {@code null}
* @param <T> the type of the reference
* @return the first argument if it is non-{@code null} and
* otherwise the second argument if it is non-{@code null}
* @throws NullPointerException if both {@code obj} is null and
* {@code defaultObj} is {@code null}
* @since 9
*/
public static <T> T requireNonNullElse(T obj, T defaultObj) {
return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj");
}
/**
* Returns the first argument if it is non-{@code null} and otherwise
* returns the non-{@code null} value of {@code supplier.get()}.
*
* @param obj an object
* @param supplier of a non-{@code null} object to return if the first argument
* is {@code null}
* @param <T> the type of the first argument and return type
* @return the first argument if it is non-{@code null} and otherwise
* the value from {@code supplier.get()} if it is non-{@code null}
* @throws NullPointerException if both {@code obj} is null and
* either the {@code supplier} is {@code null} or
* the {@code supplier.get()} value is {@code null}
* @since 9
*/
public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier) {
return (obj != null) ? obj
: requireNonNull(requireNonNull(supplier, "supplier").get(), "supplier.get()");
}
/**
* Checks that the specified object reference is not {@code null} and
* throws a customized {@link NullPointerException} if it is.
*
* <p>Unlike the method {@link #requireNonNull(Object, String)},
* this method allows creation of the message to be deferred until
* after the null check is made. While this may confer a
* performance advantage in the non-null case, when deciding to
* call this method care should be taken that the costs of
* creating the message supplier are less than the cost of just
* creating the string message directly.
*
* @param obj the object reference to check for nullity
* @param messageSupplier supplier of the detail message to be
* used in the event that a {@code NullPointerException} is thrown
* @param <T> the type of the reference
* @return {@code obj} if not {@code null}
* @throws NullPointerException if {@code obj} is {@code null}
* @since 1.8
*/
public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) {
if (obj == null)
throw new NullPointerException(messageSupplier == null ?
null : messageSupplier.get());
return obj;
}
/**
* Checks if the {@code index} is within the bounds of the range from
* {@code 0} (inclusive) to {@code length} (exclusive).
*
* <p>The {@code index} is defined to be out-of-bounds if any of the
* following inequalities is true:
* <ul>
* <li>{@code index < 0}</li>
* <li>{@code index >= length}</li>
* <li>{@code length < 0}, which is implied from the former inequalities</li>
* </ul>
*
* @param index the index
* @param length the upper-bound (exclusive) of the range
* @return {@code index} if it is within bounds of the range
* @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds
* @since 9
*/
@ForceInline
public static
int checkIndex(int index, int length) {
return Preconditions.checkIndex(index, length, null);
}
/**
* Checks if the sub-range from {@code fromIndex} (inclusive) to
* {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
* (inclusive) to {@code length} (exclusive).
*
* <p>The sub-range is defined to be out-of-bounds if any of the following
* inequalities is true:
* <ul>
* <li>{@code fromIndex < 0}</li>
* <li>{@code fromIndex > toIndex}</li>
* <li>{@code toIndex > length}</li>
* <li>{@code length < 0}, which is implied from the former inequalities</li>
* </ul>
*
* @param fromIndex the lower-bound (inclusive) of the sub-range
* @param toIndex the upper-bound (exclusive) of the sub-range
* @param length the upper-bound (exclusive) the range
* @return {@code fromIndex} if the sub-range within bounds of the range
* @throws IndexOutOfBoundsException if the sub-range is out-of-bounds
* @since 9
*/
public static
int checkFromToIndex(int fromIndex, int toIndex, int length) {
return Preconditions.checkFromToIndex(fromIndex, toIndex, length, null);
}
/**
* Checks if the sub-range from {@code fromIndex} (inclusive) to
* {@code fromIndex + size} (exclusive) is within the bounds of range from
* {@code 0} (inclusive) to {@code length} (exclusive).
*
* <p>The sub-range is defined to be out-of-bounds if any of the following
* inequalities is true:
* <ul>
* <li>{@code fromIndex < 0}</li>
* <li>{@code size < 0}</li>
* <li>{@code fromIndex + size > length}, taking into account integer overflow</li>
* <li>{@code length < 0}, which is implied from the former inequalities</li>
* </ul>
*
* @param fromIndex the lower-bound (inclusive) of the sub-interval
* @param size the size of the sub-range
* @param length the upper-bound (exclusive) of the range
* @return {@code fromIndex} if the sub-range within bounds of the range
* @throws IndexOutOfBoundsException if the sub-range is out-of-bounds
* @since 9
*/
public static
int checkFromIndexSize(int fromIndex, int size, int length) {
return Preconditions.checkFromIndexSize(fromIndex, size, length, null);
}
}

View file

@ -0,0 +1,227 @@
/*
* Copyright (c) 1994, 2016, 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;
/**
* This class represents an observable object, or "data"
* in the model-view paradigm. It can be subclassed to represent an
* object that the application wants to have observed.
* <p>
* An observable object can have one or more observers. An observer
* may be any object that implements interface {@code Observer}. After an
* observable instance changes, an application calling the
* {@code Observable}'s {@code notifyObservers} method
* causes all of its observers to be notified of the change by a call
* to their {@code update} method.
* <p>
* The order in which notifications will be delivered is unspecified.
* The default implementation provided in the Observable class will
* notify Observers in the order in which they registered interest, but
* subclasses may change this order, use no guaranteed order, deliver
* notifications on separate threads, or may guarantee that their
* subclass follows this order, as they choose.
* <p>
* Note that this notification mechanism has nothing to do with threads
* and is completely separate from the {@code wait} and {@code notify}
* mechanism of class {@code Object}.
* <p>
* When an observable object is newly created, its set of observers is
* empty. Two observers are considered the same if and only if the
* {@code equals} method returns true for them.
*
* @author Chris Warth
* @see java.util.Observable#notifyObservers()
* @see java.util.Observable#notifyObservers(java.lang.Object)
* @see java.util.Observer
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
* @since 1.0
*
* @deprecated
* This class and the {@link Observer} interface have been deprecated.
* The event model supported by {@code Observer} and {@code Observable}
* is quite limited, the order of notifications delivered by
* {@code Observable} is unspecified, and state changes are not in
* one-for-one correspondence with notifications.
* For a richer event model, consider using the
* {@link java.beans} package. For reliable and ordered
* messaging among threads, consider using one of the concurrent data
* structures in the {@link java.util.concurrent} package.
* For reactive streams style programming, see the
* {@link java.util.concurrent.Flow} API.
*/
@Deprecated(since="9")
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;
/** Construct an Observable with zero Observers. */
public Observable() {
obs = new Vector<>();
}
/**
* Adds an observer to the set of observers for this object, provided
* that it is not the same as some observer already in the set.
* The order in which notifications will be delivered to multiple
* observers is not specified. See the class comment.
*
* @param o an observer to be added.
* @throws NullPointerException if the parameter o is null.
*/
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
/**
* Deletes an observer from the set of observers of this object.
* Passing {@code null} to this method will have no effect.
* @param o the observer to be deleted.
*/
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
/**
* If this object has changed, as indicated by the
* {@code hasChanged} method, then notify all of its observers
* and then call the {@code clearChanged} method to
* indicate that this object has no longer changed.
* <p>
* Each observer has its {@code update} method called with two
* arguments: this observable object and {@code null}. In other
* words, this method is equivalent to:
* <blockquote>{@code
* notifyObservers(null)}</blockquote>
*
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers() {
notifyObservers(null);
}
/**
* If this object has changed, as indicated by the
* {@code hasChanged} method, then notify all of its observers
* and then call the {@code clearChanged} method to indicate
* that this object has no longer changed.
* <p>
* Each observer has its {@code update} method called with two
* arguments: this observable object and the {@code arg} argument.
*
* @param arg any object.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers(Object arg) {
/*
* a temporary array buffer, used as a snapshot of the state of
* current Observers.
*/
Object[] arrLocal;
synchronized (this) {
/* We don't want the Observer doing callbacks into
* arbitrary code while holding its own Monitor.
* The code where we extract each Observable from
* the Vector and store the state of the Observer
* needs synchronization, but notifying observers
* does not (should not). The worst result of any
* potential race-condition here is that:
* 1) a newly-added Observer will miss a
* notification in progress
* 2) a recently unregistered Observer will be
* wrongly notified when it doesn't care
*/
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
/**
* Clears the observer list so that this object no longer has any observers.
*/
public synchronized void deleteObservers() {
obs.removeAllElements();
}
/**
* Marks this {@code Observable} object as having been changed; the
* {@code hasChanged} method will now return {@code true}.
*/
protected synchronized void setChanged() {
changed = true;
}
/**
* Indicates that this object has no longer changed, or that it has
* already notified all of its observers of its most recent change,
* so that the {@code hasChanged} method will now return {@code false}.
* This method is called automatically by the
* {@code notifyObservers} methods.
*
* @see java.util.Observable#notifyObservers()
* @see java.util.Observable#notifyObservers(java.lang.Object)
*/
protected synchronized void clearChanged() {
changed = false;
}
/**
* Tests if this object has changed.
*
* @return {@code true} if and only if the {@code setChanged}
* method has been called more recently than the
* {@code clearChanged} method on this object;
* {@code false} otherwise.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#setChanged()
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
* Returns the number of observers of this {@code Observable} object.
*
* @return the number of observers of this object.
*/
public synchronized int countObservers() {
return obs.size();
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 1994, 2016, 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;
/**
* A class can implement the {@code Observer} interface when it
* wants to be informed of changes in observable objects.
*
* @author Chris Warth
* @see java.util.Observable
* @since 1.0
*
* @deprecated
* This interface has been deprecated. See the {@link Observable}
* class for further information.
*/
@Deprecated(since="9")
public interface Observer {
/**
* This method is called whenever the observed object is changed. An
* application calls an {@code Observable} object's
* {@code notifyObservers} method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the {@code notifyObservers}
* method.
*/
void update(Observable o, Object arg);
}

View file

@ -0,0 +1,446 @@
/*
* Copyright (c) 2012, 2017, 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;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
/**
* A container object which may or may not contain a non-{@code null} value.
* If a value is present, {@code isPresent()} returns {@code true} and
* {@code get()} returns the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(Object) orElse()}
* (returns a default value if no value is present) and
* {@link #ifPresent(Consumer) ifPresent()} (performs an
* action if a value is present).
*
* <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 Optional} may have unpredictable results and should be avoided.
*
* @apiNote
* {@code Optional} is primarily intended for use as a method return type where
* there is a clear need to represent "no result," and where using {@code null}
* is likely to cause errors. A variable whose type is {@code Optional} should
* never itself be {@code null}; it should always point to an {@code Optional}
* instance.
*
* @param <T> the type of value
* @since 1.8
*/
public final class Optional<T> {
/**
* Common instance for {@code empty()}.
*/
private static final Optional<?> EMPTY = new Optional<>();
/**
* If non-null, the value; if null, indicates no value is present
*/
private final T value;
/**
* Constructs an empty instance.
*
* @implNote Generally only one empty instance, {@link Optional#EMPTY},
* should exist per VM.
*/
private Optional() {
this.value = null;
}
/**
* Returns an empty {@code Optional} instance. No value is present for this
* {@code Optional}.
*
* @apiNote
* Though it may be tempting to do so, avoid testing if an object is empty
* by comparing with {@code ==} against instances returned by
* {@code Optional.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
* @param <T> The type of the non-existent value
* @return an empty {@code Optional}
*/
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
/**
* Constructs an instance with the described value.
*
* @param value the non-{@code null} value to describe
* @throws NullPointerException if value is {@code null}
*/
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
/**
* Returns an {@code Optional} describing the given non-{@code null}
* value.
*
* @param value the value to describe, which must be non-{@code null}
* @param <T> the type of the value
* @return an {@code Optional} with the value present
* @throws NullPointerException if value is {@code null}
*/
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
/**
* Returns an {@code Optional} describing the given value, if
* non-{@code null}, otherwise returns an empty {@code Optional}.
*
* @param value the possibly-{@code null} value to describe
* @param <T> the type of the value
* @return an {@code Optional} with a present value if the specified value
* is non-{@code null}, otherwise an empty {@code Optional}
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
/**
* If a value is present, returns the value, otherwise throws
* {@code NoSuchElementException}.
*
* @apiNote
* The methods {@link #orElse(Object) orElse} and
* {@link #orElseGet(Supplier) orElseGet}
* are generally preferable to this method, as they return a substitute
* value if the value is absent, instead of throwing an exception.
*
* @return the non-{@code null} value described by this {@code Optional}
* @throws NoSuchElementException if no value is present
* @see Optional#isPresent()
*/
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* If a value is present, returns {@code true}, otherwise {@code false}.
*
* @return {@code true} if a value is present, otherwise {@code false}
*/
public boolean isPresent() {
return value != null;
}
/**
* If a value is present, performs the given action with the value,
* otherwise does nothing.
*
* @param action the action to be performed, if a value is present
* @throws NullPointerException if value is present and the given action is
* {@code null}
*/
public void ifPresent(Consumer<? super T> action) {
if (value != null) {
action.accept(value);
}
}
/**
* If a value is present, performs the given action with the value,
* otherwise performs the given empty-based action.
*
* @param action the action to be performed, if a value is present
* @param emptyAction the empty-based action to be performed, if no value is
* present
* @throws NullPointerException if a value is present and the given action
* is {@code null}, or no value is present and the given empty-based
* action is {@code null}.
* @since 9
*/
public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) {
if (value != null) {
action.accept(value);
} else {
emptyAction.run();
}
}
/**
* If a value is present, and the value matches the given predicate,
* returns an {@code Optional} describing the value, otherwise returns an
* empty {@code Optional}.
*
* @param predicate the predicate to apply to a value, if present
* @return an {@code Optional} describing the value of this
* {@code Optional}, if a value is present and the value matches the
* given predicate, otherwise an empty {@code Optional}
* @throws NullPointerException if the predicate is {@code null}
*/
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent()) {
return this;
} else {
return predicate.test(value) ? this : empty();
}
}
/**
* If a value is present, returns an {@code Optional} describing (as if by
* {@link #ofNullable}) the result of applying the given mapping function to
* the value, otherwise returns an empty {@code Optional}.
*
* <p>If the mapping function returns a {@code null} result then this method
* returns an empty {@code Optional}.
*
* @apiNote
* This method supports post-processing on {@code Optional} values, without
* the need to explicitly check for a return status. For example, the
* following code traverses a stream of URIs, selects one that has not
* yet been processed, and creates a path from that URI, returning
* an {@code Optional<Path>}:
*
* <pre>{@code
* Optional<Path> p =
* uris.stream().filter(uri -> !isProcessedYet(uri))
* .findFirst()
* .map(Paths::get);
* }</pre>
*
* Here, {@code findFirst} returns an {@code Optional<URI>}, and then
* {@code map} returns an {@code Optional<Path>} for the desired
* URI if one exists.
*
* @param mapper the mapping function to apply to a value, if present
* @param <U> The type of the value returned from the mapping function
* @return an {@code Optional} describing the result of applying a mapping
* function to the value of this {@code Optional}, if a value is
* present, otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is {@code null}
*/
public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent()) {
return empty();
} else {
return Optional.ofNullable(mapper.apply(value));
}
}
/**
* If a value is present, returns the result of applying the given
* {@code Optional}-bearing mapping function to the value, otherwise returns
* an empty {@code Optional}.
*
* <p>This method is similar to {@link #map(Function)}, but the mapping
* function is one whose result is already an {@code Optional}, and if
* invoked, {@code flatMap} does not wrap it within an additional
* {@code Optional}.
*
* @param <U> The type of value of the {@code Optional} returned by the
* mapping function
* @param mapper the mapping function to apply to a value, if present
* @return the result of applying an {@code Optional}-bearing mapping
* function to the value of this {@code Optional}, if a value is
* present, otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is {@code null} or
* returns a {@code null} result
*/
public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent()) {
return empty();
} else {
@SuppressWarnings("unchecked")
Optional<U> r = (Optional<U>) mapper.apply(value);
return Objects.requireNonNull(r);
}
}
/**
* If a value is present, returns an {@code Optional} describing the value,
* otherwise returns an {@code Optional} produced by the supplying function.
*
* @param supplier the supplying function that produces an {@code Optional}
* to be returned
* @return returns an {@code Optional} describing the value of this
* {@code Optional}, if a value is present, otherwise an
* {@code Optional} produced by the supplying function.
* @throws NullPointerException if the supplying function is {@code null} or
* produces a {@code null} result
* @since 9
*/
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
Objects.requireNonNull(supplier);
if (isPresent()) {
return this;
} else {
@SuppressWarnings("unchecked")
Optional<T> r = (Optional<T>) supplier.get();
return Objects.requireNonNull(r);
}
}
/**
* If a value is present, returns a sequential {@link Stream} containing
* only that value, otherwise returns an empty {@code Stream}.
*
* @apiNote
* This method can be used to transform a {@code Stream} of optional
* elements to a {@code Stream} of present value elements:
* <pre>{@code
* Stream<Optional<T>> os = ..
* Stream<T> s = os.flatMap(Optional::stream)
* }</pre>
*
* @return the optional value as a {@code Stream}
* @since 9
*/
public Stream<T> stream() {
if (!isPresent()) {
return Stream.empty();
} else {
return Stream.of(value);
}
}
/**
* If a value is present, returns the value, otherwise returns
* {@code other}.
*
* @param other the value to be returned, if no value is present.
* May be {@code null}.
* @return the value, if present, otherwise {@code other}
*/
public T orElse(T other) {
return value != null ? value : other;
}
/**
* If a value is present, returns the value, otherwise returns the result
* produced by the supplying function.
*
* @param supplier the supplying function that produces a value to be returned
* @return the value, if present, otherwise the result produced by the
* supplying function
* @throws NullPointerException if no value is present and the supplying
* function is {@code null}
*/
public T orElseGet(Supplier<? extends T> supplier) {
return value != null ? value : supplier.get();
}
/**
* If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function.
*
* @apiNote
* A method reference to the exception constructor with an empty argument
* list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
* @param exceptionSupplier the supplying function that produces an
* exception to be thrown
* @return the value, if present
* @throws X if no value is present
* @throws NullPointerException if no value is present and the exception
* supplying function is {@code null}
*/
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
/**
* Indicates whether some other object is "equal to" this {@code Optional}.
* The other object is considered equal if:
* <ul>
* <li>it is also an {@code Optional} and;
* <li>both instances have no value present or;
* <li>the present values are "equal to" each other via {@code equals()}.
* </ul>
*
* @param obj an object to be tested for equality
* @return {@code true} if the other object is "equal to" this object
* otherwise {@code false}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Optional)) {
return false;
}
Optional<?> other = (Optional<?>) obj;
return Objects.equals(value, other.value);
}
/**
* Returns the hash code of the value, if present, otherwise {@code 0}
* (zero) if no value is present.
*
* @return hash code value of the present value or {@code 0} if no value is
* present
*/
@Override
public int hashCode() {
return Objects.hashCode(value);
}
/**
* Returns a non-empty string representation of this {@code Optional}
* suitable for debugging. The exact presentation format is unspecified and
* may vary between implementations and versions.
*
* @implSpec
* If a value is present the result must include its string representation
* in the result. Empty and present {@code Optional}s must be unambiguously
* differentiable.
*
* @return the string representation of this instance
*/
@Override
public String toString() {
return value != null
? String.format("Optional[%s]", value)
: "Optional.empty";
}
}

View file

@ -0,0 +1,313 @@
/*
* Copyright (c) 2012, 2017, 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;
import java.util.function.DoubleConsumer;
import java.util.function.DoubleSupplier;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
/**
* A container object which may or may not contain a {@code double} value. If a
* value is present, {@code isPresent()} returns {@code true} and
* {@code getAsDouble()} returns the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(double) orElse()}
* (returns a default value if no value is present) and
* {@link #ifPresent(DoubleConsumer) ifPresent()} (performs
* an action if a value is present).
*
* <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 OptionalDouble} may have unpredictable results and should be avoided.
*
* @apiNote
* {@code OptionalDouble} is primarily intended for use as a method return type where
* there is a clear need to represent "no result." A variable whose type is
* {@code OptionalDouble} should never itself be {@code null}; it should always point
* to an {@code OptionalDouble} instance.
*
* @since 1.8
*/
public final class OptionalDouble {
/**
* Common instance for {@code empty()}.
*/
private static final OptionalDouble EMPTY = new OptionalDouble();
/**
* If true then the value is present, otherwise indicates no value is present
*/
private final boolean isPresent;
private final double value;
/**
* Construct an empty instance.
*
* @implNote generally only one empty instance, {@link OptionalDouble#EMPTY},
* should exist per VM.
*/
private OptionalDouble() {
this.isPresent = false;
this.value = Double.NaN;
}
/**
* Returns an empty {@code OptionalDouble} instance. No value is present
* for this {@code OptionalDouble}.
*
* @apiNote
* Though it may be tempting to do so, avoid testing if an object is empty
* by comparing with {@code ==} against instances returned by
* {@code OptionalDouble.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
* @return an empty {@code OptionalDouble}.
*/
public static OptionalDouble empty() {
return EMPTY;
}
/**
* Construct an instance with the described value.
*
* @param value the double value to describe.
*/
private OptionalDouble(double value) {
this.isPresent = true;
this.value = value;
}
/**
* Returns an {@code OptionalDouble} describing the given value.
*
* @param value the value to describe
* @return an {@code OptionalDouble} with the value present
*/
public static OptionalDouble of(double value) {
return new OptionalDouble(value);
}
/**
* If a value is present, returns the value, otherwise throws
* {@code NoSuchElementException}.
*
* @apiNote
* The methods {@link #orElse(double) orElse} and
* {@link #orElseGet(DoubleSupplier) orElseGet}
* are generally preferable to this method, as they return a substitute
* value if the value is absent, instead of throwing an exception.
*
* @return the value described by this {@code OptionalDouble}
* @throws NoSuchElementException if no value is present
* @see OptionalDouble#isPresent()
*/
public double getAsDouble() {
if (!isPresent) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* If a value is present, returns {@code true}, otherwise {@code false}.
*
* @return {@code true} if a value is present, otherwise {@code false}
*/
public boolean isPresent() {
return isPresent;
}
/**
* If a value is present, performs the given action with the value,
* otherwise does nothing.
*
* @param action the action to be performed, if a value is present
* @throws NullPointerException if value is present and the given action is
* {@code null}
*/
public void ifPresent(DoubleConsumer action) {
if (isPresent) {
action.accept(value);
}
}
/**
* If a value is present, performs the given action with the value,
* otherwise performs the given empty-based action.
*
* @param action the action to be performed, if a value is present
* @param emptyAction the empty-based action to be performed, if no value is
* present
* @throws NullPointerException if a value is present and the given action
* is {@code null}, or no value is present and the given empty-based
* action is {@code null}.
* @since 9
*/
public void ifPresentOrElse(DoubleConsumer action, Runnable emptyAction) {
if (isPresent) {
action.accept(value);
} else {
emptyAction.run();
}
}
/**
* If a value is present, returns a sequential {@link DoubleStream}
* containing only that value, otherwise returns an empty
* {@code DoubleStream}.
*
* @apiNote
* This method can be used to transform a {@code Stream} of optional doubles
* to a {@code DoubleStream} of present doubles:
* <pre>{@code
* Stream<OptionalDouble> os = ..
* DoubleStream s = os.flatMapToDouble(OptionalDouble::stream)
* }</pre>
*
* @return the optional value as a {@code DoubleStream}
* @since 9
*/
public DoubleStream stream() {
if (isPresent) {
return DoubleStream.of(value);
} else {
return DoubleStream.empty();
}
}
/**
* If a value is present, returns the value, otherwise returns
* {@code other}.
*
* @param other the value to be returned, if no value is present
* @return the value, if present, otherwise {@code other}
*/
public double orElse(double other) {
return isPresent ? value : other;
}
/**
* If a value is present, returns the value, otherwise returns the result
* produced by the supplying function.
*
* @param supplier the supplying function that produces a value to be returned
* @return the value, if present, otherwise the result produced by the
* supplying function
* @throws NullPointerException if no value is present and the supplying
* function is {@code null}
*/
public double orElseGet(DoubleSupplier supplier) {
return isPresent ? value : supplier.getAsDouble();
}
/**
* If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function.
*
* @apiNote
* A method reference to the exception constructor with an empty argument
* list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
* @param exceptionSupplier the supplying function that produces an
* exception to be thrown
* @return the value, if present
* @throws X if no value is present
* @throws NullPointerException if no value is present and the exception
* supplying function is {@code null}
*/
public<X extends Throwable> double orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (isPresent) {
return value;
} else {
throw exceptionSupplier.get();
}
}
/**
* Indicates whether some other object is "equal to" this
* {@code OptionalDouble}. The other object is considered equal if:
* <ul>
* <li>it is also an {@code OptionalDouble} and;
* <li>both instances have no value present or;
* <li>the present values are "equal to" each other via
* {@code Double.compare() == 0}.
* </ul>
*
* @param obj an object to be tested for equality
* @return {@code true} if the other object is "equal to" this object
* otherwise {@code false}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof OptionalDouble)) {
return false;
}
OptionalDouble other = (OptionalDouble) obj;
return (isPresent && other.isPresent)
? Double.compare(value, other.value) == 0
: isPresent == other.isPresent;
}
/**
* Returns the hash code of the value, if present, otherwise {@code 0}
* (zero) if no value is present.
*
* @return hash code value of the present value or {@code 0} if no value is
* present
*/
@Override
public int hashCode() {
return isPresent ? Double.hashCode(value) : 0;
}
/**
* Returns a non-empty string representation of this {@code OptionalDouble}
* suitable for debugging. The exact presentation format is unspecified and
* may vary between implementations and versions.
*
* @implSpec
* If a value is present the result must include its string representation
* in the result. Empty and present {@code OptionalDouble}s must be
* unambiguously differentiable.
*
* @return the string representation of this instance
*/
@Override
public String toString() {
return isPresent
? String.format("OptionalDouble[%s]", value)
: "OptionalDouble.empty";
}
}

View file

@ -0,0 +1,311 @@
/*
* Copyright (c) 2012, 2017, 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;
import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.Supplier;
import java.util.stream.IntStream;
/**
* A container object which may or may not contain an {@code int} value. If a
* value is present, {@code isPresent()} returns {@code true} and
* {@code getAsInt()} returns the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(int) orElse()}
* (returns a default value if no value is present) and
* {@link #ifPresent(IntConsumer) ifPresent()} (performs an
* action if a value is present).
*
* <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 OptionalInt} may have unpredictable results and should be avoided.
*
* @apiNote
* {@code OptionalInt} is primarily intended for use as a method return type where
* there is a clear need to represent "no result." A variable whose type is
* {@code OptionalInt} should never itself be {@code null}; it should always point
* to an {@code OptionalInt} instance.
*
* @since 1.8
*/
public final class OptionalInt {
/**
* Common instance for {@code empty()}.
*/
private static final OptionalInt EMPTY = new OptionalInt();
/**
* If true then the value is present, otherwise indicates no value is present
*/
private final boolean isPresent;
private final int value;
/**
* Construct an empty instance.
*
* @implNote Generally only one empty instance, {@link OptionalInt#EMPTY},
* should exist per VM.
*/
private OptionalInt() {
this.isPresent = false;
this.value = 0;
}
/**
* Returns an empty {@code OptionalInt} instance. No value is present for
* this {@code OptionalInt}.
*
* @apiNote
* Though it may be tempting to do so, avoid testing if an object is empty
* by comparing with {@code ==} against instances returned by
* {@code OptionalInt.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
* @return an empty {@code OptionalInt}
*/
public static OptionalInt empty() {
return EMPTY;
}
/**
* Construct an instance with the described value.
*
* @param value the int value to describe
*/
private OptionalInt(int value) {
this.isPresent = true;
this.value = value;
}
/**
* Returns an {@code OptionalInt} describing the given value.
*
* @param value the value to describe
* @return an {@code OptionalInt} with the value present
*/
public static OptionalInt of(int value) {
return new OptionalInt(value);
}
/**
* If a value is present, returns the value, otherwise throws
* {@code NoSuchElementException}.
*
* @apiNote
* The methods {@link #orElse(int) orElse} and
* {@link #orElseGet(IntSupplier) orElseGet}
* are generally preferable to this method, as they return a substitute
* value if the value is absent, instead of throwing an exception.
*
* @return the value described by this {@code OptionalInt}
* @throws NoSuchElementException if no value is present
* @see OptionalInt#isPresent()
*/
public int getAsInt() {
if (!isPresent) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* If a value is present, returns {@code true}, otherwise {@code false}.
*
* @return {@code true} if a value is present, otherwise {@code false}
*/
public boolean isPresent() {
return isPresent;
}
/**
* If a value is present, performs the given action with the value,
* otherwise does nothing.
*
* @param action the action to be performed, if a value is present
* @throws NullPointerException if value is present and the given action is
* {@code null}
*/
public void ifPresent(IntConsumer action) {
if (isPresent) {
action.accept(value);
}
}
/**
* If a value is present, performs the given action with the value,
* otherwise performs the given empty-based action.
*
* @param action the action to be performed, if a value is present
* @param emptyAction the empty-based action to be performed, if no value is
* present
* @throws NullPointerException if a value is present and the given action
* is {@code null}, or no value is present and the given empty-based
* action is {@code null}.
* @since 9
*/
public void ifPresentOrElse(IntConsumer action, Runnable emptyAction) {
if (isPresent) {
action.accept(value);
} else {
emptyAction.run();
}
}
/**
* If a value is present, returns a sequential {@link IntStream} containing
* only that value, otherwise returns an empty {@code IntStream}.
*
* @apiNote
* This method can be used to transform a {@code Stream} of optional
* integers to an {@code IntStream} of present integers:
* <pre>{@code
* Stream<OptionalInt> os = ..
* IntStream s = os.flatMapToInt(OptionalInt::stream)
* }</pre>
*
* @return the optional value as an {@code IntStream}
* @since 9
*/
public IntStream stream() {
if (isPresent) {
return IntStream.of(value);
} else {
return IntStream.empty();
}
}
/**
* If a value is present, returns the value, otherwise returns
* {@code other}.
*
* @param other the value to be returned, if no value is present
* @return the value, if present, otherwise {@code other}
*/
public int orElse(int other) {
return isPresent ? value : other;
}
/**
* If a value is present, returns the value, otherwise returns the result
* produced by the supplying function.
*
* @param supplier the supplying function that produces a value to be returned
* @return the value, if present, otherwise the result produced by the
* supplying function
* @throws NullPointerException if no value is present and the supplying
* function is {@code null}
*/
public int orElseGet(IntSupplier supplier) {
return isPresent ? value : supplier.getAsInt();
}
/**
* If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function.
*
* @apiNote
* A method reference to the exception constructor with an empty argument
* list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
* @param exceptionSupplier the supplying function that produces an
* exception to be thrown
* @return the value, if present
* @throws X if no value is present
* @throws NullPointerException if no value is present and the exception
* supplying function is {@code null}
*/
public<X extends Throwable> int orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (isPresent) {
return value;
} else {
throw exceptionSupplier.get();
}
}
/**
* Indicates whether some other object is "equal to" this
* {@code OptionalInt}. The other object is considered equal if:
* <ul>
* <li>it is also an {@code OptionalInt} and;
* <li>both instances have no value present or;
* <li>the present values are "equal to" each other via {@code ==}.
* </ul>
*
* @param obj an object to be tested for equality
* @return {@code true} if the other object is "equal to" this object
* otherwise {@code false}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof OptionalInt)) {
return false;
}
OptionalInt other = (OptionalInt) obj;
return (isPresent && other.isPresent)
? value == other.value
: isPresent == other.isPresent;
}
/**
* Returns the hash code of the value, if present, otherwise {@code 0}
* (zero) if no value is present.
*
* @return hash code value of the present value or {@code 0} if no value is
* present
*/
@Override
public int hashCode() {
return isPresent ? Integer.hashCode(value) : 0;
}
/**
* Returns a non-empty string representation of this {@code OptionalInt}
* suitable for debugging. The exact presentation format is unspecified and
* may vary between implementations and versions.
*
* @implSpec
* If a value is present the result must include its string representation
* in the result. Empty and present {@code OptionalInt}s must be
* unambiguously differentiable.
*
* @return the string representation of this instance
*/
@Override
public String toString() {
return isPresent
? String.format("OptionalInt[%s]", value)
: "OptionalInt.empty";
}
}

View file

@ -0,0 +1,311 @@
/*
* Copyright (c) 2012, 2017, 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;
import java.util.function.LongConsumer;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
import java.util.stream.LongStream;
/**
* A container object which may or may not contain a {@code long} value. If a
* value is present, {@code isPresent()} returns {@code true} and
* {@code getAsLong()} returns the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(long) orElse()}
* (returns a default value if no value is present) and
* {@link #ifPresent(LongConsumer) ifPresent()} (performs an
* action if a value is present).
*
* <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 OptionalLong} may have unpredictable results and should be avoided.
*
* @apiNote
* {@code OptionalLong} is primarily intended for use as a method return type where
* there is a clear need to represent "no result." A variable whose type is
* {@code OptionalLong} should never itself be {@code null}; it should always point
* to an {@code OptionalLong} instance.
*
* @since 1.8
*/
public final class OptionalLong {
/**
* Common instance for {@code empty()}.
*/
private static final OptionalLong EMPTY = new OptionalLong();
/**
* If true then the value is present, otherwise indicates no value is present
*/
private final boolean isPresent;
private final long value;
/**
* Construct an empty instance.
*
* @implNote generally only one empty instance, {@link OptionalLong#EMPTY},
* should exist per VM.
*/
private OptionalLong() {
this.isPresent = false;
this.value = 0;
}
/**
* Returns an empty {@code OptionalLong} instance. No value is present for
* this {@code OptionalLong}.
*
* @apiNote
* Though it may be tempting to do so, avoid testing if an object is empty
* by comparing with {@code ==} against instances returned by
* {@code OptionalLong.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
* @return an empty {@code OptionalLong}.
*/
public static OptionalLong empty() {
return EMPTY;
}
/**
* Construct an instance with the described value.
*
* @param value the long value to describe
*/
private OptionalLong(long value) {
this.isPresent = true;
this.value = value;
}
/**
* Returns an {@code OptionalLong} describing the given value.
*
* @param value the value to describe
* @return an {@code OptionalLong} with the value present
*/
public static OptionalLong of(long value) {
return new OptionalLong(value);
}
/**
* If a value is present, returns the value, otherwise throws
* {@code NoSuchElementException}.
*
* @apiNote
* The methods {@link #orElse(long) orElse} and
* {@link #orElseGet(LongSupplier) orElseGet}
* are generally preferable to this method, as they return a substitute
* value if the value is absent, instead of throwing an exception.
*
* @return the value described by this {@code OptionalLong}
* @throws NoSuchElementException if no value is present
* @see OptionalLong#isPresent()
*/
public long getAsLong() {
if (!isPresent) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* If a value is present, returns {@code true}, otherwise {@code false}.
*
* @return {@code true} if a value is present, otherwise {@code false}
*/
public boolean isPresent() {
return isPresent;
}
/**
* If a value is present, performs the given action with the value,
* otherwise does nothing.
*
* @param action the action to be performed, if a value is present
* @throws NullPointerException if value is present and the given action is
* {@code null}
*/
public void ifPresent(LongConsumer action) {
if (isPresent) {
action.accept(value);
}
}
/**
* If a value is present, performs the given action with the value,
* otherwise performs the given empty-based action.
*
* @param action the action to be performed, if a value is present
* @param emptyAction the empty-based action to be performed, if no value is
* present
* @throws NullPointerException if a value is present and the given action
* is {@code null}, or no value is present and the given empty-based
* action is {@code null}.
* @since 9
*/
public void ifPresentOrElse(LongConsumer action, Runnable emptyAction) {
if (isPresent) {
action.accept(value);
} else {
emptyAction.run();
}
}
/**
* If a value is present, returns a sequential {@link LongStream} containing
* only that value, otherwise returns an empty {@code LongStream}.
*
* @apiNote
* This method can be used to transform a {@code Stream} of optional longs
* to an {@code LongStream} of present longs:
* <pre>{@code
* Stream<OptionalLong> os = ..
* LongStream s = os.flatMapToLong(OptionalLong::stream)
* }</pre>
*
* @return the optional value as an {@code LongStream}
* @since 9
*/
public LongStream stream() {
if (isPresent) {
return LongStream.of(value);
} else {
return LongStream.empty();
}
}
/**
* If a value is present, returns the value, otherwise returns
* {@code other}.
*
* @param other the value to be returned, if no value is present
* @return the value, if present, otherwise {@code other}
*/
public long orElse(long other) {
return isPresent ? value : other;
}
/**
* If a value is present, returns the value, otherwise returns the result
* produced by the supplying function.
*
* @param supplier the supplying function that produces a value to be returned
* @return the value, if present, otherwise the result produced by the
* supplying function
* @throws NullPointerException if no value is present and the supplying
* function is {@code null}
*/
public long orElseGet(LongSupplier supplier) {
return isPresent ? value : supplier.getAsLong();
}
/**
* If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function.
*
* @apiNote
* A method reference to the exception constructor with an empty argument
* list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
* @param exceptionSupplier the supplying function that produces an
* exception to be thrown
* @return the value, if present
* @throws X if no value is present
* @throws NullPointerException if no value is present and the exception
* supplying function is {@code null}
*/
public<X extends Throwable> long orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (isPresent) {
return value;
} else {
throw exceptionSupplier.get();
}
}
/**
* Indicates whether some other object is "equal to" this
* {@code OptionalLong}. The other object is considered equal if:
* <ul>
* <li>it is also an {@code OptionalLong} and;
* <li>both instances have no value present or;
* <li>the present values are "equal to" each other via {@code ==}.
* </ul>
*
* @param obj an object to be tested for equality
* @return {@code true} if the other object is "equal to" this object
* otherwise {@code false}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof OptionalLong)) {
return false;
}
OptionalLong other = (OptionalLong) obj;
return (isPresent && other.isPresent)
? value == other.value
: isPresent == other.isPresent;
}
/**
* Returns the hash code of the value, if present, otherwise {@code 0}
* (zero) if no value is present.
*
* @return hash code value of the present value or {@code 0} if no value is
* present
*/
@Override
public int hashCode() {
return isPresent ? Long.hashCode(value) : 0;
}
/**
* Returns a non-empty string representation of this {@code OptionalLong}
* suitable for debugging. The exact presentation format is unspecified and
* may vary between implementations and versions.
*
* @implSpec
* If a value is present the result must include its string representation
* in the result. Empty and present {@code OptionalLong}s must be
* unambiguously differentiable.
*
* @return the string representation of this instance
*/
@Override
public String toString() {
return isPresent
? String.format("OptionalLong[%s]", value)
: "OptionalLong.empty";
}
}

View file

@ -0,0 +1,302 @@
/*
* Copyright (c) 2013, 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;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
/**
* A base type for primitive specializations of {@code Iterator}. Specialized
* subtypes are provided for {@link OfInt int}, {@link OfLong long}, and
* {@link OfDouble double} values.
*
* <p>The specialized subtype default implementations of {@link Iterator#next}
* and {@link Iterator#forEachRemaining(java.util.function.Consumer)} box
* primitive values to instances of their corresponding wrapper class. Such
* boxing may offset any advantages gained when using the primitive
* specializations. To avoid boxing, the corresponding primitive-based methods
* should be used. For example, {@link PrimitiveIterator.OfInt#nextInt()} and
* {@link PrimitiveIterator.OfInt#forEachRemaining(java.util.function.IntConsumer)}
* should be used in preference to {@link PrimitiveIterator.OfInt#next()} and
* {@link PrimitiveIterator.OfInt#forEachRemaining(java.util.function.Consumer)}.
*
* <p>Iteration of primitive values using boxing-based methods
* {@link Iterator#next next()} and
* {@link Iterator#forEachRemaining(java.util.function.Consumer) forEachRemaining()},
* does not affect the order in which the values, transformed to boxed values,
* are encountered.
*
* @implNote
* If the boolean system property {@code org.openjdk.java.util.stream.tripwire}
* is set to {@code true} then diagnostic warnings are reported if boxing of
* primitive values occur when operating on primitive subtype specializations.
*
* @param <T> the type of elements returned by this PrimitiveIterator. The
* type must be a wrapper type for a primitive type, such as
* {@code Integer} for the primitive {@code int} type.
* @param <T_CONS> the type of primitive consumer. The type must be a
* primitive specialization of {@link java.util.function.Consumer} for
* {@code T}, such as {@link java.util.function.IntConsumer} for
* {@code Integer}.
*
* @since 1.8
*/
public interface PrimitiveIterator<T, T_CONS> extends Iterator<T> {
/**
* Performs the given action for each remaining element, in the order
* elements occur when iterating, until all elements have been processed
* or the action throws an exception. Errors or runtime exceptions
* thrown by the action are relayed to the caller.
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
*/
@SuppressWarnings("overloads")
void forEachRemaining(T_CONS action);
/**
* An Iterator specialized for {@code int} values.
* @since 1.8
*/
public static interface OfInt extends PrimitiveIterator<Integer, IntConsumer> {
/**
* Returns the next {@code int} element in the iteration.
*
* @return the next {@code int} element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
int nextInt();
/**
* Performs the given action for each remaining element until all elements
* have been processed or the action throws an exception. Actions are
* performed in the order of iteration, if that order is specified.
* Exceptions thrown by the action are relayed to the caller.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* while (hasNext())
* action.accept(nextInt());
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
*/
default void forEachRemaining(IntConsumer action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(nextInt());
}
/**
* {@inheritDoc}
* @implSpec
* The default implementation boxes the result of calling
* {@link #nextInt()}, and returns that boxed result.
*/
@Override
default Integer next() {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfInt.nextInt()");
return nextInt();
}
/**
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code IntConsumer} then it is cast
* to {@code IntConsumer} and passed to {@link #forEachRemaining};
* otherwise the action is adapted to an instance of
* {@code IntConsumer}, by boxing the argument of {@code IntConsumer},
* and then passed to {@link #forEachRemaining}.
*/
@Override
default void forEachRemaining(Consumer<? super Integer> action) {
if (action instanceof IntConsumer) {
forEachRemaining((IntConsumer) action);
}
else {
// The method reference action::accept is never null
Objects.requireNonNull(action);
if (Tripwire.ENABLED)
Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfInt.forEachRemainingInt(action::accept)");
forEachRemaining((IntConsumer) action::accept);
}
}
}
/**
* An Iterator specialized for {@code long} values.
* @since 1.8
*/
public static interface OfLong extends PrimitiveIterator<Long, LongConsumer> {
/**
* Returns the next {@code long} element in the iteration.
*
* @return the next {@code long} element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
long nextLong();
/**
* Performs the given action for each remaining element until all elements
* have been processed or the action throws an exception. Actions are
* performed in the order of iteration, if that order is specified.
* Exceptions thrown by the action are relayed to the caller.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* while (hasNext())
* action.accept(nextLong());
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
*/
default void forEachRemaining(LongConsumer action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(nextLong());
}
/**
* {@inheritDoc}
* @implSpec
* The default implementation boxes the result of calling
* {@link #nextLong()}, and returns that boxed result.
*/
@Override
default Long next() {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfLong.nextLong()");
return nextLong();
}
/**
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code LongConsumer} then it is cast
* to {@code LongConsumer} and passed to {@link #forEachRemaining};
* otherwise the action is adapted to an instance of
* {@code LongConsumer}, by boxing the argument of {@code LongConsumer},
* and then passed to {@link #forEachRemaining}.
*/
@Override
default void forEachRemaining(Consumer<? super Long> action) {
if (action instanceof LongConsumer) {
forEachRemaining((LongConsumer) action);
}
else {
// The method reference action::accept is never null
Objects.requireNonNull(action);
if (Tripwire.ENABLED)
Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfLong.forEachRemainingLong(action::accept)");
forEachRemaining((LongConsumer) action::accept);
}
}
}
/**
* An Iterator specialized for {@code double} values.
* @since 1.8
*/
public static interface OfDouble extends PrimitiveIterator<Double, DoubleConsumer> {
/**
* Returns the next {@code double} element in the iteration.
*
* @return the next {@code double} element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
double nextDouble();
/**
* Performs the given action for each remaining element until all elements
* have been processed or the action throws an exception. Actions are
* performed in the order of iteration, if that order is specified.
* Exceptions thrown by the action are relayed to the caller.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* while (hasNext())
* action.accept(nextDouble());
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
*/
default void forEachRemaining(DoubleConsumer action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(nextDouble());
}
/**
* {@inheritDoc}
* @implSpec
* The default implementation boxes the result of calling
* {@link #nextDouble()}, and returns that boxed result.
*/
@Override
default Double next() {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfDouble.nextLong()");
return nextDouble();
}
/**
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code DoubleConsumer} then it is
* cast to {@code DoubleConsumer} and passed to
* {@link #forEachRemaining}; otherwise the action is adapted to
* an instance of {@code DoubleConsumer}, by boxing the argument of
* {@code DoubleConsumer}, and then passed to
* {@link #forEachRemaining}.
*/
@Override
default void forEachRemaining(Consumer<? super Double> action) {
if (action instanceof DoubleConsumer) {
forEachRemaining((DoubleConsumer) action);
}
else {
// The method reference action::accept is never null
Objects.requireNonNull(action);
if (Tripwire.ENABLED)
Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfDouble.forEachRemainingDouble(action::accept)");
forEachRemaining((DoubleConsumer) action::accept);
}
}
}
}

View file

@ -0,0 +1,896 @@
/*
* Copyright (c) 2003, 2013, 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;
import java.util.function.Consumer;
/**
* An unbounded priority {@linkplain Queue queue} based on a priority heap.
* The elements of the priority queue are ordered according to their
* {@linkplain Comparable natural ordering}, or by a {@link Comparator}
* provided at queue construction time, depending on which constructor is
* used. A priority queue does not permit {@code null} elements.
* A priority queue relying on natural ordering also does not permit
* insertion of non-comparable objects (doing so may result in
* {@code ClassCastException}).
*
* <p>The <em>head</em> of this queue is the <em>least</em> element
* with respect to the specified ordering. If multiple elements are
* tied for least value, the head is one of those elements -- ties are
* broken arbitrarily. The queue retrieval operations {@code poll},
* {@code remove}, {@code peek}, and {@code element} access the
* element at the head of the queue.
*
* <p>A priority queue is unbounded, but has an internal
* <i>capacity</i> governing the size of an array used to store the
* elements on the queue. It is always at least as large as the queue
* size. As elements are added to a priority queue, its capacity
* grows automatically. The details of the growth policy are not
* specified.
*
* <p>This class and its iterator implement all of the
* <em>optional</em> methods of the {@link Collection} and {@link
* Iterator} interfaces. The Iterator provided in method {@link
* #iterator()} and the Spliterator provided in method {@link #spliterator()}
* are <em>not</em> guaranteed to traverse the elements of
* the priority queue in any particular order. If you need ordered
* traversal, consider using {@code Arrays.sort(pq.toArray())}.
*
* <p><strong>Note that this implementation is not synchronized.</strong>
* Multiple threads should not access a {@code PriorityQueue}
* instance concurrently if any of the threads modifies the queue.
* Instead, use the thread-safe {@link
* java.util.concurrent.PriorityBlockingQueue} class.
*
* <p>Implementation note: this implementation provides
* O(log(n)) time for the enqueuing and dequeuing methods
* ({@code offer}, {@code poll}, {@code remove()} and {@code add});
* linear time for the {@code remove(Object)} and {@code contains(Object)}
* methods; and constant time for the retrieval methods
* ({@code peek}, {@code element}, and {@code size}).
*
* <p>This class is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @since 1.5
* @author Josh Bloch, Doug Lea
* @param <E> the type of elements held in this queue
*/
public class PriorityQueue<E> extends AbstractQueue<E>
implements java.io.Serializable {
private static final long serialVersionUID = -7720805057305804111L;
private static final int DEFAULT_INITIAL_CAPACITY = 11;
/**
* Priority queue represented as a balanced binary heap: the two
* children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The
* priority queue is ordered by comparator, or by the elements'
* natural ordering, if comparator is null: For each node n in the
* heap and each descendant d of n, n <= d. The element with the
* lowest value is in queue[0], assuming the queue is nonempty.
*/
transient Object[] queue; // non-private to simplify nested class access
/**
* The number of elements in the priority queue.
*/
int size;
/**
* The comparator, or null if priority queue uses elements'
* natural ordering.
*/
private final Comparator<? super E> comparator;
/**
* The number of times this priority queue has been
* <i>structurally modified</i>. See AbstractList for gory details.
*/
transient int modCount; // non-private to simplify nested class access
/**
* Creates a {@code PriorityQueue} with the default initial
* capacity (11) that orders its elements according to their
* {@linkplain Comparable natural ordering}.
*/
public PriorityQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
/**
* Creates a {@code PriorityQueue} with the specified initial
* capacity that orders its elements according to their
* {@linkplain Comparable natural ordering}.
*
* @param initialCapacity the initial capacity for this priority queue
* @throws IllegalArgumentException if {@code initialCapacity} is less
* than 1
*/
public PriorityQueue(int initialCapacity) {
this(initialCapacity, null);
}
/**
* Creates a {@code PriorityQueue} with the default initial capacity and
* whose elements are ordered according to the specified comparator.
*
* @param comparator the comparator that will be used to order this
* priority queue. If {@code null}, the {@linkplain Comparable
* natural ordering} of the elements will be used.
* @since 1.8
*/
public PriorityQueue(Comparator<? super E> comparator) {
this(DEFAULT_INITIAL_CAPACITY, comparator);
}
/**
* Creates a {@code PriorityQueue} with the specified initial capacity
* that orders its elements according to the specified comparator.
*
* @param initialCapacity the initial capacity for this priority queue
* @param comparator the comparator that will be used to order this
* priority queue. If {@code null}, the {@linkplain Comparable
* natural ordering} of the elements will be used.
* @throws IllegalArgumentException if {@code initialCapacity} is
* less than 1
*/
public PriorityQueue(int initialCapacity,
Comparator<? super E> comparator) {
// Note: This restriction of at least one is not actually needed,
// but continues for 1.5 compatibility
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.queue = new Object[initialCapacity];
this.comparator = comparator;
}
/**
* Creates a {@code PriorityQueue} containing the elements in the
* specified collection. If the specified collection is an instance of
* a {@link SortedSet} or is another {@code PriorityQueue}, this
* priority queue will be ordered according to the same ordering.
* Otherwise, this priority queue will be ordered according to the
* {@linkplain Comparable natural ordering} of its elements.
*
* @param c the collection whose elements are to be placed
* into this priority queue
* @throws ClassCastException if elements of the specified collection
* cannot be compared to one another according to the priority
* queue's ordering
* @throws NullPointerException if the specified collection or any
* of its elements are null
*/
@SuppressWarnings("unchecked")
public PriorityQueue(Collection<? extends E> c) {
if (c instanceof SortedSet<?>) {
SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
this.comparator = (Comparator<? super E>) ss.comparator();
initElementsFromCollection(ss);
}
else if (c instanceof PriorityQueue<?>) {
PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
this.comparator = (Comparator<? super E>) pq.comparator();
initFromPriorityQueue(pq);
}
else {
this.comparator = null;
initFromCollection(c);
}
}
/**
* Creates a {@code PriorityQueue} containing the elements in the
* specified priority queue. This priority queue will be
* ordered according to the same ordering as the given priority
* queue.
*
* @param c the priority queue whose elements are to be placed
* into this priority queue
* @throws ClassCastException if elements of {@code c} cannot be
* compared to one another according to {@code c}'s
* ordering
* @throws NullPointerException if the specified priority queue or any
* of its elements are null
*/
@SuppressWarnings("unchecked")
public PriorityQueue(PriorityQueue<? extends E> c) {
this.comparator = (Comparator<? super E>) c.comparator();
initFromPriorityQueue(c);
}
/**
* Creates a {@code PriorityQueue} containing the elements in the
* specified sorted set. This priority queue will be ordered
* according to the same ordering as the given sorted set.
*
* @param c the sorted set whose elements are to be placed
* into this priority queue
* @throws ClassCastException if elements of the specified sorted
* set cannot be compared to one another according to the
* sorted set's ordering
* @throws NullPointerException if the specified sorted set or any
* of its elements are null
*/
@SuppressWarnings("unchecked")
public PriorityQueue(SortedSet<? extends E> c) {
this.comparator = (Comparator<? super E>) c.comparator();
initElementsFromCollection(c);
}
private void initFromPriorityQueue(PriorityQueue<? extends E> c) {
if (c.getClass() == PriorityQueue.class) {
this.queue = c.toArray();
this.size = c.size();
} else {
initFromCollection(c);
}
}
private void initElementsFromCollection(Collection<? extends E> c) {
Object[] a = c.toArray();
// If c.toArray incorrectly doesn't return Object[], copy it.
if (a.getClass() != Object[].class)
a = Arrays.copyOf(a, a.length, Object[].class);
int len = a.length;
if (len == 1 || this.comparator != null)
for (Object e : a)
if (e == null)
throw new NullPointerException();
this.queue = a;
this.size = a.length;
}
/**
* Initializes queue array with elements from the given Collection.
*
* @param c the collection
*/
private void initFromCollection(Collection<? extends E> c) {
initElementsFromCollection(c);
heapify();
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Increases the capacity of the array.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
int oldCapacity = queue.length;
// Double size if small; else grow by 50%
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
// overflow-conscious code
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
queue = Arrays.copyOf(queue, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
/**
* Inserts the specified element into this priority queue.
*
* @return {@code true} (as specified by {@link Collection#add})
* @throws ClassCastException if the specified element cannot be
* compared with elements currently in this priority queue
* according to the priority queue's ordering
* @throws NullPointerException if the specified element is null
*/
public boolean add(E e) {
return offer(e);
}
/**
* Inserts the specified element into this priority queue.
*
* @return {@code true} (as specified by {@link Queue#offer})
* @throws ClassCastException if the specified element cannot be
* compared with elements currently in this priority queue
* according to the priority queue's ordering
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1);
siftUp(i, e);
size = i + 1;
return true;
}
@SuppressWarnings("unchecked")
public E peek() {
return (size == 0) ? null : (E) queue[0];
}
private int indexOf(Object o) {
if (o != null) {
for (int i = 0; i < size; i++)
if (o.equals(queue[i]))
return i;
}
return -1;
}
/**
* Removes a single instance of the specified element from this queue,
* if it is present. More formally, removes an element {@code e} such
* that {@code o.equals(e)}, if this queue contains one or more such
* elements. Returns {@code true} if and only if this queue contained
* the specified element (or equivalently, if this queue changed as a
* result of the call).
*
* @param o element to be removed from this queue, if present
* @return {@code true} if this queue changed as a result of the call
*/
public boolean remove(Object o) {
int i = indexOf(o);
if (i == -1)
return false;
else {
removeAt(i);
return true;
}
}
/**
* Version of remove using reference equality, not equals.
* Needed by iterator.remove.
*
* @param o element to be removed from this queue, if present
* @return {@code true} if removed
*/
boolean removeEq(Object o) {
for (int i = 0; i < size; i++) {
if (o == queue[i]) {
removeAt(i);
return true;
}
}
return false;
}
/**
* Returns {@code true} if this queue contains the specified element.
* More formally, returns {@code true} if and only if this queue contains
* at least one element {@code e} such that {@code o.equals(e)}.
*
* @param o object to be checked for containment in this queue
* @return {@code true} if this queue contains the specified element
*/
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
/**
* Returns an array containing all of the elements in this queue.
* The elements are in no particular order.
*
* <p>The returned array will be "safe" in that no references to it are
* maintained by this queue. (In other words, this method must allocate
* a new array). The caller is thus free to modify the returned array.
*
* <p>This method acts as bridge between array-based and collection-based
* APIs.
*
* @return an array containing all of the elements in this queue
*/
public Object[] toArray() {
return Arrays.copyOf(queue, size);
}
/**
* Returns an array containing all of the elements in this queue; the
* runtime type of the returned array is that of the specified array.
* The returned array elements are in no particular order.
* If the queue fits in the specified array, it is returned therein.
* Otherwise, a new array is allocated with the runtime type of the
* specified array and the size of this queue.
*
* <p>If the queue fits in the specified array with room to spare
* (i.e., the array has more elements than the queue), the element in
* the array immediately following the end of the collection is set to
* {@code null}.
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
* <p>Suppose {@code x} is a queue known to contain only strings.
* The following code can be used to dump the queue into a newly
* allocated array of {@code String}:
*
* <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
*
* @param a the array into which the elements of the queue are to
* be stored, if it is big enough; otherwise, a new array of the
* same runtime type is allocated for this purpose.
* @return an array containing all of the elements in this queue
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this queue
* @throws NullPointerException if the specified array is null
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
final int size = this.size;
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(queue, size, a.getClass());
System.arraycopy(queue, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
/**
* Returns an iterator over the elements in this queue. The iterator
* does not return the elements in any particular order.
*
* @return an iterator over the elements in this queue
*/
public Iterator<E> iterator() {
return new Itr();
}
private final class Itr implements Iterator<E> {
/**
* Index (into queue array) of element to be returned by
* subsequent call to next.
*/
private int cursor;
/**
* Index of element returned by most recent call to next,
* unless that element came from the forgetMeNot list.
* Set to -1 if element is deleted by a call to remove.
*/
private int lastRet = -1;
/**
* A queue of elements that were moved from the unvisited portion of
* the heap into the visited portion as a result of "unlucky" element
* removals during the iteration. (Unlucky element removals are those
* that require a siftup instead of a siftdown.) We must visit all of
* the elements in this list to complete the iteration. We do this
* after we've completed the "normal" iteration.
*
* We expect that most iterations, even those involving removals,
* will not need to store elements in this field.
*/
private ArrayDeque<E> forgetMeNot;
/**
* Element returned by the most recent call to next iff that
* element was drawn from the forgetMeNot list.
*/
private E lastRetElt;
/**
* The modCount value that the iterator believes that the backing
* Queue should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
private int expectedModCount = modCount;
Itr() {} // prevent access constructor creation
public boolean hasNext() {
return cursor < size ||
(forgetMeNot != null && !forgetMeNot.isEmpty());
}
@SuppressWarnings("unchecked")
public E next() {
if (expectedModCount != modCount)
throw new ConcurrentModificationException();
if (cursor < size)
return (E) queue[lastRet = cursor++];
if (forgetMeNot != null) {
lastRet = -1;
lastRetElt = forgetMeNot.poll();
if (lastRetElt != null)
return lastRetElt;
}
throw new NoSuchElementException();
}
public void remove() {
if (expectedModCount != modCount)
throw new ConcurrentModificationException();
if (lastRet != -1) {
E moved = PriorityQueue.this.removeAt(lastRet);
lastRet = -1;
if (moved == null)
cursor--;
else {
if (forgetMeNot == null)
forgetMeNot = new ArrayDeque<>();
forgetMeNot.add(moved);
}
} else if (lastRetElt != null) {
PriorityQueue.this.removeEq(lastRetElt);
lastRetElt = null;
} else {
throw new IllegalStateException();
}
expectedModCount = modCount;
}
}
public int size() {
return size;
}
/**
* Removes all of the elements from this priority queue.
* The queue will be empty after this call returns.
*/
public void clear() {
modCount++;
for (int i = 0; i < size; i++)
queue[i] = null;
size = 0;
}
@SuppressWarnings("unchecked")
public E poll() {
if (size == 0)
return null;
int s = --size;
modCount++;
E result = (E) queue[0];
E x = (E) queue[s];
queue[s] = null;
if (s != 0)
siftDown(0, x);
return result;
}
/**
* Removes the ith element from queue.
*
* Normally this method leaves the elements at up to i-1,
* inclusive, untouched. Under these circumstances, it returns
* null. Occasionally, in order to maintain the heap invariant,
* it must swap a later element of the list with one earlier than
* i. Under these circumstances, this method returns the element
* that was previously at the end of the list and is now at some
* position before i. This fact is used by iterator.remove so as to
* avoid missing traversing elements.
*/
@SuppressWarnings("unchecked")
E removeAt(int i) {
// assert i >= 0 && i < size;
modCount++;
int s = --size;
if (s == i) // removed last element
queue[i] = null;
else {
E moved = (E) queue[s];
queue[s] = null;
siftDown(i, moved);
if (queue[i] == moved) {
siftUp(i, moved);
if (queue[i] != moved)
return moved;
}
}
return null;
}
/**
* Inserts item x at position k, maintaining heap invariant by
* promoting x up the tree until it is greater than or equal to
* its parent, or is the root.
*
* To simplify and speed up coercions and comparisons, the
* Comparable and Comparator versions are separated into different
* methods that are otherwise identical. (Similarly for siftDown.)
*
* @param k the position to fill
* @param x the item to insert
*/
private void siftUp(int k, E x) {
if (comparator != null)
siftUpUsingComparator(k, x);
else
siftUpComparable(k, x);
}
@SuppressWarnings("unchecked")
private void siftUpComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>) x;
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (key.compareTo((E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = key;
}
@SuppressWarnings("unchecked")
private void siftUpUsingComparator(int k, E x) {
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (comparator.compare(x, (E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = x;
}
/**
* Inserts item x at position k, maintaining heap invariant by
* demoting x down the tree repeatedly until it is less than or
* equal to its children or is a leaf.
*
* @param k the position to fill
* @param x the item to insert
*/
private void siftDown(int k, E x) {
if (comparator != null)
siftDownUsingComparator(k, x);
else
siftDownComparable(k, x);
}
@SuppressWarnings("unchecked")
private void siftDownComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>)x;
int half = size >>> 1; // loop while a non-leaf
while (k < half) {
int child = (k << 1) + 1; // assume left child is least
Object c = queue[child];
int right = child + 1;
if (right < size &&
((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
c = queue[child = right];
if (key.compareTo((E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = key;
}
@SuppressWarnings("unchecked")
private void siftDownUsingComparator(int k, E x) {
int half = size >>> 1;
while (k < half) {
int child = (k << 1) + 1;
Object c = queue[child];
int right = child + 1;
if (right < size &&
comparator.compare((E) c, (E) queue[right]) > 0)
c = queue[child = right];
if (comparator.compare(x, (E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = x;
}
/**
* Establishes the heap invariant (described above) in the entire tree,
* assuming nothing about the order of the elements prior to the call.
* This classic algorithm due to Floyd (1964) is known to be O(size).
*/
@SuppressWarnings("unchecked")
private void heapify() {
final Object[] es = queue;
int i = (size >>> 1) - 1;
if (comparator == null)
for (; i >= 0; i--)
siftDownComparable(i, (E) es[i]);
else
for (; i >= 0; i--)
siftDownUsingComparator(i, (E) es[i]);
}
/**
* Returns the comparator used to order the elements in this
* queue, or {@code null} if this queue is sorted according to
* the {@linkplain Comparable natural ordering} of its elements.
*
* @return the comparator used to order this queue, or
* {@code null} if this queue is sorted according to the
* natural ordering of its elements
*/
public Comparator<? super E> comparator() {
return comparator;
}
/**
* Saves this queue to a stream (that is, serializes it).
*
* @param s the stream
* @throws java.io.IOException if an I/O error occurs
* @serialData The length of the array backing the instance is
* emitted (int), followed by all of its elements
* (each an {@code Object}) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out element count, and any hidden stuff
s.defaultWriteObject();
// Write out array length, for compatibility with 1.5 version
s.writeInt(Math.max(2, size + 1));
// Write out all elements in the "proper order".
for (int i = 0; i < size; i++)
s.writeObject(queue[i]);
}
/**
* Reconstitutes the {@code PriorityQueue} instance from a stream
* (that is, deserializes it).
*
* @param s the stream
* @throws ClassNotFoundException if the class of a serialized object
* could not be found
* @throws java.io.IOException if an I/O error occurs
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in size, and any hidden stuff
s.defaultReadObject();
// Read in (and discard) array length
s.readInt();
queue = new Object[size];
// Read in all elements.
for (int i = 0; i < size; i++)
queue[i] = s.readObject();
// Elements are guaranteed to be in "proper order", but the
// spec has never explained what that might be.
heapify();
}
/**
* Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
* and <em>fail-fast</em> {@link Spliterator} over the elements in this
* queue. The spliterator does not traverse elements in any particular order
* (the {@link Spliterator#ORDERED ORDERED} characteristic is not reported).
*
* <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, and {@link Spliterator#NONNULL}.
* Overriding implementations should document the reporting of additional
* characteristic values.
*
* @return a {@code Spliterator} over the elements in this queue
* @since 1.8
*/
public final Spliterator<E> spliterator() {
return new PriorityQueueSpliterator(0, -1, 0);
}
final class PriorityQueueSpliterator implements Spliterator<E> {
private int index; // current index, modified on advance/split
private int fence; // -1 until first use
private int expectedModCount; // initialized when fence set
/** Creates new spliterator covering the given range. */
PriorityQueueSpliterator(int origin, int fence, int expectedModCount) {
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}
private int getFence() { // initialize fence to size on first use
int hi;
if ((hi = fence) < 0) {
expectedModCount = modCount;
hi = fence = size;
}
return hi;
}
public PriorityQueueSpliterator trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null :
new PriorityQueueSpliterator(lo, index = mid, expectedModCount);
}
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
if (fence < 0) { fence = size; expectedModCount = modCount; }
final Object[] a = queue;
int i, hi; E e;
for (i = index, index = hi = fence; i < hi; i++) {
if ((e = (E) a[i]) == null)
break; // must be CME
action.accept(e);
}
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
@SuppressWarnings("unchecked")
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
if (fence < 0) { fence = size; expectedModCount = modCount; }
int i;
if ((i = index) < fence) {
index = i + 1;
E e;
if ((e = (E) queue[i]) == null
|| modCount != expectedModCount)
throw new ConcurrentModificationException();
action.accept(e);
return true;
}
return false;
}
public long estimateSize() {
return getFence() - index;
}
public int characteristics() {
return Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.NONNULL;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,665 @@
/*
* 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
* 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;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.security.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.concurrent.ConcurrentHashMap;
import sun.security.util.SecurityConstants;
/**
* This class is for property permissions.
*
* <P>
* The name is the name of the property ("java.home",
* "os.name", etc). The naming
* convention follows the hierarchical property naming convention.
* Also, an asterisk
* may appear at the end of the name, following a ".", or by itself, to
* signify a wildcard match. For example: "java.*" and "*" signify a wildcard
* match, while "*java" and "a*b" do not.
* <P>
* The actions to be granted are passed to the constructor in a string containing
* a list of one or more comma-separated keywords. The possible keywords are
* "read" and "write". Their meaning is defined as follows:
*
* <DL>
* <DT> read
* <DD> read permission. Allows <code>System.getProperty</code> to
* be called.
* <DT> write
* <DD> write permission. Allows <code>System.setProperty</code> to
* be called.
* </DL>
* <P>
* The actions string is converted to lowercase before processing.
* <P>
* Care should be taken before granting code permission to access
* certain system properties. For example, granting permission to
* access the "java.home" system property gives potentially malevolent
* code sensitive information about the system environment (the Java
* installation directory). Also, granting permission to access
* the "user.name" and "user.home" system properties gives potentially
* malevolent code sensitive information about the user environment
* (the user's account name and home directory).
*
* @see java.security.BasicPermission
* @see java.security.Permission
* @see java.security.Permissions
* @see java.security.PermissionCollection
* @see java.lang.SecurityManager
*
*
* @author Roland Schemers
* @since 1.2
*
* @serial exclude
*/
public final class PropertyPermission extends BasicPermission {
/**
* Read action.
*/
private static final int READ = 0x1;
/**
* Write action.
*/
private static final int WRITE = 0x2;
/**
* All actions (read,write);
*/
private static final int ALL = READ|WRITE;
/**
* No actions.
*/
private static final int NONE = 0x0;
/**
* The actions mask.
*
*/
private transient int mask;
/**
* The actions string.
*
* @serial
*/
private String actions; // Left null as long as possible, then
// created and re-used in the getAction function.
/**
* initialize a PropertyPermission object. Common to all constructors.
* Also called during de-serialization.
*
* @param mask the actions mask to use.
*
*/
private void init(int mask) {
if ((mask & ALL) != mask)
throw new IllegalArgumentException("invalid actions mask");
if (mask == NONE)
throw new IllegalArgumentException("invalid actions mask");
if (getName() == null)
throw new NullPointerException("name can't be null");
this.mask = mask;
}
/**
* Creates a new PropertyPermission object with the specified name.
* The name is the name of the system property, and
* <i>actions</i> contains a comma-separated list of the
* desired actions granted on the property. Possible actions are
* "read" and "write".
*
* @param name the name of the PropertyPermission.
* @param actions the actions string.
*
* @throws NullPointerException if <code>name</code> is <code>null</code>.
* @throws IllegalArgumentException if <code>name</code> is empty or if
* <code>actions</code> is invalid.
*/
public PropertyPermission(String name, String actions) {
super(name,actions);
init(getMask(actions));
}
/**
* Creates a PropertyPermission object with the specified name and
* a pre-calculated mask. Avoids the overhead of re-computing the mask.
* Called by PropertyPermissionCollection.
*/
PropertyPermission(String name, int mask) {
super(name, getActions(mask));
this.mask = mask;
}
/**
* Checks if this PropertyPermission object "implies" the specified
* permission.
* <P>
* More specifically, this method returns true if:
* <ul>
* <li> <i>p</i> is an instanceof PropertyPermission,
* <li> <i>p</i>'s actions are a subset of this
* object's actions, and
* <li> <i>p</i>'s name is implied by this object's
* name. For example, "java.*" implies "java.home".
* </ul>
* @param p the permission to check against.
*
* @return true if the specified permission is implied by this object,
* false if not.
*/
@Override
public boolean implies(Permission p) {
if (!(p instanceof PropertyPermission))
return false;
PropertyPermission that = (PropertyPermission) p;
// we get the effective mask. i.e., the "and" of this and that.
// They must be equal to that.mask for implies to return true.
return ((this.mask & that.mask) == that.mask) && super.implies(that);
}
/**
* Checks two PropertyPermission objects for equality. Checks that <i>obj</i> is
* a PropertyPermission, and has the same name and actions as this object.
*
* @param obj the object we are testing for equality with this object.
* @return true if obj is a PropertyPermission, and has the same name and
* actions as this PropertyPermission object.
*/
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (! (obj instanceof PropertyPermission))
return false;
PropertyPermission that = (PropertyPermission) obj;
return (this.mask == that.mask) &&
(this.getName().equals(that.getName()));
}
/**
* Returns the hash code value for this object.
* The hash code used is the hash code of this permissions name, that is,
* <code>getName().hashCode()</code>, where <code>getName</code> is
* from the Permission superclass.
*
* @return a hash code value for this object.
*/
@Override
public int hashCode() {
return this.getName().hashCode();
}
/**
* Converts an actions String to an actions mask.
*
* @param actions the action string.
* @return the actions mask.
*/
private static int getMask(String actions) {
int mask = NONE;
if (actions == null) {
return mask;
}
// Use object identity comparison against known-interned strings for
// performance benefit (these values are used heavily within the JDK).
if (actions == SecurityConstants.PROPERTY_READ_ACTION) {
return READ;
} if (actions == SecurityConstants.PROPERTY_WRITE_ACTION) {
return WRITE;
} else if (actions == SecurityConstants.PROPERTY_RW_ACTION) {
return READ|WRITE;
}
char[] a = actions.toCharArray();
int i = a.length - 1;
if (i < 0)
return mask;
while (i != -1) {
char c;
// skip whitespace
while ((i!=-1) && ((c = a[i]) == ' ' ||
c == '\r' ||
c == '\n' ||
c == '\f' ||
c == '\t'))
i--;
// check for the known strings
int matchlen;
if (i >= 3 && (a[i-3] == 'r' || a[i-3] == 'R') &&
(a[i-2] == 'e' || a[i-2] == 'E') &&
(a[i-1] == 'a' || a[i-1] == 'A') &&
(a[i] == 'd' || a[i] == 'D'))
{
matchlen = 4;
mask |= READ;
} else if (i >= 4 && (a[i-4] == 'w' || a[i-4] == 'W') &&
(a[i-3] == 'r' || a[i-3] == 'R') &&
(a[i-2] == 'i' || a[i-2] == 'I') &&
(a[i-1] == 't' || a[i-1] == 'T') &&
(a[i] == 'e' || a[i] == 'E'))
{
matchlen = 5;
mask |= WRITE;
} else {
// parse error
throw new IllegalArgumentException(
"invalid permission: " + actions);
}
// make sure we didn't just match the tail of a word
// like "ackbarfaccept". Also, skip to the comma.
boolean seencomma = false;
while (i >= matchlen && !seencomma) {
switch(a[i-matchlen]) {
case ',':
seencomma = true;
break;
case ' ': case '\r': case '\n':
case '\f': case '\t':
break;
default:
throw new IllegalArgumentException(
"invalid permission: " + actions);
}
i--;
}
// point i at the location of the comma minus one (or -1).
i -= matchlen;
}
return mask;
}
/**
* Return the canonical string representation of the actions.
* Always returns present actions in the following order:
* read, write.
*
* @return the canonical string representation of the actions.
*/
static String getActions(int mask) {
switch (mask & (READ|WRITE)) {
case READ:
return SecurityConstants.PROPERTY_READ_ACTION;
case WRITE:
return SecurityConstants.PROPERTY_WRITE_ACTION;
case READ|WRITE:
return SecurityConstants.PROPERTY_RW_ACTION;
default:
return "";
}
}
/**
* Returns the "canonical string representation" of the actions.
* That is, this method always returns present actions in the following order:
* read, write. For example, if this PropertyPermission object
* allows both write and read actions, a call to <code>getActions</code>
* will return the string "read,write".
*
* @return the canonical string representation of the actions.
*/
@Override
public String getActions() {
if (actions == null)
actions = getActions(this.mask);
return actions;
}
/**
* Return the current action mask.
* Used by the PropertyPermissionCollection
*
* @return the actions mask.
*/
int getMask() {
return mask;
}
/**
* Returns a new PermissionCollection object for storing
* PropertyPermission objects.
*
* @return a new PermissionCollection object suitable for storing
* PropertyPermissions.
*/
@Override
public PermissionCollection newPermissionCollection() {
return new PropertyPermissionCollection();
}
private static final long serialVersionUID = 885438825399942851L;
/**
* WriteObject is called to save the state of the PropertyPermission
* to a stream. The actions are serialized, and the superclass
* takes care of the name.
*/
private synchronized void writeObject(java.io.ObjectOutputStream s)
throws IOException
{
// Write out the actions. The superclass takes care of the name
// call getActions to make sure actions field is initialized
if (actions == null)
getActions();
s.defaultWriteObject();
}
/**
* readObject is called to restore the state of the PropertyPermission from
* a stream.
*/
private synchronized void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException
{
// Read in the action, then initialize the rest
s.defaultReadObject();
init(getMask(actions));
}
}
/**
* A PropertyPermissionCollection stores a set of PropertyPermission
* permissions.
*
* @see java.security.Permission
* @see java.security.Permissions
* @see java.security.PermissionCollection
*
*
* @author Roland Schemers
*
* @serial include
*/
final class PropertyPermissionCollection extends PermissionCollection
implements Serializable
{
/**
* Key is property name; value is PropertyPermission.
* Not serialized; see serialization section at end of class.
*/
private transient ConcurrentHashMap<String, PropertyPermission> perms;
/**
* Boolean saying if "*" is in the collection.
*
* @see #serialPersistentFields
*/
// No sync access; OK for this to be stale.
private boolean all_allowed;
/**
* Create an empty PropertyPermissionCollection object.
*/
public PropertyPermissionCollection() {
perms = new ConcurrentHashMap<>(32); // Capacity for default policy
all_allowed = false;
}
/**
* Adds a permission to the PropertyPermissions. The key for the hash is
* the name.
*
* @param permission the Permission object to add.
*
* @exception IllegalArgumentException - if the permission is not a
* PropertyPermission
*
* @exception SecurityException - if this PropertyPermissionCollection
* object has been marked readonly
*/
@Override
public void add(Permission permission) {
if (! (permission instanceof PropertyPermission))
throw new IllegalArgumentException("invalid permission: "+
permission);
if (isReadOnly())
throw new SecurityException(
"attempt to add a Permission to a readonly PermissionCollection");
PropertyPermission pp = (PropertyPermission) permission;
String propName = pp.getName();
// Add permission to map if it is absent, or replace with new
// permission if applicable. NOTE: cannot use lambda for
// remappingFunction parameter until JDK-8076596 is fixed.
perms.merge(propName, pp,
new java.util.function.BiFunction<>() {
@Override
public PropertyPermission apply(PropertyPermission existingVal,
PropertyPermission newVal) {
int oldMask = existingVal.getMask();
int newMask = newVal.getMask();
if (oldMask != newMask) {
int effective = oldMask | newMask;
if (effective == newMask) {
return newVal;
}
if (effective != oldMask) {
return new PropertyPermission(propName, effective);
}
}
return existingVal;
}
}
);
if (!all_allowed) {
if (propName.equals("*"))
all_allowed = true;
}
}
/**
* Check and see if this set of permissions implies the permissions
* expressed in "permission".
*
* @param permission the Permission object to compare
*
* @return true if "permission" is a proper subset of a permission in
* the set, false if not.
*/
@Override
public boolean implies(Permission permission) {
if (! (permission instanceof PropertyPermission))
return false;
PropertyPermission pp = (PropertyPermission) permission;
PropertyPermission x;
int desired = pp.getMask();
int effective = 0;
// short circuit if the "*" Permission was added
if (all_allowed) {
x = perms.get("*");
if (x != null) {
effective |= x.getMask();
if ((effective & desired) == desired)
return true;
}
}
// strategy:
// Check for full match first. Then work our way up the
// name looking for matches on a.b.*
String name = pp.getName();
//System.out.println("check "+name);
x = perms.get(name);
if (x != null) {
// we have a direct hit!
effective |= x.getMask();
if ((effective & desired) == desired)
return true;
}
// work our way up the tree...
int last, offset;
offset = name.length()-1;
while ((last = name.lastIndexOf('.', offset)) != -1) {
name = name.substring(0, last+1) + "*";
//System.out.println("check "+name);
x = perms.get(name);
if (x != null) {
effective |= x.getMask();
if ((effective & desired) == desired)
return true;
}
offset = last -1;
}
// we don't have to check for "*" as it was already checked
// at the top (all_allowed), so we just return false
return false;
}
/**
* Returns an enumeration of all the PropertyPermission objects in the
* container.
*
* @return an enumeration of all the PropertyPermission objects.
*/
@Override
@SuppressWarnings("unchecked")
public Enumeration<Permission> elements() {
/**
* Casting to rawtype since Enumeration<PropertyPermission>
* cannot be directly cast to Enumeration<Permission>
*/
return (Enumeration)perms.elements();
}
private static final long serialVersionUID = 7015263904581634791L;
// Need to maintain serialization interoperability with earlier releases,
// which had the serializable field:
//
// Table of permissions.
//
// @serial
//
// private Hashtable permissions;
/**
* @serialField permissions java.util.Hashtable
* A table of the PropertyPermissions.
* @serialField all_allowed boolean
* boolean saying if "*" is in the collection.
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("permissions", Hashtable.class),
new ObjectStreamField("all_allowed", Boolean.TYPE),
};
/**
* @serialData Default fields.
*/
/*
* Writes the contents of the perms field out as a Hashtable for
* serialization compatibility with earlier releases. all_allowed
* unchanged.
*/
private void writeObject(ObjectOutputStream out) throws IOException {
// Don't call out.defaultWriteObject()
// Copy perms into a Hashtable
Hashtable<String, Permission> permissions =
new Hashtable<>(perms.size()*2);
permissions.putAll(perms);
// Write out serializable fields
ObjectOutputStream.PutField pfields = out.putFields();
pfields.put("all_allowed", all_allowed);
pfields.put("permissions", permissions);
out.writeFields();
}
/*
* Reads in a Hashtable of PropertyPermissions and saves them in the
* perms field. Reads in all_allowed.
*/
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException
{
// Don't call defaultReadObject()
// Read in serialized fields
ObjectInputStream.GetField gfields = in.readFields();
// Get all_allowed
all_allowed = gfields.get("all_allowed", false);
// Get permissions
@SuppressWarnings("unchecked")
Hashtable<String, PropertyPermission> permissions =
(Hashtable<String, PropertyPermission>)gfields.get("permissions", null);
perms = new ConcurrentHashMap<>(permissions.size()*2);
perms.putAll(permissions);
}
}

View file

@ -0,0 +1,242 @@
/*
* Copyright (c) 1996, 2016, 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.
*/
/*
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
*
* The original version of this source code and documentation
* is copyrighted and owned by Taligent, Inc., a wholly-owned
* subsidiary of IBM. These materials are provided under terms
* of a License Agreement between Taligent and Sun. This technology
* is protected by multiple US and International patents.
*
* This notice and attribution to Taligent may not be removed.
* Taligent is a registered trademark of Taligent, Inc.
*/
package java.util;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.IOException;
import java.nio.charset.MalformedInputException;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnmappableCharacterException;
import sun.security.action.GetPropertyAction;
import sun.util.PropertyResourceBundleCharset;
import sun.util.ResourceBundleEnumeration;
/**
* <code>PropertyResourceBundle</code> is a concrete subclass of
* <code>ResourceBundle</code> that manages resources for a locale
* using a set of static strings from a property file. See
* {@link ResourceBundle ResourceBundle} for more information about resource
* bundles.
*
* <p>
* Unlike other types of resource bundle, you don't subclass
* <code>PropertyResourceBundle</code>. Instead, you supply properties
* files containing the resource data. <code>ResourceBundle.getBundle</code>
* will automatically look for the appropriate properties file and create a
* <code>PropertyResourceBundle</code> that refers to it. See
* {@link ResourceBundle#getBundle(String, Locale, ClassLoader) ResourceBundle.getBundle}
* for a complete description of the search and instantiation strategy.
*
* <p>
* The following <a id="sample">example</a> shows a member of a resource
* bundle family with the base name "MyResources".
* The text defines the bundle "MyResources_de",
* the German member of the bundle family.
* This member is based on <code>PropertyResourceBundle</code>, and the text
* therefore is the content of the file "MyResources_de.properties"
* (a related <a href="ListResourceBundle.html#sample">example</a> shows
* how you can add bundles to this family that are implemented as subclasses
* of <code>ListResourceBundle</code>).
* The keys in this example are of the form "s1" etc. The actual
* keys are entirely up to your choice, so long as they are the same as
* the keys you use in your program to retrieve the objects from the bundle.
* Keys are case-sensitive.
* <blockquote>
* <pre>
* # MessageFormat pattern
* s1=Die Platte \"{1}\" enth&auml;lt {0}.
*
* # location of {0} in pattern
* s2=1
*
* # sample disk name
* s3=Meine Platte
*
* # first ChoiceFormat choice
* s4=keine Dateien
*
* # second ChoiceFormat choice
* s5=eine Datei
*
* # third ChoiceFormat choice
* s6={0,number} Dateien
*
* # sample date
* s7=3. M&auml;rz 1996
* </pre>
* </blockquote>
*
* @apiNote
* {@code PropertyResourceBundle} can be constructed either
* from an {@code InputStream} or a {@code Reader}, which represents a property file.
* Constructing a {@code PropertyResourceBundle} instance from an {@code InputStream}
* requires that the input stream be encoded in {@code UTF-8}. By default, if a
* {@link java.nio.charset.MalformedInputException} or an
* {@link java.nio.charset.UnmappableCharacterException} occurs on reading the
* input stream, then the {@code PropertyResourceBundle} instance resets to the state
* before the exception, re-reads the input stream in {@code ISO-8859-1}, and
* continues reading. If the system property
* {@code java.util.PropertyResourceBundle.encoding} is set to either
* "ISO-8859-1" or "UTF-8", the input stream is solely read in that encoding,
* and throws the exception if it encounters an invalid sequence.
* If "ISO-8859-1" is specified, characters that cannot be represented in
* ISO-8859-1 encoding must be represented by Unicode Escapes as defined in section
* 3.3 of <cite>The Java&trade; Language Specification</cite>
* whereas the other constructor which takes a {@code Reader} does not have that limitation.
* Other encoding values are ignored for this system property.
* The system property is read and evaluated when initializing this class.
* Changing or removing the property has no effect after the initialization.
*
* @implSpec
* The implementation of a {@code PropertyResourceBundle} subclass must be
* thread-safe if it's simultaneously used by multiple threads. The default
* implementations of the non-abstract methods in this class are thread-safe.
*
* @see ResourceBundle
* @see ListResourceBundle
* @see Properties
* @since 1.1
*/
public class PropertyResourceBundle extends ResourceBundle {
// Check whether the strict encoding is specified.
// The possible encoding is either "ISO-8859-1" or "UTF-8".
private static final String encoding = GetPropertyAction
.privilegedGetProperty("java.util.PropertyResourceBundle.encoding", "")
.toUpperCase(Locale.ROOT);
/**
* Creates a property resource bundle from an {@link java.io.InputStream
* InputStream}. This constructor reads the property file in UTF-8 by default.
* If a {@link java.nio.charset.MalformedInputException} or an
* {@link java.nio.charset.UnmappableCharacterException} occurs on reading the
* input stream, then the PropertyResourceBundle instance resets to the state
* before the exception, re-reads the input stream in {@code ISO-8859-1} and
* continues reading. If the system property
* {@code java.util.PropertyResourceBundle.encoding} is set to either
* "ISO-8859-1" or "UTF-8", the input stream is solely read in that encoding,
* and throws the exception if it encounters an invalid sequence. Other
* encoding values are ignored for this system property.
* The system property is read and evaluated when initializing this class.
* Changing or removing the property has no effect after the initialization.
*
* @param stream an InputStream that represents a property file
* to read from.
* @throws IOException if an I/O error occurs
* @throws NullPointerException if <code>stream</code> is null
* @throws IllegalArgumentException if {@code stream} contains a
* malformed Unicode escape sequence.
* @throws MalformedInputException if the system property
* {@code java.util.PropertyResourceBundle.encoding} is set to "UTF-8"
* and {@code stream} contains an invalid UTF-8 byte sequence.
* @throws UnmappableCharacterException if the system property
* {@code java.util.PropertyResourceBundle.encoding} is set to "UTF-8"
* and {@code stream} contains an unmappable UTF-8 byte sequence.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public PropertyResourceBundle (InputStream stream) throws IOException {
this(new InputStreamReader(stream,
"ISO-8859-1".equals(encoding) ?
StandardCharsets.ISO_8859_1.newDecoder() :
new PropertyResourceBundleCharset("UTF-8".equals(encoding)).newDecoder()));
}
/**
* Creates a property resource bundle from a {@link java.io.Reader
* Reader}. Unlike the constructor
* {@link #PropertyResourceBundle(java.io.InputStream) PropertyResourceBundle(InputStream)},
* there is no limitation as to the encoding of the input property file.
*
* @param reader a Reader that represents a property file to
* read from.
* @throws IOException if an I/O error occurs
* @throws NullPointerException if <code>reader</code> is null
* @throws IllegalArgumentException if a malformed Unicode escape sequence appears
* from {@code reader}.
* @since 1.6
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public PropertyResourceBundle (Reader reader) throws IOException {
Properties properties = new Properties();
properties.load(reader);
lookup = new HashMap(properties);
}
// Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
public Object handleGetObject(String key) {
if (key == null) {
throw new NullPointerException();
}
return lookup.get(key);
}
/**
* Returns an <code>Enumeration</code> of the keys contained in
* this <code>ResourceBundle</code> and its parent bundles.
*
* @return an <code>Enumeration</code> of the keys contained in
* this <code>ResourceBundle</code> and its parent bundles.
* @see #keySet()
*/
public Enumeration<String> getKeys() {
ResourceBundle parent = this.parent;
return new ResourceBundleEnumeration(lookup.keySet(),
(parent != null) ? parent.getKeys() : null);
}
/**
* Returns a <code>Set</code> of the keys contained
* <em>only</em> in this <code>ResourceBundle</code>.
*
* @return a <code>Set</code> of the keys contained only in this
* <code>ResourceBundle</code>
* @since 1.6
* @see #keySet()
*/
protected Set<String> handleKeySet() {
return lookup.keySet();
}
// ==================privates====================
private final Map<String,Object> lookup;
}

View file

@ -0,0 +1,212 @@
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
package java.util;
/**
* A collection designed for holding elements prior to processing.
* Besides basic {@link Collection} operations, queues provide
* additional insertion, extraction, and inspection operations.
* Each of these methods exists in two forms: one throws an exception
* if the operation fails, the other returns a special value (either
* {@code null} or {@code false}, depending on the operation). The
* latter form of the insert operation is designed specifically for
* use with capacity-restricted {@code Queue} implementations; in most
* implementations, insert operations cannot fail.
*
* <table class="striped">
* <caption>Summary of Queue methods</caption>
* <thead>
* <tr>
* <td></td>
* <th scope="col" style="font-weight:normal; font-style:italic">Throws exception</th>
* <th scope="col" style="font-weight:normal; font-style:italic">Returns special value</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th scope="row">Insert</th>
* <td>{@link #add(Object) add(e)}</td>
* <td>{@link #offer(Object) offer(e)}</td>
* </tr>
* <tr>
* <th scope="row">Remove</th>
* <td>{@link #remove() remove()}</td>
* <td>{@link #poll() poll()}</td>
* </tr>
* <tr>
* <th scope="row">Examine</th>
* <td>{@link #element() element()}</td>
* <td>{@link #peek() peek()}</td>
* </tr>
* </tbody>
* </table>
*
* <p>Queues typically, but do not necessarily, order elements in a
* FIFO (first-in-first-out) manner. Among the exceptions are
* priority queues, which order elements according to a supplied
* comparator, or the elements' natural ordering, and LIFO queues (or
* stacks) which order the elements LIFO (last-in-first-out).
* Whatever the ordering used, the <em>head</em> of the queue is that
* element which would be removed by a call to {@link #remove()} or
* {@link #poll()}. In a FIFO queue, all new elements are inserted at
* the <em>tail</em> of the queue. Other kinds of queues may use
* different placement rules. Every {@code Queue} implementation
* must specify its ordering properties.
*
* <p>The {@link #offer offer} method inserts an element if possible,
* otherwise returning {@code false}. This differs from the {@link
* java.util.Collection#add Collection.add} method, which can fail to
* add an element only by throwing an unchecked exception. The
* {@code offer} method is designed for use when failure is a normal,
* rather than exceptional occurrence, for example, in fixed-capacity
* (or &quot;bounded&quot;) queues.
*
* <p>The {@link #remove()} and {@link #poll()} methods remove and
* return the head of the queue.
* Exactly which element is removed from the queue is a
* function of the queue's ordering policy, which differs from
* implementation to implementation. The {@code remove()} and
* {@code poll()} methods differ only in their behavior when the
* queue is empty: the {@code remove()} method throws an exception,
* while the {@code poll()} method returns {@code null}.
*
* <p>The {@link #element()} and {@link #peek()} methods return, but do
* not remove, the head of the queue.
*
* <p>The {@code Queue} interface does not define the <i>blocking queue
* methods</i>, which are common in concurrent programming. These methods,
* which wait for elements to appear or for space to become available, are
* defined in the {@link java.util.concurrent.BlockingQueue} interface, which
* extends this interface.
*
* <p>{@code Queue} implementations generally do not allow insertion
* of {@code null} elements, although some implementations, such as
* {@link LinkedList}, do not prohibit insertion of {@code null}.
* Even in the implementations that permit it, {@code null} should
* not be inserted into a {@code Queue}, as {@code null} is also
* used as a special return value by the {@code poll} method to
* indicate that the queue contains no elements.
*
* <p>{@code Queue} implementations generally do not define
* element-based versions of methods {@code equals} and
* {@code hashCode} but instead inherit the identity based versions
* from class {@code Object}, because element-based equality is not
* always well-defined for queues with the same elements but different
* ordering properties.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @since 1.5
* @author Doug Lea
* @param <E> the type of elements held in this queue
*/
public interface Queue<E> extends Collection<E> {
/**
* Inserts the specified element into this queue if it is possible to do so
* immediately without violating capacity restrictions, returning
* {@code true} upon success and throwing an {@code IllegalStateException}
* if no space is currently available.
*
* @param e the element to add
* @return {@code true} (as specified by {@link Collection#add})
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null and
* this queue does not permit null elements
* @throws IllegalArgumentException if some property of this element
* prevents it from being added to this queue
*/
boolean add(E e);
/**
* Inserts the specified element into this queue if it is possible to do
* so immediately without violating capacity restrictions.
* When using a capacity-restricted queue, this method is generally
* preferable to {@link #add}, which can fail to insert an element only
* by throwing an exception.
*
* @param e the element to add
* @return {@code true} if the element was added to this queue, else
* {@code false}
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null and
* this queue does not permit null elements
* @throws IllegalArgumentException if some property of this element
* prevents it from being added to this queue
*/
boolean offer(E e);
/**
* Retrieves and removes the head of this queue. This method differs
* from {@link #poll() poll()} only in that it throws an exception if
* this queue is empty.
*
* @return the head of this queue
* @throws NoSuchElementException if this queue is empty
*/
E remove();
/**
* Retrieves and removes the head of this queue,
* or returns {@code null} if this queue is empty.
*
* @return the head of this queue, or {@code null} if this queue is empty
*/
E poll();
/**
* Retrieves, but does not remove, the head of this queue. This method
* differs from {@link #peek peek} only in that it throws an exception
* if this queue is empty.
*
* @return the head of this queue
* @throws NoSuchElementException if this queue is empty
*/
E element();
/**
* Retrieves, but does not remove, the head of this queue,
* or returns {@code null} if this queue is empty.
*
* @return the head of this queue, or {@code null} if this queue is empty
*/
E peek();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2000, 2006, 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;
/**
* Marker interface used by {@code List} implementations to indicate that
* they support fast (generally constant time) random access. The primary
* purpose of this interface is to allow generic algorithms to alter their
* behavior to provide good performance when applied to either random or
* sequential access lists.
*
* <p>The best algorithms for manipulating random access lists (such as
* {@code ArrayList}) can produce quadratic behavior when applied to
* sequential access lists (such as {@code LinkedList}). Generic list
* algorithms are encouraged to check whether the given list is an
* {@code instanceof} this interface before applying an algorithm that would
* provide poor performance if it were applied to a sequential access list,
* and to alter their behavior if necessary to guarantee acceptable
* performance.
*
* <p>It is recognized that the distinction between random and sequential
* access is often fuzzy. For example, some {@code List} implementations
* provide asymptotically linear access times if they get huge, but constant
* access times in practice. Such a {@code List} implementation
* should generally implement this interface. As a rule of thumb, a
* {@code List} implementation should implement this interface if,
* for typical instances of the class, this loop:
* <pre>
* for (int i=0, n=list.size(); i &lt; n; i++)
* list.get(i);
* </pre>
* runs faster than this loop:
* <pre>
* for (Iterator i=list.iterator(); i.hasNext(); )
* i.next();
* </pre>
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @since 1.4
*/
public interface RandomAccess {
}

View file

@ -0,0 +1,304 @@
/*
* Copyright (c) 2003, 2012, 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;
/**
* Private implementation class for EnumSet, for "regular sized" enum types
* (i.e., those with 64 or fewer enum constants).
*
* @author Josh Bloch
* @since 1.5
* @serial exclude
*/
class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> {
private static final long serialVersionUID = 3411599620347842686L;
/**
* Bit vector representation of this set. The 2^k bit indicates the
* presence of universe[k] in this set.
*/
private long elements = 0L;
RegularEnumSet(Class<E>elementType, Enum<?>[] universe) {
super(elementType, universe);
}
void addRange(E from, E to) {
elements = (-1L >>> (from.ordinal() - to.ordinal() - 1)) << from.ordinal();
}
void addAll() {
if (universe.length != 0)
elements = -1L >>> -universe.length;
}
void complement() {
if (universe.length != 0) {
elements = ~elements;
elements &= -1L >>> -universe.length; // Mask unused bits
}
}
/**
* Returns an iterator over the elements contained in this set. The
* iterator traverses the elements in their <i>natural order</i> (which is
* the order in which the enum constants are declared). The returned
* Iterator is a "snapshot" iterator that will never throw {@link
* ConcurrentModificationException}; the elements are traversed as they
* existed when this call was invoked.
*
* @return an iterator over the elements contained in this set
*/
public Iterator<E> iterator() {
return new EnumSetIterator<>();
}
private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
/**
* A bit vector representing the elements in the set not yet
* returned by this iterator.
*/
long unseen;
/**
* The bit representing the last element returned by this iterator
* but not removed, or zero if no such element exists.
*/
long lastReturned = 0;
EnumSetIterator() {
unseen = elements;
}
public boolean hasNext() {
return unseen != 0;
}
@SuppressWarnings("unchecked")
public E next() {
if (unseen == 0)
throw new NoSuchElementException();
lastReturned = unseen & -unseen;
unseen -= lastReturned;
return (E) universe[Long.numberOfTrailingZeros(lastReturned)];
}
public void remove() {
if (lastReturned == 0)
throw new IllegalStateException();
elements &= ~lastReturned;
lastReturned = 0;
}
}
/**
* Returns the number of elements in this set.
*
* @return the number of elements in this set
*/
public int size() {
return Long.bitCount(elements);
}
/**
* Returns {@code true} if this set contains no elements.
*
* @return {@code true} if this set contains no elements
*/
public boolean isEmpty() {
return elements == 0;
}
/**
* Returns {@code true} if this set contains the specified element.
*
* @param e element to be checked for containment in this collection
* @return {@code true} if this set contains the specified element
*/
public boolean contains(Object e) {
if (e == null)
return false;
Class<?> eClass = e.getClass();
if (eClass != elementType && eClass.getSuperclass() != elementType)
return false;
return (elements & (1L << ((Enum<?>)e).ordinal())) != 0;
}
// Modification Operations
/**
* Adds the specified element to this set if it is not already present.
*
* @param e element to be added to this set
* @return {@code true} if the set changed as a result of the call
*
* @throws NullPointerException if {@code e} is null
*/
public boolean add(E e) {
typeCheck(e);
long oldElements = elements;
elements |= (1L << ((Enum<?>)e).ordinal());
return elements != oldElements;
}
/**
* Removes the specified element from this set if it is present.
*
* @param e element to be removed from this set, if present
* @return {@code true} if the set contained the specified element
*/
public boolean remove(Object e) {
if (e == null)
return false;
Class<?> eClass = e.getClass();
if (eClass != elementType && eClass.getSuperclass() != elementType)
return false;
long oldElements = elements;
elements &= ~(1L << ((Enum<?>)e).ordinal());
return elements != oldElements;
}
// Bulk Operations
/**
* Returns {@code true} if this set contains all of the elements
* in the specified collection.
*
* @param c collection to be checked for containment in this set
* @return {@code true} if this set contains all of the elements
* in the specified collection
* @throws NullPointerException if the specified collection is null
*/
public boolean containsAll(Collection<?> c) {
if (!(c instanceof RegularEnumSet))
return super.containsAll(c);
RegularEnumSet<?> es = (RegularEnumSet<?>)c;
if (es.elementType != elementType)
return es.isEmpty();
return (es.elements & ~elements) == 0;
}
/**
* Adds all of the elements in the specified collection to this set.
*
* @param c collection whose elements are to be added to this set
* @return {@code true} if this set changed as a result of the call
* @throws NullPointerException if the specified collection or any
* of its elements are null
*/
public boolean addAll(Collection<? extends E> c) {
if (!(c instanceof RegularEnumSet))
return super.addAll(c);
RegularEnumSet<?> es = (RegularEnumSet<?>)c;
if (es.elementType != elementType) {
if (es.isEmpty())
return false;
else
throw new ClassCastException(
es.elementType + " != " + elementType);
}
long oldElements = elements;
elements |= es.elements;
return elements != oldElements;
}
/**
* Removes from this set all of its elements that are contained in
* the specified collection.
*
* @param c elements to be removed from this set
* @return {@code true} if this set changed as a result of the call
* @throws NullPointerException if the specified collection is null
*/
public boolean removeAll(Collection<?> c) {
if (!(c instanceof RegularEnumSet))
return super.removeAll(c);
RegularEnumSet<?> es = (RegularEnumSet<?>)c;
if (es.elementType != elementType)
return false;
long oldElements = elements;
elements &= ~es.elements;
return elements != oldElements;
}
/**
* Retains only the elements in this set that are contained in the
* specified collection.
*
* @param c elements to be retained in this set
* @return {@code true} if this set changed as a result of the call
* @throws NullPointerException if the specified collection is null
*/
public boolean retainAll(Collection<?> c) {
if (!(c instanceof RegularEnumSet))
return super.retainAll(c);
RegularEnumSet<?> es = (RegularEnumSet<?>)c;
if (es.elementType != elementType) {
boolean changed = (elements != 0);
elements = 0;
return changed;
}
long oldElements = elements;
elements &= es.elements;
return elements != oldElements;
}
/**
* Removes all of the elements from this set.
*/
public void clear() {
elements = 0;
}
/**
* Compares the specified object with this set for equality. Returns
* {@code true} if the given object is also a set, the two sets have
* the same size, and every member of the given set is contained in
* this set.
*
* @param o object to be compared for equality with this set
* @return {@code true} if the specified object is equal to this set
*/
public boolean equals(Object o) {
if (!(o instanceof RegularEnumSet))
return super.equals(o);
RegularEnumSet<?> es = (RegularEnumSet<?>)o;
if (es.elementType != elementType)
return elements == 0 && es.elements == 0;
return es.elements == elements;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2005, 2017, 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;
/**
* Error thrown when something goes wrong while locating, loading, or
* instantiating a service provider.
*
* @author Mark Reinhold
* @since 1.6
* @see ServiceLoader
*/
public class ServiceConfigurationError
extends Error
{
private static final long serialVersionUID = 74132770414881L;
/**
* Constructs a new instance with the specified message.
*
* @param msg The message, or {@code null} if there is no message
*
*/
public ServiceConfigurationError(String msg) {
super(msg);
}
/**
* Constructs a new instance with the specified message and cause.
*
* @param msg The message, or {@code null} if there is no message
*
* @param cause The cause, or {@code null} if the cause is nonexistent
* or unknown
*/
public ServiceConfigurationError(String msg, Throwable cause) {
super(msg, cause);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,703 @@
/*
* Copyright (c) 1997, 2017, 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;
/**
* A collection that contains no duplicate elements. More formally, sets
* contain no pair of elements {@code e1} and {@code e2} such that
* {@code e1.equals(e2)}, and at most one null element. As implied by
* its name, this interface models the mathematical <i>set</i> abstraction.
*
* <p>The {@code Set} interface places additional stipulations, beyond those
* inherited from the {@code Collection} interface, on the contracts of all
* constructors and on the contracts of the {@code add}, {@code equals} and
* {@code hashCode} methods. Declarations for other inherited methods are
* also included here for convenience. (The specifications accompanying these
* declarations have been tailored to the {@code Set} interface, but they do
* not contain any additional stipulations.)
*
* <p>The additional stipulation on constructors is, not surprisingly,
* that all constructors must create a set that contains no duplicate elements
* (as defined above).
*
* <p>Note: Great care must be exercised if mutable objects are used as set
* elements. The behavior of a set is not specified if the value of an object
* is changed in a manner that affects {@code equals} comparisons while the
* object is an element in the set. A special case of this prohibition is
* that it is not permissible for a set to contain itself as an element.
*
* <p>Some set implementations have restrictions on the elements that
* they may contain. For example, some implementations prohibit null elements,
* and some have restrictions on the types of their elements. Attempting to
* add an ineligible element throws an unchecked exception, typically
* {@code NullPointerException} or {@code ClassCastException}. Attempting
* to query the presence of an ineligible element may throw an exception,
* or it may simply return false; some implementations will exhibit the former
* behavior and some will exhibit the latter. More generally, attempting an
* operation on an ineligible element whose completion would not result in
* the insertion of an ineligible element into the set may throw an
* exception or it may succeed, at the option of the implementation.
* Such exceptions are marked as "optional" in the specification for this
* interface.
*
* <h2><a id="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. Calling any mutator method will always cause
* {@code UnsupportedOperationException} to be thrown.
* 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.
* <li>They are serialized as specified on the
* <a href="{@docRoot}/serialized-form.html#java.util.CollSer">Serialized Form</a>
* page.
* </ul>
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <E> the type of elements maintained by this set
*
* @author Josh Bloch
* @author Neal Gafter
* @see Collection
* @see List
* @see SortedSet
* @see HashSet
* @see TreeSet
* @see AbstractSet
* @see Collections#singleton(java.lang.Object)
* @see Collections#EMPTY_SET
* @since 1.2
*/
public interface Set<E> extends Collection<E> {
// Query Operations
/**
* Returns the number of elements in this set (its cardinality). If this
* set contains more than {@code Integer.MAX_VALUE} elements, returns
* {@code Integer.MAX_VALUE}.
*
* @return the number of elements in this set (its cardinality)
*/
int size();
/**
* Returns {@code true} if this set contains no elements.
*
* @return {@code true} if this set contains no elements
*/
boolean isEmpty();
/**
* Returns {@code true} if this set contains the specified element.
* More formally, returns {@code true} if and only if this set
* contains an element {@code e} such that
* {@code Objects.equals(o, e)}.
*
* @param o element whose presence in this set is to be tested
* @return {@code true} if this set contains the specified element
* @throws ClassCastException if the type of the specified element
* is incompatible with this set
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* set does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>)
*/
boolean contains(Object o);
/**
* Returns an iterator over the elements in this set. The elements are
* returned in no particular order (unless this set is an instance of some
* class that provides a guarantee).
*
* @return an iterator over the elements in this set
*/
Iterator<E> iterator();
/**
* Returns an array containing all of the elements in this set.
* If this set makes any guarantees as to what order its elements
* are returned by its iterator, this method must return the
* elements in the same order.
*
* <p>The returned array will be "safe" in that no references to it
* are maintained by this set. (In other words, this method must
* allocate a new array even if this set is backed by an array).
* The caller is thus free to modify the returned array.
*
* <p>This method acts as bridge between array-based and collection-based
* APIs.
*
* @return an array containing all the elements in this set
*/
Object[] toArray();
/**
* Returns an array containing all of the elements in this set; the
* runtime type of the returned array is that of the specified array.
* If the set fits in the specified array, it is returned therein.
* Otherwise, a new array is allocated with the runtime type of the
* specified array and the size of this set.
*
* <p>If this set fits in the specified array with room to spare
* (i.e., the array has more elements than this set), the element in
* the array immediately following the end of the set is set to
* {@code null}. (This is useful in determining the length of this
* set <i>only</i> if the caller knows that this set does not contain
* any null elements.)
*
* <p>If this set makes any guarantees as to what order its elements
* are returned by its iterator, this method must return the elements
* in the same order.
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
* <p>Suppose {@code x} is a set known to contain only strings.
* The following code can be used to dump the set into a newly allocated
* array of {@code String}:
*
* <pre>
* String[] y = x.toArray(new String[0]);</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
*
* @param a the array into which the elements of this set are to be
* stored, if it is big enough; otherwise, a new array of the same
* runtime type is allocated for this purpose.
* @return an array containing all the elements in this set
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in this
* set
* @throws NullPointerException if the specified array is null
*/
<T> T[] toArray(T[] a);
// Modification Operations
/**
* Adds the specified element to this set if it is not already present
* (optional operation). More formally, adds the specified element
* {@code e} to this set if the set contains no element {@code e2}
* such that
* {@code Objects.equals(e, e2)}.
* If this set already contains the element, the call leaves the set
* unchanged and returns {@code false}. In combination with the
* restriction on constructors, this ensures that sets never contain
* duplicate elements.
*
* <p>The stipulation above does not imply that sets must accept all
* elements; sets may refuse to add any particular element, including
* {@code null}, and throw an exception, as described in the
* specification for {@link Collection#add Collection.add}.
* Individual set implementations should clearly document any
* restrictions on the elements that they may contain.
*
* @param e element to be added to this set
* @return {@code true} if this set did not already contain the specified
* element
* @throws UnsupportedOperationException if the {@code add} operation
* is not supported by this set
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this set
* @throws NullPointerException if the specified element is null and this
* set does not permit null elements
* @throws IllegalArgumentException if some property of the specified element
* prevents it from being added to this set
*/
boolean add(E e);
/**
* Removes the specified element from this set if it is present
* (optional operation). More formally, removes an element {@code e}
* such that
* {@code Objects.equals(o, e)}, if
* this set contains such an element. Returns {@code true} if this set
* contained the element (or equivalently, if this set changed as a
* result of the call). (This set will not contain the element once the
* call returns.)
*
* @param o object to be removed from this set, if present
* @return {@code true} if this set contained the specified element
* @throws ClassCastException if the type of the specified element
* is incompatible with this set
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* set does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws UnsupportedOperationException if the {@code remove} operation
* is not supported by this set
*/
boolean remove(Object o);
// Bulk Operations
/**
* Returns {@code true} if this set contains all of the elements of the
* specified collection. If the specified collection is also a set, this
* method returns {@code true} if it is a <i>subset</i> of this set.
*
* @param c collection to be checked for containment in this set
* @return {@code true} if this set contains all of the elements of the
* specified collection
* @throws ClassCastException if the types of one or more elements
* in the specified collection are incompatible with this
* set
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified collection contains one
* or more null elements and this set does not permit null
* elements
* (<a href="Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #contains(Object)
*/
boolean containsAll(Collection<?> c);
/**
* Adds all of the elements in the specified collection to this set if
* they're not already present (optional operation). If the specified
* collection is also a set, the {@code addAll} operation effectively
* modifies this set so that its value is the <i>union</i> of the two
* sets. The behavior of this operation is undefined if the specified
* collection is modified while the operation is in progress.
*
* @param c collection containing elements to be added to this set
* @return {@code true} if this set changed as a result of the call
*
* @throws UnsupportedOperationException if the {@code addAll} operation
* is not supported by this set
* @throws ClassCastException if the class of an element of the
* specified collection prevents it from being added to this set
* @throws NullPointerException if the specified collection contains one
* or more null elements and this set does not permit null
* elements, or if the specified collection is null
* @throws IllegalArgumentException if some property of an element of the
* specified collection prevents it from being added to this set
* @see #add(Object)
*/
boolean addAll(Collection<? extends E> c);
/**
* Retains only the elements in this set that are contained in the
* specified collection (optional operation). In other words, removes
* from this set all of its elements that are not contained in the
* specified collection. If the specified collection is also a set, this
* operation effectively modifies this set so that its value is the
* <i>intersection</i> of the two sets.
*
* @param c collection containing elements to be retained in this set
* @return {@code true} if this set changed as a result of the call
* @throws UnsupportedOperationException if the {@code retainAll} operation
* is not supported by this set
* @throws ClassCastException if the class of an element of this set
* is incompatible with the specified collection
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this set contains a null element and the
* specified collection does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #remove(Object)
*/
boolean retainAll(Collection<?> c);
/**
* Removes from this set all of its elements that are contained in the
* specified collection (optional operation). If the specified
* collection is also a set, this operation effectively modifies this
* set so that its value is the <i>asymmetric set difference</i> of
* the two sets.
*
* @param c collection containing elements to be removed from this set
* @return {@code true} if this set changed as a result of the call
* @throws UnsupportedOperationException if the {@code removeAll} operation
* is not supported by this set
* @throws ClassCastException if the class of an element of this set
* is incompatible with the specified collection
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this set contains a null element and the
* specified collection does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #remove(Object)
* @see #contains(Object)
*/
boolean removeAll(Collection<?> c);
/**
* Removes all of the elements from this set (optional operation).
* The set will be empty after this call returns.
*
* @throws UnsupportedOperationException if the {@code clear} method
* is not supported by this set
*/
void clear();
// Comparison and hashing
/**
* Compares the specified object with this set for equality. Returns
* {@code true} if the specified object is also a set, the two sets
* have the same size, and every member of the specified set is
* contained in this set (or equivalently, every member of this set is
* contained in the specified set). This definition ensures that the
* equals method works properly across different implementations of the
* set interface.
*
* @param o object to be compared for equality with this set
* @return {@code true} if the specified object is equal to this set
*/
boolean equals(Object o);
/**
* Returns the hash code value for this set. The hash code of a set is
* defined to be the sum of the hash codes of the elements in the set,
* where the hash code of a {@code null} element is defined to be zero.
* This ensures that {@code s1.equals(s2)} implies that
* {@code s1.hashCode()==s2.hashCode()} for any two sets {@code s1}
* and {@code s2}, as required by the general contract of
* {@link Object#hashCode}.
*
* @return the hash code value for this set
* @see Object#equals(Object)
* @see Set#equals(Object)
*/
int hashCode();
/**
* Creates a {@code Spliterator} over the elements in this set.
*
* <p>The {@code Spliterator} reports {@link Spliterator#DISTINCT}.
* Implementations should document the reporting of additional
* characteristic values.
*
* @implSpec
* The default implementation creates a
* <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator
* from the set's {@code Iterator}. The spliterator inherits the
* <em>fail-fast</em> properties of the set's iterator.
* <p>
* The created {@code Spliterator} additionally reports
* {@link Spliterator#SIZED}.
*
* @implNote
* The created {@code Spliterator} additionally reports
* {@link Spliterator#SUBSIZED}.
*
* @return a {@code Spliterator} over the elements in this set
* @since 1.8
*/
@Override
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 ImmutableCollections.Set0.instance();
}
/**
* 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 new ImmutableCollections.Set1<>(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) {
return new ImmutableCollections.Set2<>(e1, e2);
}
/**
* 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) {
return new ImmutableCollections.SetN<>(e1, e2, e3);
}
/**
* 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) {
return new ImmutableCollections.SetN<>(e1, e2, e3, e4);
}
/**
* 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) {
return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5);
}
/**
* 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) {
return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5,
e6);
}
/**
* 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) {
return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5,
e6, e7);
}
/**
* 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) {
return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5,
e6, e7, e8);
}
/**
* 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) {
return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5,
e6, e7, e8, e9);
}
/**
* 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) {
return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5,
e6, e7, e8, e9, e10);
}
/**
* 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
@SuppressWarnings("varargs")
static <E> Set<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
return ImmutableCollections.Set0.instance();
case 1:
return new ImmutableCollections.Set1<>(elements[0]);
case 2:
return new ImmutableCollections.Set2<>(elements[0], elements[1]);
default:
return new ImmutableCollections.SetN<>(elements);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,284 @@
/*
* Copyright (c) 1998, 2011, 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;
/**
* A {@link Map} that further provides a <em>total ordering</em> on its keys.
* The map is ordered according to the {@linkplain Comparable natural
* ordering} of its keys, or by a {@link Comparator} typically
* provided at sorted map creation time. This order is reflected when
* iterating over the sorted map's collection views (returned by the
* {@code entrySet}, {@code keySet} and {@code values} methods).
* Several additional operations are provided to take advantage of the
* ordering. (This interface is the map analogue of {@link SortedSet}.)
*
* <p>All keys inserted into a sorted map must implement the {@code Comparable}
* interface (or be accepted by the specified comparator). Furthermore, all
* such keys must be <em>mutually comparable</em>: {@code k1.compareTo(k2)} (or
* {@code comparator.compare(k1, k2)}) must not throw a
* {@code ClassCastException} for any keys {@code k1} and {@code k2} in
* the sorted map. Attempts to violate this restriction will cause the
* offending method or constructor invocation to throw a
* {@code ClassCastException}.
*
* <p>Note that the ordering maintained by a sorted map (whether or not an
* explicit comparator is provided) must be <em>consistent with equals</em> if
* the sorted map is to correctly implement the {@code Map} interface. (See
* the {@code Comparable} interface or {@code Comparator} interface for a
* precise definition of <em>consistent with equals</em>.) This is so because
* the {@code Map} interface is defined in terms of the {@code equals}
* operation, but a sorted map performs all key comparisons using its
* {@code compareTo} (or {@code compare}) method, so two keys that are
* deemed equal by this method are, from the standpoint of the sorted map,
* equal. The behavior of a tree map <em>is</em> well-defined even if its
* ordering is inconsistent with equals; it just fails to obey the general
* contract of the {@code Map} interface.
*
* <p>All general-purpose sorted map implementation classes should provide four
* "standard" constructors. It is not possible to enforce this recommendation
* though as required constructors cannot be specified by interfaces. The
* expected "standard" constructors for all sorted map implementations are:
* <ol>
* <li>A void (no arguments) constructor, which creates an empty sorted map
* sorted according to the natural ordering of its keys.</li>
* <li>A constructor with a single argument of type {@code Comparator}, which
* creates an empty sorted map sorted according to the specified comparator.</li>
* <li>A constructor with a single argument of type {@code Map}, which creates
* a new map with the same key-value mappings as its argument, sorted
* according to the keys' natural ordering.</li>
* <li>A constructor with a single argument of type {@code SortedMap}, which
* creates a new sorted map with the same key-value mappings and the same
* ordering as the input sorted map.</li>
* </ol>
*
* <p><strong>Note</strong>: several methods return submaps with restricted key
* ranges. Such ranges are <em>half-open</em>, that is, they include their low
* endpoint but not their high endpoint (where applicable). If you need a
* <em>closed range</em> (which includes both endpoints), and the key type
* allows for calculation of the successor of a given key, merely request
* the subrange from {@code lowEndpoint} to
* {@code successor(highEndpoint)}. For example, suppose that {@code m}
* is a map whose keys are strings. The following idiom obtains a view
* containing all of the key-value mappings in {@code m} whose keys are
* between {@code low} and {@code high}, inclusive:<pre>
* SortedMap&lt;String, V&gt; sub = m.subMap(low, high+"\0");</pre>
*
* A similar technique can be used to generate an <em>open range</em>
* (which contains neither endpoint). The following idiom obtains a
* view containing all of the key-value mappings in {@code m} whose keys
* are between {@code low} and {@code high}, exclusive:<pre>
* SortedMap&lt;String, V&gt; sub = m.subMap(low+"\0", high);</pre>
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
*
* @author Josh Bloch
* @see Map
* @see TreeMap
* @see SortedSet
* @see Comparator
* @see Comparable
* @see Collection
* @see ClassCastException
* @since 1.2
*/
public interface SortedMap<K,V> extends Map<K,V> {
/**
* Returns the comparator used to order the keys in this map, or
* {@code null} if this map uses the {@linkplain Comparable
* natural ordering} of its keys.
*
* @return the comparator used to order the keys in this map,
* or {@code null} if this map uses the natural ordering
* of its keys
*/
Comparator<? super K> comparator();
/**
* Returns a view of the portion of this map whose keys range from
* {@code fromKey}, inclusive, to {@code toKey}, exclusive. (If
* {@code fromKey} and {@code toKey} are equal, the returned map
* is empty.) The returned map is backed by this map, so changes
* in the returned map are reflected in this map, and vice-versa.
* The returned map supports all optional map operations that this
* map supports.
*
* <p>The returned map will throw an {@code IllegalArgumentException}
* on an attempt to insert a key outside its range.
*
* @param fromKey low endpoint (inclusive) of the keys in the returned map
* @param toKey high endpoint (exclusive) of the keys in the returned map
* @return a view of the portion of this map whose keys range from
* {@code fromKey}, inclusive, to {@code toKey}, exclusive
* @throws ClassCastException if {@code fromKey} and {@code toKey}
* cannot be compared to one another using this map's comparator
* (or, if the map has no comparator, using natural ordering).
* Implementations may, but are not required to, throw this
* exception if {@code fromKey} or {@code toKey}
* cannot be compared to keys currently in the map.
* @throws NullPointerException if {@code fromKey} or {@code toKey}
* is null and this map does not permit null keys
* @throws IllegalArgumentException if {@code fromKey} is greater than
* {@code toKey}; or if this map itself has a restricted
* range, and {@code fromKey} or {@code toKey} lies
* outside the bounds of the range
*/
SortedMap<K,V> subMap(K fromKey, K toKey);
/**
* Returns a view of the portion of this map whose keys are
* strictly less than {@code toKey}. The returned map is backed
* by this map, so changes in the returned map are reflected in
* this map, and vice-versa. The returned map supports all
* optional map operations that this map supports.
*
* <p>The returned map will throw an {@code IllegalArgumentException}
* on an attempt to insert a key outside its range.
*
* @param toKey high endpoint (exclusive) of the keys in the returned map
* @return a view of the portion of this map whose keys are strictly
* less than {@code toKey}
* @throws ClassCastException if {@code toKey} is not compatible
* with this map's comparator (or, if the map has no comparator,
* if {@code toKey} does not implement {@link Comparable}).
* Implementations may, but are not required to, throw this
* exception if {@code toKey} cannot be compared to keys
* currently in the map.
* @throws NullPointerException if {@code toKey} is null and
* this map does not permit null keys
* @throws IllegalArgumentException if this map itself has a
* restricted range, and {@code toKey} lies outside the
* bounds of the range
*/
SortedMap<K,V> headMap(K toKey);
/**
* Returns a view of the portion of this map whose keys are
* greater than or equal to {@code fromKey}. The returned map is
* backed by this map, so changes in the returned map are
* reflected in this map, and vice-versa. The returned map
* supports all optional map operations that this map supports.
*
* <p>The returned map will throw an {@code IllegalArgumentException}
* on an attempt to insert a key outside its range.
*
* @param fromKey low endpoint (inclusive) of the keys in the returned map
* @return a view of the portion of this map whose keys are greater
* than or equal to {@code fromKey}
* @throws ClassCastException if {@code fromKey} is not compatible
* with this map's comparator (or, if the map has no comparator,
* if {@code fromKey} does not implement {@link Comparable}).
* Implementations may, but are not required to, throw this
* exception if {@code fromKey} cannot be compared to keys
* currently in the map.
* @throws NullPointerException if {@code fromKey} is null and
* this map does not permit null keys
* @throws IllegalArgumentException if this map itself has a
* restricted range, and {@code fromKey} lies outside the
* bounds of the range
*/
SortedMap<K,V> tailMap(K fromKey);
/**
* Returns the first (lowest) key currently in this map.
*
* @return the first (lowest) key currently in this map
* @throws NoSuchElementException if this map is empty
*/
K firstKey();
/**
* Returns the last (highest) key currently in this map.
*
* @return the last (highest) key currently in this map
* @throws NoSuchElementException if this map is empty
*/
K lastKey();
/**
* Returns a {@link Set} view of the keys contained in this map.
* The set's iterator returns the keys in ascending order.
* The set is backed by the map, so changes to the map are
* reflected in the set, and vice-versa. If the map is modified
* while an iteration over the set is in progress (except through
* the iterator's own {@code remove} operation), the results of
* the iteration are undefined. The set supports element removal,
* which removes the corresponding mapping from the map, via the
* {@code Iterator.remove}, {@code Set.remove},
* {@code removeAll}, {@code retainAll}, and {@code clear}
* operations. It does not support the {@code add} or {@code addAll}
* operations.
*
* @return a set view of the keys contained in this map, sorted in
* ascending order
*/
Set<K> keySet();
/**
* Returns a {@link Collection} view of the values contained in this map.
* The collection's iterator returns the values in ascending order
* of the corresponding keys.
* The collection is backed by the map, so changes to the map are
* reflected in the collection, and vice-versa. If the map is
* modified while an iteration over the collection is in progress
* (except through the iterator's own {@code remove} operation),
* the results of the iteration are undefined. The collection
* supports element removal, which removes the corresponding
* mapping from the map, via the {@code Iterator.remove},
* {@code Collection.remove}, {@code removeAll},
* {@code retainAll} and {@code clear} operations. It does not
* support the {@code add} or {@code addAll} operations.
*
* @return a collection view of the values contained in this map,
* sorted in ascending key order
*/
Collection<V> values();
/**
* Returns a {@link Set} view of the mappings contained in this map.
* The set's iterator returns the entries in ascending key order.
* The set is backed by the map, so changes to the map are
* reflected in the set, and vice-versa. If the map is modified
* while an iteration over the set is in progress (except through
* the iterator's own {@code remove} operation, or through the
* {@code setValue} operation on a map entry returned by the
* iterator) the results of the iteration are undefined. The set
* supports element removal, which removes the corresponding
* mapping from the map, via the {@code Iterator.remove},
* {@code Set.remove}, {@code removeAll}, {@code retainAll} and
* {@code clear} operations. It does not support the
* {@code add} or {@code addAll} operations.
*
* @return a set view of the mappings contained in this map,
* sorted in ascending key order
*/
Set<Map.Entry<K, V>> entrySet();
}

View file

@ -0,0 +1,264 @@
/*
* Copyright (c) 1998, 2013, 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;
/**
* A {@link Set} that further provides a <i>total ordering</i> on its elements.
* The elements are ordered using their {@linkplain Comparable natural
* ordering}, or by a {@link Comparator} typically provided at sorted
* set creation time. The set's iterator will traverse the set in
* ascending element order. Several additional operations are provided
* to take advantage of the ordering. (This interface is the set
* analogue of {@link SortedMap}.)
*
* <p>All elements inserted into a sorted set must implement the {@code Comparable}
* interface (or be accepted by the specified comparator). Furthermore, all
* such elements must be <i>mutually comparable</i>: {@code e1.compareTo(e2)}
* (or {@code comparator.compare(e1, e2)}) must not throw a
* {@code ClassCastException} for any elements {@code e1} and {@code e2} in
* the sorted set. Attempts to violate this restriction will cause the
* offending method or constructor invocation to throw a
* {@code ClassCastException}.
*
* <p>Note that the ordering maintained by a sorted set (whether or not an
* explicit comparator is provided) must be <i>consistent with equals</i> if
* the sorted set is to correctly implement the {@code Set} interface. (See
* the {@code Comparable} interface or {@code Comparator} interface for a
* precise definition of <i>consistent with equals</i>.) This is so because
* the {@code Set} interface is defined in terms of the {@code equals}
* operation, but a sorted set performs all element comparisons using its
* {@code compareTo} (or {@code compare}) method, so two elements that are
* deemed equal by this method are, from the standpoint of the sorted set,
* equal. The behavior of a sorted set <i>is</i> well-defined even if its
* ordering is inconsistent with equals; it just fails to obey the general
* contract of the {@code Set} interface.
*
* <p>All general-purpose sorted set implementation classes should
* provide four "standard" constructors: 1) A void (no arguments)
* constructor, which creates an empty sorted set sorted according to
* the natural ordering of its elements. 2) A constructor with a
* single argument of type {@code Comparator}, which creates an empty
* sorted set sorted according to the specified comparator. 3) A
* constructor with a single argument of type {@code Collection},
* which creates a new sorted set with the same elements as its
* argument, sorted according to the natural ordering of the elements.
* 4) A constructor with a single argument of type {@code SortedSet},
* which creates a new sorted set with the same elements and the same
* ordering as the input sorted set. There is no way to enforce this
* recommendation, as interfaces cannot contain constructors.
*
* <p>Note: several methods return subsets with restricted ranges.
* Such ranges are <i>half-open</i>, that is, they include their low
* endpoint but not their high endpoint (where applicable).
* If you need a <i>closed range</i> (which includes both endpoints), and
* the element type allows for calculation of the successor of a given
* value, merely request the subrange from {@code lowEndpoint} to
* {@code successor(highEndpoint)}. For example, suppose that {@code s}
* is a sorted set of strings. The following idiom obtains a view
* containing all of the strings in {@code s} from {@code low} to
* {@code high}, inclusive:<pre>
* SortedSet&lt;String&gt; sub = s.subSet(low, high+"\0");</pre>
*
* A similar technique can be used to generate an <i>open range</i> (which
* contains neither endpoint). The following idiom obtains a view
* containing all of the Strings in {@code s} from {@code low} to
* {@code high}, exclusive:<pre>
* SortedSet&lt;String&gt; sub = s.subSet(low+"\0", high);</pre>
*
* <p>This interface is a member of the
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <E> the type of elements maintained by this set
*
* @author Josh Bloch
* @see Set
* @see TreeSet
* @see SortedMap
* @see Collection
* @see Comparable
* @see Comparator
* @see ClassCastException
* @since 1.2
*/
public interface SortedSet<E> extends Set<E> {
/**
* Returns the comparator used to order the elements in this set,
* or {@code null} if this set uses the {@linkplain Comparable
* natural ordering} of its elements.
*
* @return the comparator used to order the elements in this set,
* or {@code null} if this set uses the natural ordering
* of its elements
*/
Comparator<? super E> comparator();
/**
* Returns a view of the portion of this set whose elements range
* from {@code fromElement}, inclusive, to {@code toElement},
* exclusive. (If {@code fromElement} and {@code toElement} are
* equal, the returned set is empty.) The returned set is backed
* by this set, so changes in the returned set are reflected in
* this set, and vice-versa. The returned set supports all
* optional set operations that this set supports.
*
* <p>The returned set will throw an {@code IllegalArgumentException}
* on an attempt to insert an element outside its range.
*
* @param fromElement low endpoint (inclusive) of the returned set
* @param toElement high endpoint (exclusive) of the returned set
* @return a view of the portion of this set whose elements range from
* {@code fromElement}, inclusive, to {@code toElement}, exclusive
* @throws ClassCastException if {@code fromElement} and
* {@code toElement} cannot be compared to one another using this
* set's comparator (or, if the set has no comparator, using
* natural ordering). Implementations may, but are not required
* to, throw this exception if {@code fromElement} or
* {@code toElement} cannot be compared to elements currently in
* the set.
* @throws NullPointerException if {@code fromElement} or
* {@code toElement} is null and this set does not permit null
* elements
* @throws IllegalArgumentException if {@code fromElement} is
* greater than {@code toElement}; or if this set itself
* has a restricted range, and {@code fromElement} or
* {@code toElement} lies outside the bounds of the range
*/
SortedSet<E> subSet(E fromElement, E toElement);
/**
* Returns a view of the portion of this set whose elements are
* strictly less than {@code toElement}. The returned set is
* backed by this set, so changes in the returned set are
* reflected in this set, and vice-versa. The returned set
* supports all optional set operations that this set supports.
*
* <p>The returned set will throw an {@code IllegalArgumentException}
* on an attempt to insert an element outside its range.
*
* @param toElement high endpoint (exclusive) of the returned set
* @return a view of the portion of this set whose elements are strictly
* less than {@code toElement}
* @throws ClassCastException if {@code toElement} is not compatible
* with this set's comparator (or, if the set has no comparator,
* if {@code toElement} does not implement {@link Comparable}).
* Implementations may, but are not required to, throw this
* exception if {@code toElement} cannot be compared to elements
* currently in the set.
* @throws NullPointerException if {@code toElement} is null and
* this set does not permit null elements
* @throws IllegalArgumentException if this set itself has a
* restricted range, and {@code toElement} lies outside the
* bounds of the range
*/
SortedSet<E> headSet(E toElement);
/**
* Returns a view of the portion of this set whose elements are
* greater than or equal to {@code fromElement}. The returned
* set is backed by this set, so changes in the returned set are
* reflected in this set, and vice-versa. The returned set
* supports all optional set operations that this set supports.
*
* <p>The returned set will throw an {@code IllegalArgumentException}
* on an attempt to insert an element outside its range.
*
* @param fromElement low endpoint (inclusive) of the returned set
* @return a view of the portion of this set whose elements are greater
* than or equal to {@code fromElement}
* @throws ClassCastException if {@code fromElement} is not compatible
* with this set's comparator (or, if the set has no comparator,
* if {@code fromElement} does not implement {@link Comparable}).
* Implementations may, but are not required to, throw this
* exception if {@code fromElement} cannot be compared to elements
* currently in the set.
* @throws NullPointerException if {@code fromElement} is null
* and this set does not permit null elements
* @throws IllegalArgumentException if this set itself has a
* restricted range, and {@code fromElement} lies outside the
* bounds of the range
*/
SortedSet<E> tailSet(E fromElement);
/**
* Returns the first (lowest) element currently in this set.
*
* @return the first (lowest) element currently in this set
* @throws NoSuchElementException if this set is empty
*/
E first();
/**
* Returns the last (highest) element currently in this set.
*
* @return the last (highest) element currently in this set
* @throws NoSuchElementException if this set is empty
*/
E last();
/**
* Creates a {@code Spliterator} over the elements in this sorted set.
*
* <p>The {@code Spliterator} reports {@link Spliterator#DISTINCT},
* {@link Spliterator#SORTED} and {@link Spliterator#ORDERED}.
* Implementations should document the reporting of additional
* characteristic values.
*
* <p>The spliterator's comparator (see
* {@link java.util.Spliterator#getComparator()}) must be {@code null} if
* the sorted set's comparator (see {@link #comparator()}) is {@code null}.
* Otherwise, the spliterator's comparator must be the same as or impose the
* same total ordering as the sorted set's comparator.
*
* @implSpec
* The default implementation creates a
* <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator
* from the sorted set's {@code Iterator}. The spliterator inherits the
* <em>fail-fast</em> properties of the set's iterator. The
* spliterator's comparator is the same as the sorted set's comparator.
* <p>
* The created {@code Spliterator} additionally reports
* {@link Spliterator#SIZED}.
*
* @implNote
* The created {@code Spliterator} additionally reports
* {@link Spliterator#SUBSIZED}.
*
* @return a {@code Spliterator} over the elements in this sorted set
* @since 1.8
*/
@Override
default Spliterator<E> spliterator() {
return new Spliterators.IteratorSpliterator<E>(
this, Spliterator.DISTINCT | Spliterator.SORTED | Spliterator.ORDERED) {
@Override
public Comparator<? super E> getComparator() {
return SortedSet.this.comparator();
}
};
}
}

Some files were not shown because too many files have changed in this diff Show more