feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,469 @@
/*
* 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 <tt>Collection</tt>
* 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 <tt>iterator</tt> and
* <tt>size</tt> methods. (The iterator returned by the <tt>iterator</tt>
* method must implement <tt>hasNext</tt> and <tt>next</tt>.)<p>
*
* To implement a modifiable collection, the programmer must additionally
* override this class's <tt>add</tt> method (which otherwise throws an
* <tt>UnsupportedOperationException</tt>), and the iterator returned by the
* <tt>iterator</tt> method must additionally implement its <tt>remove</tt>
* method.<p>
*
* The programmer should generally provide a void (no argument) and
* <tt>Collection</tt> constructor, as per the recommendation in the
* <tt>Collection</tt> 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}/../technotes/guides/collections/index.html">
* 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}
*
* <p>This implementation returns <tt>size() == 0</tt>.
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* {@inheritDoc}
*
* <p>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}
*
* <p>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}
*
* <p>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}
*
* <p>This implementation always throws an
* <tt>UnsupportedOperationException</tt>.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
* @throws IllegalStateException {@inheritDoc}
*/
public boolean add(E e) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* <p>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
* <tt>UnsupportedOperationException</tt> if the iterator returned by this
* collection's iterator method does not implement the <tt>remove</tt>
* 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}
*
* <p>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 <tt>true</tt> is returned, otherwise <tt>false</tt>.
*
* @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}
*
* <p>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
* <tt>UnsupportedOperationException</tt> unless <tt>add</tt> 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}
*
* <p>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 <tt>remove</tt> method.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the iterator returned by the
* <tt>iterator</tt> method does not implement the <tt>remove</tt> 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}
*
* <p>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 <tt>remove</tt> method.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the iterator returned by the
* <tt>iterator</tt> method does not implement the <tt>remove</tt> 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}
*
* <p>This implementation iterates over this collection, removing each
* element using the <tt>Iterator.remove</tt> operation. Most
* implementations will probably choose to override this method for
* efficiency.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the iterator returned by this
* collection's <tt>iterator</tt> method does not implement the
* <tt>remove</tt> 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
* (<tt>"[]"</tt>). Adjacent elements are separated by the characters
* <tt>", "</tt> (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,781 @@
/*
* Copyright (c) 1997, 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;
/**
* 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}/../technotes/guides/collections/index.html">
* 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.
*
* <p>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}
*/
abstract public E get(int index);
/**
* {@inheritDoc}
*
* <p>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}
*
* <p>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}
*
* <p>This implementation always throws an
* {@code UnsupportedOperationException}.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E remove(int index) {
throw new UnsupportedOperationException();
}
// Search Operations
/**
* {@inheritDoc}
*
* <p>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}
*
* <p>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.
*
* <p>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}
*
* <p>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.
*
* <p>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}
*
* <p>This implementation returns {@code listIterator(0)}.
*
* @see #listIterator(int)
*/
public ListIterator<E> listIterator() {
return listIterator(0);
}
/**
* {@inheritDoc}
*
* <p>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}
*
* <p>This implementation returns a list that subclasses
* {@code AbstractList}. The subclass stores, in private fields, the
* offset of the subList within the backing list, 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) {
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, 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.<p>
*
* 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.
*
* <p>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.
*
* <p>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();
}
}
class SubList<E> extends AbstractList<E> {
private final AbstractList<E> l;
private final int offset;
private int size;
SubList(AbstractList<E> list, int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > list.size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
this.modCount = l.modCount;
}
public E set(int index, E element) {
rangeCheck(index);
checkForComodification();
return l.set(index+offset, element);
}
public E get(int index) {
rangeCheck(index);
checkForComodification();
return l.get(index+offset);
}
public int size() {
checkForComodification();
return size;
}
public void add(int index, E element) {
rangeCheckForAdd(index);
checkForComodification();
l.add(index+offset, element);
this.modCount = l.modCount;
size++;
}
public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = l.remove(index+offset);
this.modCount = l.modCount;
size--;
return result;
}
protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
l.removeRange(fromIndex+offset, toIndex+offset);
this.modCount = l.modCount;
size -= (toIndex-fromIndex);
}
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();
l.addAll(offset+index, c);
this.modCount = l.modCount;
size += cSize;
return true;
}
public Iterator<E> iterator() {
return listIterator();
}
public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
return new ListIterator<E>() {
private final ListIterator<E> i = l.listIterator(index+offset);
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();
SubList.this.modCount = l.modCount;
size--;
}
public void set(E e) {
i.set(e);
}
public void add(E e) {
i.add(e);
SubList.this.modCount = l.modCount;
size++;
}
};
}
public List<E> subList(int fromIndex, int toIndex) {
return new SubList<>(this, fromIndex, toIndex);
}
private void rangeCheck(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
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 (this.modCount != l.modCount)
throw new ConcurrentModificationException();
}
}
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
super(list, fromIndex, toIndex);
}
public List<E> subList(int fromIndex, int toIndex) {
return new RandomAccessSubList<>(this, fromIndex, toIndex);
}
}

View File

@@ -0,0 +1,860 @@
/*
* 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 <tt>Map</tt>
* 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 <tt>entrySet</tt> method, which
* returns a set-view of the map's mappings. Typically, the returned set
* will, in turn, be implemented atop <tt>AbstractSet</tt>. This set should
* not support the <tt>add</tt> or <tt>remove</tt> methods, and its iterator
* should not support the <tt>remove</tt> method.
*
* <p>To implement a modifiable map, the programmer must additionally override
* this class's <tt>put</tt> method (which otherwise throws an
* <tt>UnsupportedOperationException</tt>), and the iterator returned by
* <tt>entrySet().iterator()</tt> must additionally implement its
* <tt>remove</tt> method.
*
* <p>The programmer should generally provide a void (no argument) and map
* constructor, as per the recommendation in the <tt>Map</tt> 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}/../technotes/guides/collections/index.html">
* 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 <tt>entrySet().size()</tt>.
*/
public int size() {
return entrySet().size();
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns <tt>size() == 0</tt>.
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over <tt>entrySet()</tt> searching
* for an entry with the specified value. If such an entry is found,
* <tt>true</tt> is returned. If the iteration terminates without
* finding such an entry, <tt>false</tt> 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 <tt>entrySet()</tt> searching
* for an entry with the specified key. If such an entry is found,
* <tt>true</tt> is returned. If the iteration terminates without
* finding such an entry, <tt>false</tt> 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 <tt>entrySet()</tt> 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, <tt>null</tt> 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
* <tt>UnsupportedOperationException</tt>.
*
* @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 <tt>entrySet()</tt> searching for an
* entry with the specified key. If such an entry is found, its value is
* obtained with its <tt>getValue</tt> operation, the entry is removed
* from the collection (and the backing map) with the iterator's
* <tt>remove</tt> operation, and the saved value is returned. If the
* iteration terminates without finding such an entry, <tt>null</tt> 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
* <tt>UnsupportedOperationException</tt> if the <tt>entrySet</tt>
* iterator does not support the <tt>remove</tt> 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
* <tt>entrySet()</tt> collection, and calls this map's <tt>put</tt>
* operation once for each entry returned by the iteration.
*
* <p>Note that this implementation throws an
* <tt>UnsupportedOperationException</tt> if this map does not support
* the <tt>put</tt> 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 <tt>entrySet().clear()</tt>.
*
* <p>Note that this implementation throws an
* <tt>UnsupportedOperationException</tt> if the <tt>entrySet</tt>
* does not support the <tt>clear</tt> 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 <tt>entrySet()</tt> iterator. The <tt>size</tt> method
* delegates to this map's <tt>size</tt> method and the
* <tt>contains</tt> method delegates to this map's
* <tt>containsKey</tt> 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 <tt>entrySet()</tt> iterator.
* The <tt>size</tt> method delegates to this map's <tt>size</tt>
* method and the <tt>contains</tt> method delegates to this map's
* <tt>containsValue</tt> 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
* <tt>true</tt> if the given object is also a map and the two maps
* represent the same mappings. More formally, two maps <tt>m1</tt> and
* <tt>m2</tt> represent the same mappings if
* <tt>m1.entrySet().equals(m2.entrySet())</tt>. This ensures that the
* <tt>equals</tt> method works properly across different implementations
* of the <tt>Map</tt> interface.
*
* @implSpec
* This implementation first checks if the specified object is this map;
* if so it returns <tt>true</tt>. Then, it checks if the specified
* object is a map whose size is identical to the size of this map; if
* not, it returns <tt>false</tt>. If so, it iterates over this map's
* <tt>entrySet</tt> collection, and checks that the specified map
* contains each mapping that this map contains. If the specified map
* fails to contain such a mapping, <tt>false</tt> is returned. If the
* iteration completes, <tt>true</tt> is returned.
*
* @param o object to be compared for equality with this map
* @return <tt>true</tt> 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 {
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext()) {
Entry<K,V> e = i.next();
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
* <tt>entrySet()</tt> view. This ensures that <tt>m1.equals(m2)</tt>
* implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two maps
* <tt>m1</tt> and <tt>m2</tt>, as required by the general contract of
* {@link Object#hashCode}.
*
* @implSpec
* This implementation iterates over <tt>entrySet()</tt>, 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;
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext())
h += i.next().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 <tt>entrySet</tt> view's iterator, enclosed in braces
* (<tt>"{}"</tt>). Adjacent mappings are separated by the characters
* <tt>", "</tt> (comma and space). Each key-value mapping is rendered as
* the key followed by an equals sign (<tt>"="</tt>) 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 <tt>AbstractMap</tt> 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 <tt>setValue</tt> method. This class
* facilitates the process of building custom map
* implementations. For example, it may be convenient to return
* arrays of <tt>SimpleEntry</tt> instances in method
* <tt>Map.entrySet().toArray</tt>.
*
* @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 ("<tt>=</tt>")
* 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 <tt>setValue</tt>. 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
* <tt>UnsupportedOperationException</tt>, 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 ("<tt>=</tt>")
* 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 <tt>null</tt>
* 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 <tt>false</tt> or
* <tt>null</tt> returns.
*
* <p>A <tt>Queue</tt> implementation that extends this class must
* minimally define a method {@link Queue#offer} which does not permit
* insertion of <tt>null</tt> 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}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @since 1.5
* @author Doug Lea
* @param <E> the type of elements held in this collection
*/
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
* <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
* if no space is currently available.
*
* <p>This implementation returns <tt>true</tt> if <tt>offer</tt> succeeds,
* else throws an <tt>IllegalStateException</tt>.
*
* @param e the element to add
* @return <tt>true</tt> (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 <tt>poll</tt>
* 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 <tt>peek</tt>
* 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 <tt>null</tt>.
*/
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
* <tt>IllegalArgumentException</tt>. 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
* <tt>null</tt> 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 <tt>true</tt> 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,253 @@
/*
* 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 <tt>List</tt>
* 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), <tt>AbstractList</tt> should be used
* in preference to this class.<p>
*
* This class is the opposite of the <tt>AbstractList</tt> class in the sense
* that it implements the "random access" methods (<tt>get(int index)</tt>,
* <tt>set(int index, E element)</tt>, <tt>add(int index, E element)</tt> and
* <tt>remove(int index)</tt>) 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 <tt>listIterator</tt> and <tt>size</tt>
* methods. For an unmodifiable list, the programmer need only implement the
* list iterator's <tt>hasNext</tt>, <tt>next</tt>, <tt>hasPrevious</tt>,
* <tt>previous</tt> and <tt>index</tt> methods.<p>
*
* For a modifiable list the programmer should additionally implement the list
* iterator's <tt>set</tt> method. For a variable-size list the programmer
* should additionally implement the list iterator's <tt>remove</tt> and
* <tt>add</tt> methods.<p>
*
* The programmer should generally provide a void (no argument) and collection
* constructor, as per the recommendation in the <tt>Collection</tt> interface
* specification.<p>
*
* This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* 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 <tt>listIterator(index)</tt>). Then, it gets
* the element using <tt>ListIterator.next</tt> 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 <tt>listIterator(index)</tt>). Then, it gets
* the current element using <tt>ListIterator.next</tt> and replaces it
* with <tt>ListIterator.set</tt>.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the list iterator does not
* implement the <tt>set</tt> 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 <tt>listIterator(index)</tt>). Then, it
* inserts the specified element with <tt>ListIterator.add</tt>.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the list iterator does not
* implement the <tt>add</tt> 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 <tt>listIterator(index)</tt>). Then, it removes
* the element with <tt>ListIterator.remove</tt>.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the list iterator does not
* implement the <tt>remove</tt> 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
* <tt>listIterator(index)</tt>). Then, it iterates over the specified
* collection, inserting the elements obtained from the iterator into this
* list, one at a time, using <tt>ListIterator.add</tt> followed by
* <tt>ListIterator.next</tt> (to skip over the added element).
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the list iterator returned by
* the <tt>listIterator</tt> method does not implement the <tt>add</tt>
* 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);
Iterator<? extends E> e2 = c.iterator();
while (e2.hasNext()) {
e1.add(e2.next());
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</code> 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 <tt>Set</tt>
* 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 <tt>Set</tt>
* 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 <tt>AbstractCollection</tt> class. It merely adds implementations
* for <tt>equals</tt> and <tt>hashCode</tt>.<p>
*
* This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* 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
* <tt>true</tt> 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 <tt>equals</tt> method works
* properly across different implementations of the <tt>Set</tt>
* interface.<p>
*
* This implementation first checks if the specified object is this
* set; if so it returns <tt>true</tt>. 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
* <tt>containsAll((Collection) o)</tt>.
*
* @param o object to be compared for equality with this set
* @return <tt>true</tt> 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 <tt>null</tt> element is defined to be zero.
* This ensures that <tt>s1.equals(s2)</tt> implies that
* <tt>s1.hashCode()==s2.hashCode()</tt> for any two sets <tt>s1</tt>
* and <tt>s2</tt>, as required by the general contract of
* {@link Object#hashCode}.
*
* <p>This implementation iterates over the set, calling the
* <tt>hashCode</tt> 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 <tt>size</tt>
* 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 <tt>remove</tt> 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 <tt>remove</tt> method.
*
* <p>Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the iterator returned by the
* <tt>iterator</tt> method does not implement the <tt>remove</tt> method.
*
* @param c collection containing elements to be removed from this set
* @return <tt>true</tt> if this set changed as a result of the call
* @throws UnsupportedOperationException if the <tt>removeAll</tt> 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 (Iterator<?> i = c.iterator(); i.hasNext(); )
modified |= remove(i.next());
} else {
for (Iterator<?> i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
}
return modified;
}
}

View File

@@ -0,0 +1,992 @@
/*
* 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 Josh Bloch of Google Inc. and released to the public domain,
* as explained at http://creativecommons.org/publicdomain/zero/1.0/.
*/
package java.util;
import java.io.Serializable;
import java.util.function.Consumer;
import sun.misc.SharedSecrets;
/**
* Resizable-array implementation of the {@link Deque} interface. Array
* deques have no capacity restrictions; they grow as necessary to support
* usage. They are not thread-safe; in the absence of external
* synchronization, they do not support concurrent access by multiple threads.
* Null elements are prohibited. This class is likely to be faster than
* {@link Stack} when used as a stack, and faster than {@link LinkedList}
* when used as a queue.
*
* <p>Most {@code ArrayDeque} operations run in amortized constant time.
* Exceptions include {@link #remove(Object) remove}, {@link
* #removeFirstOccurrence removeFirstOccurrence}, {@link #removeLastOccurrence
* removeLastOccurrence}, {@link #contains contains}, {@link #iterator
* iterator.remove()}, and the bulk operations, all of which run in linear
* time.
*
* <p>The iterators returned by this class's {@code iterator} method are
* <i>fail-fast</i>: If the deque 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 generally 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 and its iterator implement all of the
* <em>optional</em> methods of the {@link Collection} and {@link
* Iterator} interfaces.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @author Josh Bloch and Doug Lea
* @since 1.6
* @param <E> the type of elements held in this collection
*/
public class ArrayDeque<E> extends AbstractCollection<E>
implements Deque<E>, Cloneable, Serializable
{
/**
* The array in which the elements of the deque are stored.
* The capacity of the deque is the length of this array, which is
* always a power of two. The array is never allowed to become
* full, except transiently within an addX method where it is
* resized (see doubleCapacity) immediately upon becoming full,
* thus avoiding head and tail wrapping around to equal each
* other. We also guarantee that all array cells not holding
* deque elements are always null.
*/
transient Object[] elements; // non-private to simplify nested class access
/**
* The index of the element at the head of the deque (which is the
* element that would be removed by remove() or pop()); or an
* arbitrary number equal to tail if the deque is empty.
*/
transient int head;
/**
* The index at which the next element would be added to the tail
* of the deque (via addLast(E), add(E), or push(E)).
*/
transient int tail;
/**
* The minimum capacity that we'll use for a newly created deque.
* Must be a power of 2.
*/
private static final int MIN_INITIAL_CAPACITY = 8;
// ****** Array allocation and resizing utilities ******
private static int calculateSize(int numElements) {
int initialCapacity = MIN_INITIAL_CAPACITY;
// Find the best power of two to hold elements.
// Tests "<=" because arrays aren't kept full.
if (numElements >= initialCapacity) {
initialCapacity = numElements;
initialCapacity |= (initialCapacity >>> 1);
initialCapacity |= (initialCapacity >>> 2);
initialCapacity |= (initialCapacity >>> 4);
initialCapacity |= (initialCapacity >>> 8);
initialCapacity |= (initialCapacity >>> 16);
initialCapacity++;
if (initialCapacity < 0) // Too many elements, must back off
initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
}
return initialCapacity;
}
/**
* Allocates empty array to hold the given number of elements.
*
* @param numElements the number of elements to hold
*/
private void allocateElements(int numElements) {
elements = new Object[calculateSize(numElements)];
}
/**
* Doubles the capacity of this deque. Call only when full, i.e.,
* when head and tail have wrapped around to become equal.
*/
private void doubleCapacity() {
assert head == tail;
int p = head;
int n = elements.length;
int r = n - p; // number of elements to the right of p
int newCapacity = n << 1;
if (newCapacity < 0)
throw new IllegalStateException("Sorry, deque too big");
Object[] a = new Object[newCapacity];
System.arraycopy(elements, p, a, 0, r);
System.arraycopy(elements, 0, a, r, p);
elements = a;
head = 0;
tail = n;
}
/**
* Copies the elements from our element array into the specified array,
* in order (from first to last element in the deque). It is assumed
* that the array is large enough to hold all elements in the deque.
*
* @return its argument
*/
private <T> T[] copyElements(T[] a) {
if (head < tail) {
System.arraycopy(elements, head, a, 0, size());
} else if (head > tail) {
int headPortionLen = elements.length - head;
System.arraycopy(elements, head, a, 0, headPortionLen);
System.arraycopy(elements, 0, a, headPortionLen, tail);
}
return a;
}
/**
* Constructs an empty array deque with an initial capacity
* sufficient to hold 16 elements.
*/
public ArrayDeque() {
elements = new Object[16];
}
/**
* Constructs an empty array deque with an initial capacity
* sufficient to hold the specified number of elements.
*
* @param numElements lower bound on initial capacity of the deque
*/
public ArrayDeque(int numElements) {
allocateElements(numElements);
}
/**
* Constructs a deque containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator. (The first element returned by the collection's
* iterator becomes the first element, or <i>front</i> of the
* deque.)
*
* @param c the collection whose elements are to be placed into the deque
* @throws NullPointerException if the specified collection is null
*/
public ArrayDeque(Collection<? extends E> c) {
allocateElements(c.size());
addAll(c);
}
// The main insertion and extraction methods are addFirst,
// addLast, pollFirst, pollLast. The other methods are defined in
// terms of these.
/**
* Inserts the specified element at the front of this deque.
*
* @param e the element to add
* @throws NullPointerException if the specified element is null
*/
public void addFirst(E e) {
if (e == null)
throw new NullPointerException();
elements[head = (head - 1) & (elements.length - 1)] = e;
if (head == tail)
doubleCapacity();
}
/**
* Inserts the specified element at the end of this deque.
*
* <p>This method is equivalent to {@link #add}.
*
* @param e the element to add
* @throws NullPointerException if the specified element is null
*/
public void addLast(E e) {
if (e == null)
throw new NullPointerException();
elements[tail] = e;
if ( (tail = (tail + 1) & (elements.length - 1)) == head)
doubleCapacity();
}
/**
* Inserts the specified element at the front of this deque.
*
* @param e the element to add
* @return {@code true} (as specified by {@link Deque#offerFirst})
* @throws NullPointerException if the specified element is null
*/
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
/**
* Inserts the specified element at the end of this deque.
*
* @param e the element to add
* @return {@code true} (as specified by {@link Deque#offerLast})
* @throws NullPointerException if the specified element is null
*/
public boolean offerLast(E e) {
addLast(e);
return true;
}
/**
* @throws NoSuchElementException {@inheritDoc}
*/
public E removeFirst() {
E x = pollFirst();
if (x == null)
throw new NoSuchElementException();
return x;
}
/**
* @throws NoSuchElementException {@inheritDoc}
*/
public E removeLast() {
E x = pollLast();
if (x == null)
throw new NoSuchElementException();
return x;
}
public E pollFirst() {
int h = head;
@SuppressWarnings("unchecked")
E result = (E) elements[h];
// Element is null if deque empty
if (result == null)
return null;
elements[h] = null; // Must null out slot
head = (h + 1) & (elements.length - 1);
return result;
}
public E pollLast() {
int t = (tail - 1) & (elements.length - 1);
@SuppressWarnings("unchecked")
E result = (E) elements[t];
if (result == null)
return null;
elements[t] = null;
tail = t;
return result;
}
/**
* @throws NoSuchElementException {@inheritDoc}
*/
public E getFirst() {
@SuppressWarnings("unchecked")
E result = (E) elements[head];
if (result == null)
throw new NoSuchElementException();
return result;
}
/**
* @throws NoSuchElementException {@inheritDoc}
*/
public E getLast() {
@SuppressWarnings("unchecked")
E result = (E) elements[(tail - 1) & (elements.length - 1)];
if (result == null)
throw new NoSuchElementException();
return result;
}
@SuppressWarnings("unchecked")
public E peekFirst() {
// elements[head] is null if deque empty
return (E) elements[head];
}
@SuppressWarnings("unchecked")
public E peekLast() {
return (E) elements[(tail - 1) & (elements.length - 1)];
}
/**
* Removes the first occurrence of the specified element in this
* deque (when traversing the deque from head to tail).
* If the deque does not contain the element, it is unchanged.
* More formally, removes the first element {@code e} such that
* {@code o.equals(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 the deque contained the specified element
*/
public boolean removeFirstOccurrence(Object o) {
if (o == null)
return false;
int mask = elements.length - 1;
int i = head;
Object x;
while ( (x = elements[i]) != null) {
if (o.equals(x)) {
delete(i);
return true;
}
i = (i + 1) & mask;
}
return false;
}
/**
* Removes the last occurrence of the specified element in this
* deque (when traversing the deque from head to tail).
* If the deque does not contain the element, it is unchanged.
* More formally, removes the last element {@code e} such that
* {@code o.equals(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 the deque contained the specified element
*/
public boolean removeLastOccurrence(Object o) {
if (o == null)
return false;
int mask = elements.length - 1;
int i = (tail - 1) & mask;
Object x;
while ( (x = elements[i]) != null) {
if (o.equals(x)) {
delete(i);
return true;
}
i = (i - 1) & mask;
}
return false;
}
// *** Queue methods ***
/**
* Inserts the specified element at the end of this deque.
*
* <p>This method is equivalent to {@link #addLast}.
*
* @param e the element to add
* @return {@code true} (as specified by {@link Collection#add})
* @throws NullPointerException if the specified element is null
*/
public boolean add(E e) {
addLast(e);
return true;
}
/**
* Inserts the specified element at the end of this deque.
*
* <p>This method is equivalent to {@link #offerLast}.
*
* @param e the element to add
* @return {@code true} (as specified by {@link Queue#offer})
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
return offerLast(e);
}
/**
* Retrieves and removes the head of the queue represented by 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 {@inheritDoc}
*/
public E remove() {
return removeFirst();
}
/**
* 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 head of the queue represented by this deque, or
* {@code null} if this deque is empty
*/
public E poll() {
return pollFirst();
}
/**
* Retrieves, but does not remove, the head of the queue represented by
* 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 {@inheritDoc}
*/
public E element() {
return getFirst();
}
/**
* Retrieves, but does not remove, the head of the queue represented by
* 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
*/
public E peek() {
return peekFirst();
}
// *** Stack methods ***
/**
* Pushes an element onto the stack represented by this deque. In other
* words, inserts the element at the front of this deque.
*
* <p>This method is equivalent to {@link #addFirst}.
*
* @param e the element to push
* @throws NullPointerException if the specified element is null
*/
public void push(E e) {
addFirst(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 {@inheritDoc}
*/
public E pop() {
return removeFirst();
}
private void checkInvariants() {
assert elements[tail] == null;
assert head == tail ? elements[head] == null :
(elements[head] != null &&
elements[(tail - 1) & (elements.length - 1)] != null);
assert elements[(head - 1) & (elements.length - 1)] == null;
}
/**
* Removes the element at the specified position in the elements array,
* adjusting head and tail as necessary. This can result in motion of
* elements backwards or forwards in the array.
*
* <p>This method is called delete rather than remove to emphasize
* that its semantics differ from those of {@link List#remove(int)}.
*
* @return true if elements moved backwards
*/
private boolean delete(int i) {
checkInvariants();
final Object[] elements = this.elements;
final int mask = elements.length - 1;
final int h = head;
final int t = tail;
final int front = (i - h) & mask;
final int back = (t - i) & mask;
// Invariant: head <= i < tail mod circularity
if (front >= ((t - h) & mask))
throw new ConcurrentModificationException();
// Optimize for least element motion
if (front < back) {
if (h <= i) {
System.arraycopy(elements, h, elements, h + 1, front);
} else { // Wrap around
System.arraycopy(elements, 0, elements, 1, i);
elements[0] = elements[mask];
System.arraycopy(elements, h, elements, h + 1, mask - h);
}
elements[h] = null;
head = (h + 1) & mask;
return false;
} else {
if (i < t) { // Copy the null tail as well
System.arraycopy(elements, i + 1, elements, i, back);
tail = t - 1;
} else { // Wrap around
System.arraycopy(elements, i + 1, elements, i, mask - i);
elements[mask] = elements[0];
System.arraycopy(elements, 1, elements, 0, t);
tail = (t - 1) & mask;
}
return true;
}
}
// *** Collection Methods ***
/**
* Returns the number of elements in this deque.
*
* @return the number of elements in this deque
*/
public int size() {
return (tail - head) & (elements.length - 1);
}
/**
* Returns {@code true} if this deque contains no elements.
*
* @return {@code true} if this deque contains no elements
*/
public boolean isEmpty() {
return head == tail;
}
/**
* Returns an iterator over the elements in this deque. The elements
* will be ordered from first (head) to last (tail). This is the same
* order that elements would be dequeued (via successive calls to
* {@link #remove} or popped (via successive calls to {@link #pop}).
*
* @return an iterator over the elements in this deque
*/
public Iterator<E> iterator() {
return new DeqIterator();
}
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
private class DeqIterator implements Iterator<E> {
/**
* Index of element to be returned by subsequent call to next.
*/
private int cursor = head;
/**
* Tail recorded at construction (also in remove), to stop
* iterator and also to check for comodification.
*/
private int fence = tail;
/**
* Index of element returned by most recent call to next.
* Reset to -1 if element is deleted by a call to remove.
*/
private int lastRet = -1;
public boolean hasNext() {
return cursor != fence;
}
public E next() {
if (cursor == fence)
throw new NoSuchElementException();
@SuppressWarnings("unchecked")
E result = (E) elements[cursor];
// This check doesn't catch all possible comodifications,
// but does catch the ones that corrupt traversal
if (tail != fence || result == null)
throw new ConcurrentModificationException();
lastRet = cursor;
cursor = (cursor + 1) & (elements.length - 1);
return result;
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
if (delete(lastRet)) { // if left-shifted, undo increment in next()
cursor = (cursor - 1) & (elements.length - 1);
fence = tail;
}
lastRet = -1;
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
Object[] a = elements;
int m = a.length - 1, f = fence, i = cursor;
cursor = f;
while (i != f) {
@SuppressWarnings("unchecked") E e = (E)a[i];
i = (i + 1) & m;
if (e == null)
throw new ConcurrentModificationException();
action.accept(e);
}
}
}
private class DescendingIterator implements Iterator<E> {
/*
* This class is nearly a mirror-image of DeqIterator, using
* tail instead of head for initial cursor, and head instead of
* tail for fence.
*/
private int cursor = tail;
private int fence = head;
private int lastRet = -1;
public boolean hasNext() {
return cursor != fence;
}
public E next() {
if (cursor == fence)
throw new NoSuchElementException();
cursor = (cursor - 1) & (elements.length - 1);
@SuppressWarnings("unchecked")
E result = (E) elements[cursor];
if (head != fence || result == null)
throw new ConcurrentModificationException();
lastRet = cursor;
return result;
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
if (!delete(lastRet)) {
cursor = (cursor + 1) & (elements.length - 1);
fence = head;
}
lastRet = -1;
}
}
/**
* 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 o.equals(e)}.
*
* @param o object to be checked for containment in this deque
* @return {@code true} if this deque contains the specified element
*/
public boolean contains(Object o) {
if (o == null)
return false;
int mask = elements.length - 1;
int i = head;
Object x;
while ( (x = elements[i]) != null) {
if (o.equals(x))
return true;
i = (i + 1) & mask;
}
return false;
}
/**
* Removes a single instance 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 o.equals(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 this deque contained the specified element
*/
public boolean remove(Object o) {
return removeFirstOccurrence(o);
}
/**
* Removes all of the elements from this deque.
* The deque will be empty after this call returns.
*/
public void clear() {
int h = head;
int t = tail;
if (h != t) { // clear all cells
head = tail = 0;
int i = h;
int mask = elements.length - 1;
do {
elements[i] = null;
i = (i + 1) & mask;
} while (i != t);
}
}
/**
* Returns an array containing all of the elements in this deque
* in proper sequence (from first to last element).
*
* <p>The returned array will be "safe" in that no references to it are
* maintained by this deque. (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 deque
*/
public Object[] toArray() {
return copyElements(new Object[size()]);
}
/**
* Returns an array containing all of the elements in this deque in
* proper sequence (from first to last element); the runtime type of the
* returned array is that of the specified array. If the deque 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 deque.
*
* <p>If this deque fits in the specified array with room to spare
* (i.e., the array has more elements than this deque), the element in
* the array immediately following the end of the deque 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 deque known to contain only strings.
* The following code can be used to dump the deque 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 deque 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 deque
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this deque
* @throws NullPointerException if the specified array is null
*/
@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);
copyElements(a);
if (a.length > size)
a[size] = null;
return a;
}
// *** Object methods ***
/**
* Returns a copy of this deque.
*
* @return a copy of this deque
*/
public ArrayDeque<E> clone() {
try {
@SuppressWarnings("unchecked")
ArrayDeque<E> result = (ArrayDeque<E>) super.clone();
result.elements = Arrays.copyOf(elements, elements.length);
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
private static final long serialVersionUID = 2340985798034038923L;
/**
* Saves this deque to a stream (that is, serializes it).
*
* @serialData The current size ({@code int}) of the deque,
* followed by all of its elements (each an object reference) in
* first-to-last order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
s.defaultWriteObject();
// Write out size
s.writeInt(size());
// Write out elements in order.
int mask = elements.length - 1;
for (int i = head; i != tail; i = (i + 1) & mask)
s.writeObject(elements[i]);
}
/**
* Reconstitutes this deque from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
// Read in size and allocate array
int size = s.readInt();
int capacity = calculateSize(size);
SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
allocateElements(size);
head = 0;
tail = size;
// Read in all elements in the proper order.
for (int i = 0; i < size; i++)
elements[i] = s.readObject();
}
/**
* Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
* and <em>fail-fast</em> {@link Spliterator} over the elements in this
* deque.
*
* <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
* {@link Spliterator#NONNULL}. Overriding implementations should document
* the reporting of additional characteristic values.
*
* @return a {@code Spliterator} over the elements in this deque
* @since 1.8
*/
public Spliterator<E> spliterator() {
return new DeqSpliterator<E>(this, -1, -1);
}
static final class DeqSpliterator<E> implements Spliterator<E> {
private final ArrayDeque<E> deq;
private int fence; // -1 until first use
private int index; // current index, modified on traverse/split
/** Creates new spliterator covering the given array and range */
DeqSpliterator(ArrayDeque<E> deq, int origin, int fence) {
this.deq = deq;
this.index = origin;
this.fence = fence;
}
private int getFence() { // force initialization
int t;
if ((t = fence) < 0) {
t = fence = deq.tail;
index = deq.head;
}
return t;
}
public DeqSpliterator<E> trySplit() {
int t = getFence(), h = index, n = deq.elements.length;
if (h != t && ((h + 1) & (n - 1)) != t) {
if (h > t)
t += n;
int m = ((h + t) >>> 1) & (n - 1);
return new DeqSpliterator<>(deq, h, index = m);
}
return null;
}
public void forEachRemaining(Consumer<? super E> consumer) {
if (consumer == null)
throw new NullPointerException();
Object[] a = deq.elements;
int m = a.length - 1, f = getFence(), i = index;
index = f;
while (i != f) {
@SuppressWarnings("unchecked") E e = (E)a[i];
i = (i + 1) & m;
if (e == null)
throw new ConcurrentModificationException();
consumer.accept(e);
}
}
public boolean tryAdvance(Consumer<? super E> consumer) {
if (consumer == null)
throw new NullPointerException();
Object[] a = deq.elements;
int m = a.length - 1, f = getFence(), i = index;
if (i != fence) {
@SuppressWarnings("unchecked") E e = (E)a[i];
index = (i + 1) & m;
if (e == null)
throw new ConcurrentModificationException();
consumer.accept(e);
return true;
}
return false;
}
public long estimateSize() {
int n = getFence() - index;
if (n < 0)
n += deq.elements.length;
return (long) n;
}
@Override
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED |
Spliterator.NONNULL | Spliterator.SUBSIZED;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,696 @@
/*
* 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;
/*
* 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/
*/
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.CountedCompleter;
import java.util.function.BinaryOperator;
import java.util.function.IntBinaryOperator;
import java.util.function.LongBinaryOperator;
import java.util.function.DoubleBinaryOperator;
/**
* 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 soley 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;
}
@SuppressWarnings("unchecked")
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
if ((par = (CumulateTask<T>)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; 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
}
}
}
}
}
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
}
}
}
}
}
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
}
}
}
}
}
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
}
}
}
}
}
}

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,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 name="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 name="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 name="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 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++]] < 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, 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.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 <tt>Set</tt> and <tt>List</tt>. 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 <tt>Collection</tt> implementation classes (which
* typically implement <tt>Collection</tt> 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 <tt>Collection</tt>, 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 <tt>Collection</tt>
* 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 <tt>UnsupportedOperationException</tt> if this collection does not
* support the operation. If this is the case, these methods may, but are not
* required to, throw an <tt>UnsupportedOperationException</tt> 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 name="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
* <tt>NullPointerException</tt> or <tt>ClassCastException</tt>. 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 <tt>true</tt> if and only if this collection
* contains at least one element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>." This specification should
* <i>not</i> be construed to imply that invoking <tt>Collection.contains</tt>
* with a non-null argument <tt>o</tt> will cause <tt>o.equals(e)</tt> to be
* invoked for any element <tt>e</tt>. Implementations are free to implement
* optimizations whereby the <tt>equals</tt> 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}/../technotes/guides/collections/index.html">
* 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 <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
*
* @return the number of elements in this collection
*/
int size();
/**
* Returns <tt>true</tt> if this collection contains no elements.
*
* @return <tt>true</tt> if this collection contains no elements
*/
boolean isEmpty();
/**
* Returns <tt>true</tt> if this collection contains the specified element.
* More formally, returns <tt>true</tt> if and only if this collection
* contains at least one element <tt>e</tt> such that
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
*
* @param o element whose presence in this collection is to be tested
* @return <tt>true</tt> if this collection contains the specified
* element
* @throws ClassCastException if the type of the specified element
* is incompatible with this collection
* (<a href="#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* collection does not permit null elements
* (<a href="#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 <tt>Iterator</tt> 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
* <tt>null</tt>. (This is useful in determining the length of this
* collection <i>only</i> if the caller knows that this collection does
* not contain any <tt>null</tt> 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 <tt>x</tt> is a collection known to contain only strings.
* The following code can be used to dump the collection into a newly
* allocated array of <tt>String</tt>:
*
* <pre>
* String[] y = x.toArray(new String[0]);</pre>
*
* Note that <tt>toArray(new Object[0])</tt> is identical in function to
* <tt>toArray()</tt>.
*
* @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 <tt>true</tt> if this collection changed as a
* result of the call. (Returns <tt>false</tt> 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 <tt>null</tt> 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 <tt>false</tt>). 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 <tt>true</tt> if this collection changed as a result of the
* call
* @throws UnsupportedOperationException if the <tt>add</tt> 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 <tt>e</tt> such that
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>, if
* this collection contains one or more such elements. Returns
* <tt>true</tt> 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 <tt>true</tt> 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="#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* collection does not permit null elements
* (<a href="#optional-restrictions">optional</a>)
* @throws UnsupportedOperationException if the <tt>remove</tt> operation
* is not supported by this collection
*/
boolean remove(Object o);
// Bulk Operations
/**
* Returns <tt>true</tt> if this collection contains all of the elements
* in the specified collection.
*
* @param c collection to be checked for containment in this collection
* @return <tt>true</tt> 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="#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="#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 <tt>true</tt> if this collection changed as a result of the call
* @throws UnsupportedOperationException if the <tt>addAll</tt> 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 <tt>true</tt> if this collection changed as a result of the
* call
* @throws UnsupportedOperationException if the <tt>removeAll</tt> 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="#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="#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 <tt>true</tt> if this collection changed as a result of the call
* @throws UnsupportedOperationException if the <tt>retainAll</tt> 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="#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="#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 <tt>clear</tt> operation
* is not supported by this collection
*/
void clear();
// Comparison and hashing
/**
* Compares the specified object with this collection for equality. <p>
*
* While the <tt>Collection</tt> interface adds no stipulations to the
* general contract for the <tt>Object.equals</tt>, programmers who
* implement the <tt>Collection</tt> interface "directly" (in other words,
* create a class that is a <tt>Collection</tt> but is not a <tt>Set</tt>
* or a <tt>List</tt>) must exercise care if they choose to override the
* <tt>Object.equals</tt>. It is not necessary to do so, and the simplest
* course of action is to rely on <tt>Object</tt>'s implementation, but
* the implementor may wish to implement a "value comparison" in place of
* the default "reference comparison." (The <tt>List</tt> and
* <tt>Set</tt> interfaces mandate such value comparisons.)<p>
*
* The general contract for the <tt>Object.equals</tt> method states that
* equals must be symmetric (in other words, <tt>a.equals(b)</tt> if and
* only if <tt>b.equals(a)</tt>). The contracts for <tt>List.equals</tt>
* and <tt>Set.equals</tt> state that lists are only equal to other lists,
* and sets to other sets. Thus, a custom <tt>equals</tt> method for a
* collection class that implements neither the <tt>List</tt> nor
* <tt>Set</tt> interface must return <tt>false</tt> 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 <tt>Set</tt> and
* <tt>List</tt> interfaces.)
*
* @param o object to be compared for equality with this collection
* @return <tt>true</tt> 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
* <tt>Collection</tt> interface adds no stipulations to the general
* contract for the <tt>Object.hashCode</tt> method, programmers should
* take note that any class that overrides the <tt>Object.equals</tt>
* method must also override the <tt>Object.hashCode</tt> method in order
* to satisfy the general contract for the <tt>Object.hashCode</tt> method.
* In particular, <tt>c1.equals(c2)</tt> implies that
* <tt>c1.hashCode()==c2.hashCode()</tt>.
*
* @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 collections'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, 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 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 <tt>c</tt> on a set of elements
* <tt>S</tt> is said to be <i>consistent with equals</i> if and only if
* <tt>c.compare(e1, e2)==0</tt> has the same boolean value as
* <tt>e1.equals(e2)</tt> for every <tt>e1</tt> and <tt>e2</tt> in
* <tt>S</tt>.<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 <tt>c</tt>
* is used with elements (or keys) drawn from a set <tt>S</tt>. If the
* ordering imposed by <tt>c</tt> on <tt>S</tt> 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 <tt>equals</tt>.<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
* <tt>java.io.Serializable</tt>, 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 <tt>Serializable</tt>.<p>
*
* For the mathematically inclined, the <i>relation</i> that defines the
* <i>imposed ordering</i> that a given comparator <tt>c</tt> imposes on a
* given set of objects <tt>S</tt> 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 <tt>compare</tt> that the
* quotient is an <i>equivalence relation</i> on <tt>S</tt>, and that the
* imposed ordering is a <i>total order</i> on <tt>S</tt>. When we say that
* the ordering imposed by <tt>c</tt> on <tt>S</tt> 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}/../technotes/guides/collections/index.html">
* 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>
*
* In the foregoing description, the notation
* <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
* <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
* <tt>0</tt>, or <tt>1</tt> according to whether the value of
* <i>expression</i> is negative, zero or positive.<p>
*
* The implementor must ensure that <tt>sgn(compare(x, y)) ==
* -sgn(compare(y, x))</tt> for all <tt>x</tt> and <tt>y</tt>. (This
* implies that <tt>compare(x, y)</tt> must throw an exception if and only
* if <tt>compare(y, x)</tt> throws an exception.)<p>
*
* The implementor must also ensure that the relation is transitive:
* <tt>((compare(x, y)&gt;0) &amp;&amp; (compare(y, z)&gt;0))</tt> implies
* <tt>compare(x, z)&gt;0</tt>.<p>
*
* Finally, the implementor must ensure that <tt>compare(x, y)==0</tt>
* implies that <tt>sgn(compare(x, z))==sgn(compare(y, z))</tt> for all
* <tt>z</tt>.<p>
*
* It is generally the case, but <i>not</i> strictly required that
* <tt>(compare(x, y)==0) == (x.equals(y))</tt>. 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."
*
* @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
* <tt>true</tt> <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)</code> implies that <tt>sgn(comp1.compare(o1,
* o2))==sgn(comp2.compare(o1, o2))</tt> for every object reference
* <tt>o1</tt> and <tt>o2</tt>.<p>
*
* Note that it is <i>always</i> safe <i>not</i> to override
* <tt>Object.equals(Object)</tt>. 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</code> 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 a {@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
*/
final static 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,783 @@
/*
* Copyright (c) 2000, 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.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
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.
*
* @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.
*/
transient private final int defaultFractionDigits;
/**
* ISO 4217 numeric code for this currency.
* Set from currency data tables.
*/
transient private final 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 sc* arrays + 1
// - scCutOverTimes: 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
// - scOldCurrencies: old currencies for special case countries
// - scNewCurrencies: new currencies for special case countries that are
// changing currencies; null for others
// - scOldCurrenciesDFD: default fraction digits for old currencies
// - scNewCurrenciesDFD: default fraction digits for new currencies, 0 for
// countries that are not changing currencies
// - otherCurrencies: concatenation of all currency codes that are not the
// main currency of a simple country, separated by "-"
// - otherCurrenciesDFD: decimal format digits for currencies in otherCurrencies, same order
static int formatVersion;
static int dataVersion;
static int[] mainTable;
static long[] scCutOverTimes;
static String[] scOldCurrencies;
static String[] scNewCurrencies;
static int[] scOldCurrenciesDFD;
static int[] scNewCurrenciesDFD;
static int[] scOldCurrenciesNumericCode;
static int[] scNewCurrenciesNumericCode;
static String otherCurrencies;
static int[] otherCurrenciesDFD;
static int[] otherCurrenciesNumericCode;
// 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 = 2;
static {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
String homeDir = System.getProperty("java.home");
try {
String dataFile = homeDir + File.separator +
"lib" + File.separator + "currency.data";
try (DataInputStream dis = new DataInputStream(
new BufferedInputStream(
new FileInputStream(dataFile)))) {
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();
scCutOverTimes = readLongArray(dis, scCount);
scOldCurrencies = readStringArray(dis, scCount);
scNewCurrencies = readStringArray(dis, scCount);
scOldCurrenciesDFD = readIntArray(dis, scCount);
scNewCurrenciesDFD = readIntArray(dis, scCount);
scOldCurrenciesNumericCode = readIntArray(dis, scCount);
scNewCurrenciesNumericCode = readIntArray(dis, scCount);
int ocCount = dis.readInt();
otherCurrencies = dis.readUTF();
otherCurrenciesDFD = readIntArray(dis, ocCount);
otherCurrenciesNumericCode = readIntArray(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 = homeDir + 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.
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;
} else {
// Check for '-' separately so we don't get false hits in the table.
if (currencyCode.charAt(2) == '-') {
throw new IllegalArgumentException();
}
int index = otherCurrencies.indexOf(currencyCode);
if (index == -1) {
throw new IllegalArgumentException();
}
defaultFractionDigits = otherCurrenciesDFD[index / 4];
numericCode = otherCurrenciesNumericCode[index / 4];
}
}
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> or its country
* 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 = (tableEntry & SPECIAL_CASE_COUNTRY_INDEX_MASK) - SPECIAL_CASE_COUNTRY_INDEX_DELTA;
if (scCutOverTimes[index] == Long.MAX_VALUE || System.currentTimeMillis() < scCutOverTimes[index]) {
return getInstance(scOldCurrencies[index], scOldCurrenciesDFD[index],
scOldCurrenciesNumericCode[index]);
} else {
return getInstance(scNewCurrencies[index], scNewCurrenciesDFD[index],
scNewCurrenciesNumericCode[index]);
}
}
}
}
/**
* 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));
}
}
}
// Now add other currencies
StringTokenizer st = new StringTokenizer(otherCurrencies, "-");
while (st.hasMoreElements()) {
available.add(getInstance((String)st.nextElement()));
}
}
}
@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.
* 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;
}
/**
* 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 long[] readLongArray(DataInputStream dis, int count) throws IOException {
long[] ret = new long[count];
for (int i = 0; i < count; i++) {
ret[i] = dis.readLong();
}
return ret;
}
private static String[] readStringArray(DataInputStream dis, int count) throws IOException {
String[] ret = new String[count];
for (int i = 0; i < count; i++) {
ret[i] = dis.readUTF();
}
return ret;
}
/**
* 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;
for (index = 0; index < scOldCurrencies.length; index++) {
if (scOldCurrencies[index].equals(code)) {
break;
}
}
if (index == scOldCurrencies.length) {
// 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);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,584 @@
/*
* 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 BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Summary of Deque methods</caption>
* <tr>
* <td></td>
* <td ALIGN=CENTER COLSPAN = 2> <b>First Element (Head)</b></td>
* <td ALIGN=CENTER COLSPAN = 2> <b>Last Element (Tail)</b></td>
* </tr>
* <tr>
* <td></td>
* <td ALIGN=CENTER><em>Throws exception</em></td>
* <td ALIGN=CENTER><em>Special value</em></td>
* <td ALIGN=CENTER><em>Throws exception</em></td>
* <td ALIGN=CENTER><em>Special value</em></td>
* </tr>
* <tr>
* <td><b>Insert</b></td>
* <td>{@link Deque#addFirst addFirst(e)}</td>
* <td>{@link Deque#offerFirst offerFirst(e)}</td>
* <td>{@link Deque#addLast addLast(e)}</td>
* <td>{@link Deque#offerLast offerLast(e)}</td>
* </tr>
* <tr>
* <td><b>Remove</b></td>
* <td>{@link Deque#removeFirst removeFirst()}</td>
* <td>{@link Deque#pollFirst pollFirst()}</td>
* <td>{@link Deque#removeLast removeLast()}</td>
* <td>{@link Deque#pollLast pollLast()}</td>
* </tr>
* <tr>
* <td><b>Examine</b></td>
* <td>{@link Deque#getFirst getFirst()}</td>
* <td>{@link Deque#peekFirst peekFirst()}</td>
* <td>{@link Deque#getLast getLast()}</td>
* <td>{@link Deque#peekLast peekLast()}</td>
* </tr>
* </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 BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Comparison of Queue and Deque methods</caption>
* <tr>
* <td ALIGN=CENTER> <b>{@code Queue} Method</b></td>
* <td ALIGN=CENTER> <b>Equivalent {@code Deque} Method</b></td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#add add(e)}</td>
* <td>{@link #addLast addLast(e)}</td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#offer offer(e)}</td>
* <td>{@link #offerLast offerLast(e)}</td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#remove remove()}</td>
* <td>{@link #removeFirst removeFirst()}</td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#poll poll()}</td>
* <td>{@link #pollFirst pollFirst()}</td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#element element()}</td>
* <td>{@link #getFirst getFirst()}</td>
* </tr>
* <tr>
* <td>{@link java.util.Queue#peek peek()}</td>
* <td>{@link #peek peekFirst()}</td>
* </tr>
* </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 BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Comparison of Stack and Deque methods</caption>
* <tr>
* <td ALIGN=CENTER> <b>Stack Method</b></td>
* <td ALIGN=CENTER> <b>Equivalent {@code Deque} Method</b></td>
* </tr>
* <tr>
* <td>{@link #push push(e)}</td>
* <td>{@link #addFirst addFirst(e)}</td>
* </tr>
* <tr>
* <td>{@link #pop pop()}</td>
* <td>{@link #removeFirst removeFirst()}</td>
* </tr>
* <tr>
* <td>{@link #peek peek()}</td>
* <td>{@link #peekFirst peekFirst()}</td>
* </tr>
* </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 indicated 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}/../technotes/guides/collections/index.html"> Java Collections
* Framework</a>.
*
* @author Doug Lea
* @author Josh Bloch
* @since 1.6
* @param <E> the type of elements held in this collection
*/
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
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
* (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="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* (<a href="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
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
* (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="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* (<a href="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();
// *** 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
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
* (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="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* (<a href="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
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
*
* @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 type of the specified element
* is incompatible with this deque
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* (<a href="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
*/
public 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</code> class is the abstract parent of any
* class, such as <code>Hashtable</code>, which maps keys to values.
* Every key and every value is an object. In any one <tt>Dictionary</tt>
* object, every key is associated with at most one value. Given a
* <tt>Dictionary</tt> and a key, the associated element can be looked up.
* Any non-<code>null</code> object can be used as a key and as a value.
* <p>
* As a rule, the <code>equals</code> 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 JDK1.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.
*/
abstract public int size();
/**
* Tests if this dictionary maps no keys to value. The general contract
* for the <tt>isEmpty</tt> method is that the result is true if and only
* if this dictionary contains no entries.
*
* @return <code>true</code> if this dictionary maps no keys to values;
* <code>false</code> otherwise.
*/
abstract public boolean isEmpty();
/**
* Returns an enumeration of the keys in this dictionary. The general
* contract for the keys method is that an <tt>Enumeration</tt> 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
*/
abstract public Enumeration<K> keys();
/**
* Returns an enumeration of the values in this dictionary. The general
* contract for the <tt>elements</tt> method is that an
* <tt>Enumeration</tt> 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
*/
abstract public Enumeration<V> elements();
/**
* Returns the value to which the key is mapped in this dictionary.
* The general contract for the <tt>isEmpty</tt> method is that if this
* dictionary contains an entry for the specified key, the associated
* value is returned; otherwise, <tt>null</tt> is returned.
*
* @return the value to which the key is mapped in this dictionary;
* @param key a key in this dictionary.
* <code>null</code> if the key is not mapped to any value in
* this dictionary.
* @exception NullPointerException if the <tt>key</tt> is <tt>null</tt>.
* @see java.util.Dictionary#put(java.lang.Object, java.lang.Object)
*/
abstract public V get(Object key);
/**
* Maps the specified <code>key</code> to the specified
* <code>value</code> in this dictionary. Neither the key nor the
* value can be <code>null</code>.
* <p>
* If this dictionary already contains an entry for the specified
* <tt>key</tt>, the value already in this dictionary for that
* <tt>key</tt> is returned, after modifying the entry to contain the
* new element. <p>If this dictionary does not already have an entry
* for the specified <tt>key</tt>, an entry is created for the
* specified <tt>key</tt> and <tt>value</tt>, and <tt>null</tt> is
* returned.
* <p>
* The <code>value</code> can be retrieved by calling the
* <code>get</code> method with a <code>key</code> that is equal to
* the original <code>key</code>.
*
* @param key the hashtable key.
* @param value the value.
* @return the previous value to which the <code>key</code> was mapped
* in this dictionary, or <code>null</code> if the key did not
* have a previous mapping.
* @exception NullPointerException if the <code>key</code> or
* <code>value</code> is <code>null</code>.
* @see java.lang.Object#equals(java.lang.Object)
* @see java.util.Dictionary#get(java.lang.Object)
*/
abstract public V put(K key, V value);
/**
* Removes the <code>key</code> (and its corresponding
* <code>value</code>) from this dictionary. This method does nothing
* if the <code>key</code> is not in this dictionary.
*
* @param key the key that needs to be removed.
* @return the value to which the <code>key</code> had been mapped in this
* dictionary, or <code>null</code> if the key did not have a
* mapping.
* @exception NullPointerException if <tt>key</tt> is <tt>null</tt>.
*/
abstract public V remove(Object key);
}

View File

@@ -0,0 +1,233 @@
/*
* 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.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.toDoubleStatistics()} 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.
*
* If any recorded value is a NaN or the sum is at any point a NaN
* then the sum will be NaN.
*
* <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.
*
* @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.
*
* If any recorded value is a NaN or the sum is at any point a NaN
* then the average will be code NaN.
*
* <p>The average returned can vary depending upon the order in
* which values are recorded.
*
* This method may be implemented using compensated summation or
* other technique to reduce the error bound in the {@link #getSum
* numerical sum} used to compute the average.
*
* @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;
}
/**
* {@inheritDoc}
*
* 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 <tt>null</tt> 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</code> class to indicate
* that the stack is empty.
*
* @author Jonathan Payne
* @see java.util.Stack
* @since JDK1.0
*/
public
class EmptyStackException extends RuntimeException {
private static final long serialVersionUID = 5084686378493302095L;
/**
* Constructs a new <code>EmptyStackException</code> with <tt>null</tt>
* 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 java.util.Map.Entry;
import sun.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 <tt>EnumMap</tt> 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}/../technotes/guides/collections/index.html">
* 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 <tt>Class</tt> 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);
}
private static final Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
/**
* 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 <tt>keyType</tt> 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 <tt>m</tt> 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 <tt>EnumMap</tt> 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 <tt>m</tt> is not an
* <tt>EnumMap</tt> instance and contains no mappings
* @throws NullPointerException if <tt>m</tt> 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 <tt>true</tt> 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 <tt>true</tt> 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 <tt>true</tt> if this map contains a mapping for the specified
* key.
*
* @param key the key whose presence in this map is to be tested
* @return <tt>true</tt> 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
* <tt>null</tt> if there was no mapping for key. (A <tt>null</tt>
* return can also indicate that the map previously associated
* <tt>null</tt> 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
* <tt>null</tt> if there was no entry for key. (A <tt>null</tt>
* return can also indicate that the map previously associated
* <tt>null</tt> 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
* <tt>true</tt> 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 <tt>true</tt> 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.keyType != keyType)
return size == 0 && em.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 <tt>EnumMap</tt> 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 <tt>EnumMap</tt> 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,464 @@
/*
* 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 sun.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 <tt>int</tt>-based "bit flags." Even bulk
* operations (such as <tt>containsAll</tt> and <tt>retainAll</tt>) should
* run very quickly if their argument is also an enum set.
*
* <p>The iterator returned by the <tt>iterator</tt> 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, <tt>EnumSet</tt> 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}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @author Josh Bloch
* @since 1.5
* @see EnumMap
* @serial exclude
*/
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;
private static Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
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 <tt>elementType</tt> 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 <tt>elementType</tt> 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 <tt>s</tt> 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 <tt>EnumSet</tt> 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 <tt>c</tt> is not an
* <tt>EnumSet</tt> instance and contains no elements
* @throws NullPointerException if <tt>c</tt> 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 <tt>s</tt> 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 <tt>e</tt> 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 <tt>rest</tt> 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
{
/**
* 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,79 @@
/*
* Copyright (c) 1994, 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;
/**
* An object that implements the Enumeration interface generates a
* series of elements, one at a time. Successive calls to the
* <code>nextElement</code> method return successive elements of the
* series.
* <p>
* For example, to print all elements of a <tt>Vector&lt;E&gt;</tt> <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</code>.
* <p>
* NOTE: The functionality of this interface is duplicated by the Iterator
* interface. In addition, Iterator adds an optional remove operation, and
* has shorter method names. New implementations should consider using
* Iterator in preference to Enumeration.
*
* @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 JDK1.0
*/
public interface Enumeration<E> {
/**
* Tests if this enumeration contains more elements.
*
* @return <code>true</code> if and only if this enumeration object
* contains at least one more element to provide;
* <code>false</code> 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();
}

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 JDK1.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 JDK1.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 <tt>null</tt> 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 <tt>Formattable</tt> interface must be implemented by any class that
* needs to perform custom formatting using the <tt>'s'</tt> 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 <tt>null</tt> 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
* <tt>formatter</tt> 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
* <tt>width</tt> then the output will be padded by
* <tt>'&nbsp;&nbsp;'</tt> 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 <tt>width</tt> is <tt>-1</tt>
* 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 <tt>precision</tt> characters even if the
* <tt>width</tt> is greater than the <tt>precision</tt>. If
* <tt>precision</tt> is <tt>-1</tt> 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 (<tt>'&#92;u0020'</tt>) 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 <tt>'-'</tt> (<tt>'&#92;u002d'</tt>) 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
* <tt>formatter</tt> 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 <tt>'S'</tt> (<tt>'&#92;u0053'</tt>) 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 <tt>Formattable</tt>.
*
* <p> This flag corresponds to <tt>'#'</tt> (<tt>'&#92;u0023'</tt>) 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 <tt>null</tt> 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,362 @@
/*
* Copyright (c) 1997, 2021, 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;
import sun.misc.SharedSecrets;
/**
* This class implements the <tt>Set</tt> interface, backed by a hash table
* (actually a <tt>HashMap</tt> 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 <tt>null</tt>
* element.
*
* <p>This class offers constant time performance for the basic operations
* (<tt>add</tt>, <tt>remove</tt>, <tt>contains</tt> and <tt>size</tt>),
* assuming the hash function disperses the elements properly among the
* buckets. Iterating over this set requires time proportional to the sum of
* the <tt>HashSet</tt> instance's size (the number of elements) plus the
* "capacity" of the backing <tt>HashMap</tt> 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 <tt>iterator</tt> 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 <tt>remove</tt>
* 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 <tt>ConcurrentModificationException</tt> 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}/../technotes/guides/collections/index.html">
* 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 <tt>HashMap</tt> 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 <tt>HashMap</tt> 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 <tt>HashMap</tt> 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 <tt>HashMap</tt> 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 <tt>true</tt> if this set contains no elements.
*
* @return <tt>true</tt> if this set contains no elements
*/
public boolean isEmpty() {
return map.isEmpty();
}
/**
* Returns <tt>true</tt> if this set contains the specified element.
* More formally, returns <tt>true</tt> if and only if this set
* contains an element <tt>e</tt> such that
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
*
* @param o element whose presence in this set is to be tested
* @return <tt>true</tt> 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 <tt>e</tt> to this set if
* this set contains no element <tt>e2</tt> such that
* <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
* If this set already contains the element, the call leaves the set
* unchanged and returns <tt>false</tt>.
*
* @param e element to be added to this set
* @return <tt>true</tt> 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 <tt>e</tt> such that
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
* if this set contains such an element. Returns <tt>true</tt> 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 <tt>true</tt> 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 <tt>HashSet</tt> 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 <tt>HashSet</tt> instance to a stream (that is,
* serialize it).
*
* @serialData The capacity of the backing <tt>HashMap</tt> 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 <tt>HashSet</tt> instance from a stream (that is,
* deserialize it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Consume and ignore stream fields (currently zero).
s.readFields();
// 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);
}
// Clamp load factor to range of 0.25...4.0.
loadFactor = Math.min(Math.max(0.25f, loadFactor), 4.0f);
// 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);
// Constructing the backing map will lazily create an array when the first element is
// added, so check it before construction. Call HashMap.tableSizeFor to compute the
// actual allocation size. Check Map.Entry[].class since it's the nearest public type to
// what is actually created.
SharedSecrets.getJavaOISAccess()
.checkArray(s, Map.Entry[].class, HashMap.tableSizeFor(capacity));
// Create backing HashMap
map = (((HashSet<?>)this) instanceof LinkedHashSet ?
new LinkedHashMap<E,Object>(capacity, loadFactor) :
new HashMap<E,Object>(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<E,Object>(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 <tt>null</tt> 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 <tt>null</tt> 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 <tt>null</tt> 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
* <tt>-1</tt>, 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 <tt>-1</tt> 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,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</code> 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</code> with <tt>null</tt>
* as its error message string.
*/
public InputMismatchException() {
super();
}
/**
* Constructs an <code>InputMismatchException</code>, saving a reference
* to the error message string <tt>s</tt> for later retrieval by the
* <tt>getMessage</tt> method.
*
* @param s the detail message.
*/
public InputMismatchException(String s) {
super(s);
}
}

View File

@@ -0,0 +1,171 @@
/*
* 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.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.toIntStatistics()} 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;
}
@Override
/**
* {@inheritDoc}
*
* 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.
*/
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,118 @@
/*
* 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;
/**
* 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}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @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}. 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.
*
* @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.
*
* @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 <tt>true</tt> if this set contains no elements.
*
* @return <tt>true</tt> if this set contains no elements
*/
public boolean isEmpty() {
return size == 0;
}
/**
* Returns <tt>true</tt> if this set contains the specified element.
*
* @param e element to be checked for containment in this collection
* @return <tt>true</tt> 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 <tt>true</tt> if the set changed as a result of the call
*
* @throws NullPointerException if <tt>e</tt> 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 <tt>true</tt> 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 <tt>true</tt> if this set contains all of the elements
* in the specified collection.
*
* @param c collection to be checked for containment in this set
* @return <tt>true</tt> 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 <tt>true</tt> 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 <tt>true</tt> 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 <tt>true</tt> 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
* <tt>true</tt> 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 <tt>true</tt> 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,756 @@
/*
* 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 <tt>Map</tt> interface,
* with predictable iteration order. This implementation differs from
* <tt>HashMap</tt> 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 <tt>k</tt> is
* reinserted into a map <tt>m</tt> if <tt>m.put(k, v)</tt> is invoked when
* <tt>m.containsKey(k)</tt> would return <tt>true</tt> 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 <tt>Map</tt> operations, and
* permits null elements. Like <tt>HashMap</tt>, it provides constant-time
* performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
* <tt>remove</tt>), assuming the hash function disperses elements
* properly among the buckets. Performance is likely to be just slightly
* below that of <tt>HashMap</tt>, due to the added expense of maintaining the
* linked list, with one exception: Iteration over the collection-views
* of a <tt>LinkedHashMap</tt> requires time proportional to the <i>size</i>
* of the map, regardless of its capacity. Iteration over a <tt>HashMap</tt>
* 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 <tt>HashMap</tt>. Note, however, that the penalty for choosing an
* excessively high value for initial capacity is less severe for this class
* than for <tt>HashMap</tt>, 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 <tt>get</tt> is a structural modification.
* </strong>)
*
* <p>The iterators returned by the <tt>iterator</tt> 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
* <tt>remove</tt> 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 <tt>ConcurrentModificationException</tt> 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}/../technotes/guides/collections/index.html">
* 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: <tt>true</tt>
* for access-order, <tt>false</tt> 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<K,V>(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<K,V>(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<K,V>(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<K,V>(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 <tt>LinkedHashMap</tt> 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 <tt>LinkedHashMap</tt> 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 <tt>LinkedHashMap</tt> instance
* with the default initial capacity (16) and load factor (0.75).
*/
public LinkedHashMap() {
super();
accessOrder = false;
}
/**
* Constructs an insertion-ordered <tt>LinkedHashMap</tt> instance with
* the same mappings as the specified map. The <tt>LinkedHashMap</tt>
* 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 <tt>LinkedHashMap</tt> 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 - <tt>true</tt> for
* access-order, <tt>false</tt> 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 <tt>true</tt> 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 <tt>true</tt> 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 <tt>true</tt> if this map should remove its eldest entry.
* This method is invoked by <tt>put</tt> and <tt>putAll</tt> 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
* <tt>false</tt> (indicating that the map should not attempt any
* further modification). The effects of returning <tt>true</tt>
* after modifying the map from within this method are unspecified.
*
* <p>This implementation merely returns <tt>false</tt> (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 <tt>true</tt>. If the map was empty prior
* to the <tt>put</tt> or <tt>putAll</tt> 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 <tt>true</tt> if the eldest entry should be removed
* from the map; <tt>false</tt> 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 <tt>remove</tt> operation), the results of
* the iteration are undefined. The set supports element removal,
* which removes the corresponding mapping from the map, via the
* <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
* <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
* operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
* 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 <tt>remove</tt> operation),
* the results of the iteration are undefined. The collection
* supports element removal, which removes the corresponding
* mapping from the map, via the <tt>Iterator.remove</tt>,
* <tt>Collection.remove</tt>, <tt>removeAll</tt>,
* <tt>retainAll</tt> and <tt>clear</tt> operations. It does not
* support the <tt>add</tt> or <tt>addAll</tt> 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 <tt>remove</tt> operation, or through the
* <tt>setValue</tt> 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 <tt>Iterator.remove</tt>,
* <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
* <tt>clear</tt> operations. It does not support the
* <tt>add</tt> or <tt>addAll</tt> 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;
K key = p.key;
removeNode(hash(key), 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 <tt>Set</tt> interface,
* with predictable iteration order. This implementation differs from
* <tt>HashSet</tt> 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 <tt>e</tt>
* is reinserted into a set <tt>s</tt> if <tt>s.add(e)</tt> is invoked when
* <tt>s.contains(e)</tt> would return <tt>true</tt> 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 <tt>Set</tt> operations, and
* permits null elements. Like <tt>HashSet</tt>, it provides constant-time
* performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
* <tt>remove</tt>), assuming the hash function disperses elements
* properly among the buckets. Performance is likely to be just slightly
* below that of <tt>HashSet</tt>, due to the added expense of maintaining the
* linked list, with one exception: Iteration over a <tt>LinkedHashSet</tt>
* requires time proportional to the <i>size</i> of the set, regardless of
* its capacity. Iteration over a <tt>HashSet</tt> 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 <tt>HashSet</tt>. Note, however, that the penalty for choosing an
* excessively high value for initial capacity is less severe for this class
* than for <tt>HashSet</tt>, 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 <tt>iterator</tt> 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 <tt>remove</tt>
* 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 <tt>ConcurrentModificationException</tt> 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}/../technotes/guides/collections/index.html">
* 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

View File

@@ -0,0 +1,734 @@
/*
* Copyright (c) 1997, 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 java.util.function.UnaryOperator;
/**
* An ordered collection (also known as a <i>sequence</i>). The user of this
* interface has precise control over where in the list each element is
* inserted. The user can access elements by their integer index (position in
* the list), and search for elements in the list.<p>
*
* Unlike sets, lists typically allow duplicate elements. More formally,
* lists typically allow pairs of elements <tt>e1</tt> and <tt>e2</tt>
* such that <tt>e1.equals(e2)</tt>, and they typically allow multiple
* null elements if they allow null elements at all. It is not inconceivable
* that someone might wish to implement a list that prohibits duplicates, by
* throwing runtime exceptions when the user attempts to insert them, but we
* expect this usage to be rare.<p>
*
* The <tt>List</tt> interface places additional stipulations, beyond those
* specified in the <tt>Collection</tt> interface, on the contracts of the
* <tt>iterator</tt>, <tt>add</tt>, <tt>remove</tt>, <tt>equals</tt>, and
* <tt>hashCode</tt> methods. Declarations for other inherited methods are
* also included here for convenience.<p>
*
* The <tt>List</tt> interface provides four methods for positional (indexed)
* access to list elements. Lists (like Java arrays) are zero based. Note
* that these operations may execute in time proportional to the index value
* for some implementations (the <tt>LinkedList</tt> class, for
* example). Thus, iterating over the elements in a list is typically
* preferable to indexing through it if the caller does not know the
* implementation.<p>
*
* The <tt>List</tt> interface provides a special iterator, called a
* <tt>ListIterator</tt>, that allows element insertion and replacement, and
* bidirectional access in addition to the normal operations that the
* <tt>Iterator</tt> interface provides. A method is provided to obtain a
* list iterator that starts at a specified position in the list.<p>
*
* The <tt>List</tt> interface provides two methods to search for a specified
* object. From a performance standpoint, these methods should be used with
* caution. In many implementations they will perform costly linear
* searches.<p>
*
* The <tt>List</tt> interface provides two methods to efficiently insert and
* remove multiple elements at an arbitrary point in the list.<p>
*
* Note: While it is permissible for lists to contain themselves as elements,
* extreme caution is advised: the <tt>equals</tt> and <tt>hashCode</tt>
* methods are no longer well defined on such a list.
*
* <p>Some list 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
* <tt>NullPointerException</tt> or <tt>ClassCastException</tt>. 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 list 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>This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @param <E> the type of elements in this list
*
* @author Josh Bloch
* @author Neal Gafter
* @see Collection
* @see Set
* @see ArrayList
* @see LinkedList
* @see Vector
* @see Arrays#asList(Object[])
* @see Collections#nCopies(int, Object)
* @see Collections#EMPTY_LIST
* @see AbstractList
* @see AbstractSequentialList
* @since 1.2
*/
public interface List<E> extends Collection<E> {
// Query Operations
/**
* Returns the number of elements in this list. If this list contains
* more than <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
*
* @return the number of elements in this list
*/
int size();
/**
* Returns <tt>true</tt> if this list contains no elements.
*
* @return <tt>true</tt> if this list contains no elements
*/
boolean isEmpty();
/**
* Returns <tt>true</tt> if this list contains the specified element.
* More formally, returns <tt>true</tt> if and only if this list contains
* at least one element <tt>e</tt> such that
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
*
* @param o element whose presence in this list is to be tested
* @return <tt>true</tt> if this list contains the specified element
* @throws ClassCastException if the type of the specified element
* is incompatible with this list
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* list 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 list in proper sequence.
*
* @return an iterator over the elements in this list in proper sequence
*/
Iterator<E> iterator();
/**
* Returns an array containing all of the elements in this list in proper
* sequence (from first to last element).
*
* <p>The returned array will be "safe" in that no references to it are
* maintained by this list. (In other words, this method must
* allocate a new array even if this list 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 list in proper
* sequence
* @see Arrays#asList(Object[])
*/
Object[] toArray();
/**
* Returns an array containing all of the elements in this list in
* proper sequence (from first to last element); the runtime type of
* the returned array is that of the specified array. If the list 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 list.
*
* <p>If the list fits in the specified array with room to spare (i.e.,
* the array has more elements than the list), the element in the array
* immediately following the end of the list is set to <tt>null</tt>.
* (This is useful in determining the length of the list <i>only</i> if
* the caller knows that the list does not contain any null elements.)
*
* <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 <tt>x</tt> is a list known to contain only strings.
* The following code can be used to dump the list into a newly
* allocated array of <tt>String</tt>:
*
* <pre>{@code
* String[] y = x.toArray(new String[0]);
* }</pre>
*
* Note that <tt>toArray(new Object[0])</tt> is identical in function to
* <tt>toArray()</tt>.
*
* @param a the array into which the elements of this list 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 the elements of this list
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this list
* @throws NullPointerException if the specified array is null
*/
<T> T[] toArray(T[] a);
// Modification Operations
/**
* 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.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
* @throws UnsupportedOperationException if the <tt>add</tt> 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
*/
boolean add(E e);
/**
* Removes the first occurrence of the specified element from this list,
* if it is present (optional operation). If this list does not contain
* the element, it is unchanged. More formally, removes the element with
* the lowest index <tt>i</tt> such that
* <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
* (if such an element exists). Returns <tt>true</tt> if this list
* contained the specified element (or equivalently, if this list changed
* as a result of the call).
*
* @param o element to be removed from this list, if present
* @return <tt>true</tt> if this list contained the specified element
* @throws ClassCastException if the type of the specified element
* is incompatible with this list
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* list does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws UnsupportedOperationException if the <tt>remove</tt> operation
* is not supported by this list
*/
boolean remove(Object o);
// Bulk Modification Operations
/**
* Returns <tt>true</tt> if this list contains all of the elements of the
* specified collection.
*
* @param c collection to be checked for containment in this list
* @return <tt>true</tt> if this list 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
* list
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified collection contains one
* or more null elements and this list 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);
/**
* Appends all of the elements in the specified collection to the end of
* this list, in the order that they are returned by the specified
* collection's iterator (optional operation). 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.)
*
* @param c collection containing elements to be added to this list
* @return <tt>true</tt> if this list changed as a result of the call
* @throws UnsupportedOperationException if the <tt>addAll</tt> operation
* is not supported by this list
* @throws ClassCastException if the class of an element of the specified
* collection prevents it from being added to this list
* @throws NullPointerException if the specified collection contains one
* or more null elements and this list 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 list
* @see #add(Object)
*/
boolean addAll(Collection<? extends E> c);
/**
* 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.)
*
* @param index index at which to insert the first element from the
* specified collection
* @param c collection containing elements to be added to this list
* @return <tt>true</tt> if this list changed as a result of the call
* @throws UnsupportedOperationException if the <tt>addAll</tt> operation
* is not supported by this list
* @throws ClassCastException if the class of an element of the specified
* collection prevents it from being added to this list
* @throws NullPointerException if the specified collection contains one
* or more null elements and this list 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 list
* @throws IndexOutOfBoundsException if the index is out of range
* (<tt>index &lt; 0 || index &gt; size()</tt>)
*/
boolean addAll(int index, Collection<? extends E> c);
/**
* Removes from this list all of its elements that are contained in the
* specified collection (optional operation).
*
* @param c collection containing elements to be removed from this list
* @return <tt>true</tt> if this list changed as a result of the call
* @throws UnsupportedOperationException if the <tt>removeAll</tt> operation
* is not supported by this list
* @throws ClassCastException if the class of an element of this list
* is incompatible with the specified collection
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this list 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);
/**
* Retains only the elements in this list that are contained in the
* specified collection (optional operation). In other words, removes
* from this list all of its elements that are not contained in the
* specified collection.
*
* @param c collection containing elements to be retained in this list
* @return <tt>true</tt> if this list changed as a result of the call
* @throws UnsupportedOperationException if the <tt>retainAll</tt> operation
* is not supported by this list
* @throws ClassCastException if the class of an element of this list
* is incompatible with the specified collection
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this list 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 retainAll(Collection<?> c);
/**
* Replaces each element of this list with the result of applying the
* operator to that element. Errors or runtime exceptions thrown by
* the operator are relayed to the caller.
*
* @implSpec
* The default implementation is equivalent to, for this {@code list}:
* <pre>{@code
* final ListIterator<E> li = list.listIterator();
* while (li.hasNext()) {
* li.set(operator.apply(li.next()));
* }
* }</pre>
*
* If the list's list-iterator does not support the {@code set} operation
* then an {@code UnsupportedOperationException} will be thrown when
* replacing the first element.
*
* @param operator the operator to apply to each element
* @throws UnsupportedOperationException if this list is unmodifiable.
* Implementations may throw this exception if an element
* cannot be replaced or if, in general, modification is not
* supported
* @throws NullPointerException if the specified operator is null or
* if the operator result is a null value and this list does
* not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @since 1.8
*/
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
/**
* Sorts this list according to the order induced by the specified
* {@link Comparator}.
*
* <p>All elements in this list must be <i>mutually comparable</i> using the
* specified comparator (that is, {@code c.compare(e1, e2)} must not throw
* a {@code ClassCastException} for any elements {@code e1} and {@code e2}
* in the list).
*
* <p>If the specified comparator is {@code null} then all elements in this
* list must implement the {@link Comparable} interface and the elements'
* {@linkplain Comparable natural ordering} should be used.
*
* <p>This list must be modifiable, but need not be resizable.
*
* @implSpec
* The default implementation obtains an array containing all elements in
* this list, sorts the array, and iterates over this list resetting each
* element from the corresponding position in the array. (This avoids the
* n<sup>2</sup> log(n) performance that would result from attempting
* to sort a linked list in place.)
*
* @implNote
* This implementation is a stable, adaptive, iterative mergesort that
* requires far fewer than n lg(n) comparisons when the input array is
* partially sorted, while offering the performance of a traditional
* mergesort when the input array is randomly ordered. If the input array
* is nearly sorted, the implementation requires approximately n
* comparisons. Temporary storage requirements vary from a small constant
* for nearly sorted input arrays to n/2 object references for randomly
* ordered input arrays.
*
* <p>The implementation takes equal advantage of ascending and
* descending order in its input array, and can take advantage of
* ascending and descending order in different parts of the same
* input array. It is well-suited to merging two or more sorted arrays:
* simply concatenate the arrays and sort the resulting array.
*
* <p>The implementation was adapted from Tim Peters's list sort for Python
* (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
* TimSort</a>). It uses techniques from Peter McIlroy's "Optimistic
* Sorting and Information Theoretic Complexity", in Proceedings of the
* Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
* January 1993.
*
* @param c the {@code Comparator} used to compare list elements.
* A {@code null} value indicates that the elements'
* {@linkplain Comparable natural ordering} should be used
* @throws ClassCastException if the list contains elements that are not
* <i>mutually comparable</i> using the specified comparator
* @throws UnsupportedOperationException if the list's list-iterator does
* not support the {@code set} operation
* @throws IllegalArgumentException
* (<a href="Collection.html#optional-restrictions">optional</a>)
* if the comparator is found to violate the {@link Comparator}
* contract
* @since 1.8
*/
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
/**
* Removes all of the elements from this list (optional operation).
* The list will be empty after this call returns.
*
* @throws UnsupportedOperationException if the <tt>clear</tt> operation
* is not supported by this list
*/
void clear();
// Comparison and hashing
/**
* Compares the specified object with this list for equality. Returns
* <tt>true</tt> 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 <tt>e1</tt> and
* <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null :
* e1.equals(e2))</tt>.) In other words, two lists are defined to be
* equal if they contain the same elements in the same order. This
* definition ensures that the equals method works properly across
* different implementations of the <tt>List</tt> interface.
*
* @param o the object to be compared for equality with this list
* @return <tt>true</tt> if the specified object is equal to this list
*/
boolean equals(Object o);
/**
* Returns the hash code value for this list. The hash code of a list
* is defined to be the result of the following calculation:
* <pre>{@code
* int hashCode = 1;
* for (E e : list)
* hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
* }</pre>
* This ensures that <tt>list1.equals(list2)</tt> implies that
* <tt>list1.hashCode()==list2.hashCode()</tt> for any two lists,
* <tt>list1</tt> and <tt>list2</tt>, as required by the general
* contract of {@link Object#hashCode}.
*
* @return the hash code value for this list
* @see Object#equals(Object)
* @see #equals(Object)
*/
int hashCode();
// Positional Access Operations
/**
* Returns the element at the specified position in this list.
*
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException if the index is out of range
* (<tt>index &lt; 0 || index &gt;= size()</tt>)
*/
E get(int index);
/**
* Replaces the element at the specified position in this list with the
* specified element (optional operation).
*
* @param index index of the element to replace
* @param element element to be stored at the specified position
* @return the element previously at the specified position
* @throws UnsupportedOperationException if the <tt>set</tt> 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 the specified
* element prevents it from being added to this list
* @throws IndexOutOfBoundsException if the index is out of range
* (<tt>index &lt; 0 || index &gt;= size()</tt>)
*/
E set(int index, E element);
/**
* 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).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws UnsupportedOperationException if the <tt>add</tt> 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 the specified
* element prevents it from being added to this list
* @throws IndexOutOfBoundsException if the index is out of range
* (<tt>index &lt; 0 || index &gt; size()</tt>)
*/
void add(int index, E element);
/**
* 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.
*
* @param index the index of the element to be removed
* @return the element previously at the specified position
* @throws UnsupportedOperationException if the <tt>remove</tt> operation
* is not supported by this list
* @throws IndexOutOfBoundsException if the index is out of range
* (<tt>index &lt; 0 || index &gt;= size()</tt>)
*/
E remove(int index);
// Search Operations
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index <tt>i</tt> such that
* <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*
* @param o element to search for
* @return the index of the first occurrence of the specified element in
* this list, or -1 if this list does not contain the element
* @throws ClassCastException if the type of the specified element
* is incompatible with this list
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* list does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>)
*/
int indexOf(Object o);
/**
* Returns the index of the last occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the highest index <tt>i</tt> such that
* <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*
* @param o element to search for
* @return the index of the last occurrence of the specified element in
* this list, or -1 if this list does not contain the element
* @throws ClassCastException if the type of the specified element
* is incompatible with this list
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* list does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>)
*/
int lastIndexOf(Object o);
// List Iterators
/**
* Returns a list iterator over the elements in this list (in proper
* sequence).
*
* @return a list iterator over the elements in this list (in proper
* sequence)
*/
ListIterator<E> listIterator();
/**
* Returns a list iterator over the elements in this list (in proper
* sequence), starting at the specified position in the list.
* The specified index indicates the first element that would be
* returned by an initial call to {@link ListIterator#next next}.
* An initial call to {@link ListIterator#previous previous} would
* return the element with the specified index minus one.
*
* @param index index of the first element to be returned from the
* list iterator (by a call to {@link ListIterator#next next})
* @return a list iterator over the elements in this list (in proper
* sequence), starting at the specified position in the list
* @throws IndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index > size()})
*/
ListIterator<E> listIterator(int index);
// View
/**
* Returns a view of the portion of this list between the specified
* <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive. (If
* <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is
* empty.) The returned list is backed by this list, so non-structural
* changes in the returned list are reflected in this list, and vice-versa.
* The returned list supports all of the optional list operations supported
* by this list.<p>
*
* This method eliminates the need for explicit range operations (of
* the sort that commonly exist for arrays). Any operation that expects
* a list can be used as a range operation by passing a subList view
* instead of a whole list. For example, the following idiom
* removes a range of elements from a list:
* <pre>{@code
* list.subList(from, to).clear();
* }</pre>
* Similar idioms may be constructed for <tt>indexOf</tt> and
* <tt>lastIndexOf</tt>, and all of the algorithms in the
* <tt>Collections</tt> class can be applied to a subList.<p>
*
* The semantics of the list returned by this method become undefined if
* the backing list (i.e., this list) is <i>structurally modified</i> in
* any way other than via the returned list. (Structural modifications are
* those that change the size of this list, or otherwise perturb it in such
* a fashion that iterations in progress may yield incorrect results.)
*
* @param fromIndex low endpoint (inclusive) of the subList
* @param toIndex high endpoint (exclusive) of the subList
* @return a view of the specified range within this list
* @throws IndexOutOfBoundsException for an illegal endpoint index value
* (<tt>fromIndex &lt; 0 || toIndex &gt; size ||
* fromIndex &gt; toIndex</tt>)
*/
List<E> subList(int fromIndex, int toIndex);
/**
* Creates a {@link Spliterator} over the elements in this list.
*
* <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and
* {@link Spliterator#ORDERED}. 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 list's {@code Iterator}. The spliterator inherits the
* <em>fail-fast</em> properties of the list's iterator.
*
* @implNote
* The created {@code Spliterator} additionally reports
* {@link Spliterator#SUBSIZED}.
*
* @return a {@code Spliterator} over the elements in this list
* @since 1.8
*/
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.ORDERED);
}
}

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}/../technotes/guides/collections/index.html">
* 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, 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.
*/
/*
* (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 name="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 JDK1.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.
*/
abstract protected 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 (int i = 0; i < contents.length; ++i) {
// key must be non-null String, value must be non-null
String key = (String) contents[i][0];
Object value = contents[i][1];
if (key == null || value == null) {
throw new NullPointerException();
}
temp.put(key, value);
}
lookup = temp;
}
private Map<String,Object> lookup = null;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,482 @@
/*
* Copyright (c) 2005, 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;
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
;
private LocaleISOData() {
}
}

View File

@@ -0,0 +1,183 @@
/*
* 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.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.toLongStatistics()} 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;
}
@Override
/**
* {@inheritDoc}
*
* 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.
*/
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 <tt>null</tt> 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 <tt>null</tt> 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 JDK1.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</code> with
* <code>message</code>, <code>className</code>, <code>key</code>,
* and <code>cause</code>. This constructor is package private for
* use by <code>ResourceBundle.getBundle</code>.
*
* @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,424 @@
/*
* 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
* {@code lowerEntry}, {@code floorEntry}, {@code ceilingEntry},
* and {@code 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
* {@code lowerKey}, {@code floorKey}, {@code ceilingKey}, and
* {@code 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 {@code 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 {@code subMap}, {@code headMap},
* and {@code tailMap} 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 {@code firstEntry},
* {@code pollFirstEntry}, {@code lastEntry}, and
* {@code 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 overriden to return {@code NavigableSet}.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* 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
* <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
* 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,319 @@
/*
* 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 {@code lower},
* {@code floor}, {@code ceiling}, and {@code 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. A {@code NavigableSet} may be accessed and
* traversed in either ascending or descending order. The {@code
* 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
* {@code pollFirst} and {@code pollLast} that return and remove the
* lowest and highest element, if one exists, else returning {@code
* null}. Methods {@code subSet}, {@code headSet},
* and {@code tailSet} 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}/../technotes/guides/collections/index.html">
* 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
* <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
* 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 JDK1.0
*/
public
class NoSuchElementException extends RuntimeException {
private static final long serialVersionUID = 6769829250639411880L;
/**
* Constructs a <code>NoSuchElementException</code> with <tt>null</tt>
* as its error message string.
*/
public NoSuchElementException() {
super();
}
/**
* Constructs a <code>NoSuchElementException</code>, saving a reference
* to the error message string <tt>s</tt> for later retrieval by the
* <tt>getMessage</tt> method.
*
* @param s the detail message.
*/
public NoSuchElementException(String s) {
super(s);
}
}

View File

@@ -0,0 +1,293 @@
/*
* Copyright (c) 2009, 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.Supplier;
/**
* This class consists of {@code static} utility methods for operating
* on objects. 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, and comparing two objects.
*
* @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;
}
/**
* 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.get());
return obj;
}
}

View File

@@ -0,0 +1,213 @@
/*
* 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;
/**
* 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 <tt>Observer</tt>. After an
* observable instance changes, an application calling the
* <code>Observable</code>'s <code>notifyObservers</code> method
* causes all of its observers to be notified of the change by a call
* to their <code>update</code> 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 <tt>wait</tt> and <tt>notify</tt>
* mechanism of class <tt>Object</tt>.
* <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
* <tt>equals</tt> 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 JDK1.0
*/
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</CODE> 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</code> method, then notify all of its observers
* and then call the <code>clearChanged</code> method to
* indicate that this object has no longer changed.
* <p>
* Each observer has its <code>update</code> method called with two
* arguments: this observable object and <code>null</code>. In other
* words, this method is equivalent to:
* <blockquote><tt>
* notifyObservers(null)</tt></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</code> method, then notify all of its observers
* and then call the <code>clearChanged</code> method to indicate
* that this object has no longer changed.
* <p>
* Each observer has its <code>update</code> method called with two
* arguments: this observable object and the <code>arg</code> 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 <tt>Observable</tt> object as having been changed; the
* <tt>hasChanged</tt> method will now return <tt>true</tt>.
*/
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 <tt>hasChanged</tt> method will now return <tt>false</tt>.
* This method is called automatically by the
* <code>notifyObservers</code> 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</code> if and only if the <code>setChanged</code>
* method has been called more recently than the
* <code>clearChanged</code> method on this object;
* <code>false</code> otherwise.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#setChanged()
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
* Returns the number of observers of this <tt>Observable</tt> object.
*
* @return the number of observers of this object.
*/
public synchronized int countObservers() {
return obs.size();
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 1994, 1998, 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</code> interface when it
* wants to be informed of changes in observable objects.
*
* @author Chris Warth
* @see java.util.Observable
* @since JDK1.0
*/
public interface Observer {
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> 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</code>
* method.
*/
void update(Observable o, Object arg);
}

View File

@@ -0,0 +1,349 @@
/*
* 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.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* A container object which may or may not contain a non-null value.
* If a value is present, {@code isPresent()} will return {@code true} and
* {@code get()} will return the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(java.lang.Object) orElse()}
* (return a default value if value not present) and
* {@link #ifPresent(java.util.function.Consumer) ifPresent()} (execute a block
* of code if the 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.
*
* @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
* 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 Option.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
* @param <T> 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 value present.
*
* @param value the non-null value to be present
* @throws NullPointerException if value is null
*/
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
/**
* Returns an {@code Optional} with the specified present non-null value.
*
* @param <T> the class of the value
* @param value the value to be present, which must be non-null
* @return an {@code Optional} with the value present
* @throws NullPointerException if value is null
*/
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
/**
* Returns an {@code Optional} describing the specified value, if non-null,
* otherwise returns an empty {@code Optional}.
*
* @param <T> the class of the value
* @param value the possibly-null value to describe
* @return an {@code Optional} with a present value if the specified value
* is non-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 in this {@code Optional}, returns the value,
* otherwise throws {@code NoSuchElementException}.
*
* @return the non-null value held by this {@code Optional}
* @throws NoSuchElementException if there is no value present
*
* @see Optional#isPresent()
*/
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* Return {@code true} if there is a value present, otherwise {@code false}.
*
* @return {@code true} if there is a value present, otherwise {@code false}
*/
public boolean isPresent() {
return value != null;
}
/**
* If a value is present, invoke the specified consumer with the value,
* otherwise do nothing.
*
* @param consumer block to be executed if a value is present
* @throws NullPointerException if value is present and {@code consumer} is
* null
*/
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
/**
* If a value is present, and the value matches the given predicate,
* return an {@code Optional} describing the value, otherwise return an
* empty {@code Optional}.
*
* @param predicate a predicate to apply to the 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 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, apply the provided mapping function to it,
* and if the result is non-null, return an {@code Optional} describing the
* result. Otherwise return an empty {@code Optional}.
*
* @apiNote This method supports post-processing on optional values, without
* the need to explicitly check for a return status. For example, the
* following code traverses a stream of file names, selects one that has
* not yet been processed, and then opens that file, returning an
* {@code Optional<FileInputStream>}:
*
* <pre>{@code
* Optional<FileInputStream> fis =
* names.stream().filter(name -> !isProcessedYet(name))
* .findFirst()
* .map(name -> new FileInputStream(name));
* }</pre>
*
* Here, {@code findFirst} returns an {@code Optional<String>}, and then
* {@code map} returns an {@code Optional<FileInputStream>} for the desired
* file if one exists.
*
* @param <U> The type of the result of the mapping function
* @param mapper a mapping function to apply to the value, if present
* @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 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, apply the provided {@code Optional}-bearing
* mapping function to it, return that result, otherwise return an empty
* {@code Optional}. This method is similar to {@link #map(Function)},
* but the provided mapper is one whose result is already an {@code Optional},
* and if invoked, {@code flatMap} does not wrap it with an additional
* {@code Optional}.
*
* @param <U> The type parameter to the {@code Optional} returned by
* @param mapper a mapping function to apply to the value, if present
* the mapping function
* @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 null or returns
* a null result
*/
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
/**
* Return the value if present, otherwise return {@code other}.
*
* @param other the value to be returned if there is no value present, may
* be null
* @return the value, if present, otherwise {@code other}
*/
public T orElse(T other) {
return value != null ? value : other;
}
/**
* Return the value if present, otherwise invoke {@code other} and return
* the result of that invocation.
*
* @param other a {@code Supplier} whose result is returned if no value
* is present
* @return the value if present otherwise the result of {@code other.get()}
* @throws NullPointerException if value is not present and {@code other} is
* null
*/
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
/**
* Return the contained value, if present, otherwise throw an exception
* to be created by the provided supplier.
*
* @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 supplier which will return the exception to
* be thrown
* @return the present value
* @throws X if there is no value present
* @throws NullPointerException if no value is present and
* {@code exceptionSupplier} is 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 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 value of the present value, if any, or 0 (zero) if
* no value is present.
*
* @return hash code value of the present value or 0 if no value is present
*/
@Override
public int hashCode() {
return Objects.hashCode(value);
}
/**
* Returns a non-empty string representation of this 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 Optionals 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,252 @@
/*
* 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.util.function.DoubleConsumer;
import java.util.function.DoubleSupplier;
import java.util.function.Supplier;
/**
* A container object which may or may not contain a {@code double} value.
* If a value is present, {@code isPresent()} will return {@code true} and
* {@code getAsDouble()} will return the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(double) orElse()}
* (return a default value if value not present) and
* {@link #ifPresent(java.util.function.DoubleConsumer) ifPresent()} (execute a block
* of code if the 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.
*
* @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
* 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 Option.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 value present.
*
* @param value the double value to be present.
*/
private OptionalDouble(double value) {
this.isPresent = true;
this.value = value;
}
/**
* Return an {@code OptionalDouble} with the specified value present.
*
* @param value the value to be present
* @return an {@code OptionalDouble} with the value present
*/
public static OptionalDouble of(double value) {
return new OptionalDouble(value);
}
/**
* If a value is present in this {@code OptionalDouble}, returns the value,
* otherwise throws {@code NoSuchElementException}.
*
* @return the value held by this {@code OptionalDouble}
* @throws NoSuchElementException if there is no value present
*
* @see OptionalDouble#isPresent()
*/
public double getAsDouble() {
if (!isPresent) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* Return {@code true} if there is a value present, otherwise {@code false}.
*
* @return {@code true} if there is a value present, otherwise {@code false}
*/
public boolean isPresent() {
return isPresent;
}
/**
* Have the specified consumer accept the value if a value is present,
* otherwise do nothing.
*
* @param consumer block to be executed if a value is present
* @throws NullPointerException if value is present and {@code consumer} is
* null
*/
public void ifPresent(DoubleConsumer consumer) {
if (isPresent)
consumer.accept(value);
}
/**
* Return the value if present, otherwise return {@code other}.
*
* @param other the value to be returned if there is no value present
* @return the value, if present, otherwise {@code other}
*/
public double orElse(double other) {
return isPresent ? value : other;
}
/**
* Return the value if present, otherwise invoke {@code other} and return
* the result of that invocation.
*
* @param other a {@code DoubleSupplier} whose result is returned if no value
* is present
* @return the value if present otherwise the result of {@code other.getAsDouble()}
* @throws NullPointerException if value is not present and {@code other} is
* null
*/
public double orElseGet(DoubleSupplier other) {
return isPresent ? value : other.getAsDouble();
}
/**
* Return the contained value, if present, otherwise throw an exception
* to be created by the provided supplier.
*
* @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 supplier which will return the exception to
* be thrown
* @return the present value
* @throws X if there is no value present
* @throws NullPointerException if no value is present and
* {@code exceptionSupplier} is null
*/
public<X extends Throwable> double orElseThrow(Supplier<X> exceptionSupplier) throws X {
if (isPresent) {
return value;
} else {
throw exceptionSupplier.get();
}
}
/**
* Indicates whether some other object is "equal to" this 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 value of the present value, if any, or 0 (zero) if
* no value is present.
*
* @return hash code value of the present value or 0 if no value is present
*/
@Override
public int hashCode() {
return isPresent ? Double.hashCode(value) : 0;
}
/**
* {@inheritDoc}
*
* 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.
*
* @implSpec If a value is present the result must include its string
* representation in the result. Empty and present instances 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,252 @@
/*
* 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.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.Supplier;
/**
* A container object which may or may not contain a {@code int} value.
* If a value is present, {@code isPresent()} will return {@code true} and
* {@code getAsInt()} will return the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(int) orElse()}
* (return a default value if value not present) and
* {@link #ifPresent(java.util.function.IntConsumer) ifPresent()} (execute a block
* of code if the 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.
*
* @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
* 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 Option.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 value present.
*
* @param value the int value to be present
*/
private OptionalInt(int value) {
this.isPresent = true;
this.value = value;
}
/**
* Return an {@code OptionalInt} with the specified value present.
*
* @param value the value to be present
* @return an {@code OptionalInt} with the value present
*/
public static OptionalInt of(int value) {
return new OptionalInt(value);
}
/**
* If a value is present in this {@code OptionalInt}, returns the value,
* otherwise throws {@code NoSuchElementException}.
*
* @return the value held by this {@code OptionalInt}
* @throws NoSuchElementException if there is no value present
*
* @see OptionalInt#isPresent()
*/
public int getAsInt() {
if (!isPresent) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* Return {@code true} if there is a value present, otherwise {@code false}.
*
* @return {@code true} if there is a value present, otherwise {@code false}
*/
public boolean isPresent() {
return isPresent;
}
/**
* Have the specified consumer accept the value if a value is present,
* otherwise do nothing.
*
* @param consumer block to be executed if a value is present
* @throws NullPointerException if value is present and {@code consumer} is
* null
*/
public void ifPresent(IntConsumer consumer) {
if (isPresent)
consumer.accept(value);
}
/**
* Return the value if present, otherwise return {@code other}.
*
* @param other the value to be returned if there is no value present
* @return the value, if present, otherwise {@code other}
*/
public int orElse(int other) {
return isPresent ? value : other;
}
/**
* Return the value if present, otherwise invoke {@code other} and return
* the result of that invocation.
*
* @param other a {@code IntSupplier} whose result is returned if no value
* is present
* @return the value if present otherwise the result of {@code other.getAsInt()}
* @throws NullPointerException if value is not present and {@code other} is
* null
*/
public int orElseGet(IntSupplier other) {
return isPresent ? value : other.getAsInt();
}
/**
* Return the contained value, if present, otherwise throw an exception
* to be created by the provided supplier.
*
* @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 supplier which will return the exception to
* be thrown
* @return the present value
* @throws X if there is no value present
* @throws NullPointerException if no value is present and
* {@code exceptionSupplier} is null
*/
public<X extends Throwable> int orElseThrow(Supplier<X> exceptionSupplier) throws X {
if (isPresent) {
return value;
} else {
throw exceptionSupplier.get();
}
}
/**
* Indicates whether some other object is "equal to" this 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 value of the present value, if any, or 0 (zero) if
* no value is present.
*
* @return hash code value of the present value or 0 if no value is present
*/
@Override
public int hashCode() {
return isPresent ? Integer.hashCode(value) : 0;
}
/**
* {@inheritDoc}
*
* 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.
*
* @implSpec If a value is present the result must include its string
* representation in the result. Empty and present instances 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,252 @@
/*
* 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.util.function.LongConsumer;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
/**
* A container object which may or may not contain a {@code long} value.
* If a value is present, {@code isPresent()} will return {@code true} and
* {@code getAsLong()} will return the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(long) orElse()}
* (return a default value if value not present) and
* {@link #ifPresent(java.util.function.LongConsumer) ifPresent()} (execute a block
* of code if the 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.
*
* @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
* 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 Option.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 value present.
*
* @param value the long value to be present
*/
private OptionalLong(long value) {
this.isPresent = true;
this.value = value;
}
/**
* Return an {@code OptionalLong} with the specified value present.
*
* @param value the value to be present
* @return an {@code OptionalLong} with the value present
*/
public static OptionalLong of(long value) {
return new OptionalLong(value);
}
/**
* If a value is present in this {@code OptionalLong}, returns the value,
* otherwise throws {@code NoSuchElementException}.
*
* @return the value held by this {@code OptionalLong}
* @throws NoSuchElementException if there is no value present
*
* @see OptionalLong#isPresent()
*/
public long getAsLong() {
if (!isPresent) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* Return {@code true} if there is a value present, otherwise {@code false}.
*
* @return {@code true} if there is a value present, otherwise {@code false}
*/
public boolean isPresent() {
return isPresent;
}
/**
* Have the specified consumer accept the value if a value is present,
* otherwise do nothing.
*
* @param consumer block to be executed if a value is present
* @throws NullPointerException if value is present and {@code consumer} is
* null
*/
public void ifPresent(LongConsumer consumer) {
if (isPresent)
consumer.accept(value);
}
/**
* Return the value if present, otherwise return {@code other}.
*
* @param other the value to be returned if there is no value present
* @return the value, if present, otherwise {@code other}
*/
public long orElse(long other) {
return isPresent ? value : other;
}
/**
* Return the value if present, otherwise invoke {@code other} and return
* the result of that invocation.
*
* @param other a {@code LongSupplier} whose result is returned if no value
* is present
* @return the value if present otherwise the result of {@code other.getAsLong()}
* @throws NullPointerException if value is not present and {@code other} is
* null
*/
public long orElseGet(LongSupplier other) {
return isPresent ? value : other.getAsLong();
}
/**
* Return the contained value, if present, otherwise throw an exception
* to be created by the provided supplier.
*
* @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 supplier which will return the exception to
* be thrown
* @return the present value
* @throws X if there is no value present
* @throws NullPointerException if no value is present and
* {@code exceptionSupplier} is null
*/
public<X extends Throwable> long orElseThrow(Supplier<X> exceptionSupplier) throws X {
if (isPresent) {
return value;
} else {
throw exceptionSupplier.get();
}
}
/**
* Indicates whether some other object is "equal to" this 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 value of the present value, if any, or 0 (zero) if
* no value is present.
*
* @return hash code value of the present value or 0 if no value is present
*/
@Override
public int hashCode() {
return isPresent ? Long.hashCode(value) : 0;
}
/**
* {@inheritDoc}
*
* 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.
*
* @implSpec If a value is present the result must include its string
* representation in the result. Empty and present instances 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,906 @@
/*
* Copyright (c) 2003, 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 sun.misc.SharedSecrets;
/**
* 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()} is <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}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @since 1.5
* @author Josh Bloch, Doug Lea
* @param <E> the type of elements held in this collection
*/
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.
*/
private int size = 0;
/**
* 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 = 0; // 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.getClass() != ArrayList.class)
a = Arrays.copyOf(a, a.length, Object[].class);
int len = a.length;
if (len == 1 || this.comparator != null)
for (int i = 0; i < len; i++)
if (a[i] == 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);
size = i + 1;
if (i == 0)
queue[0] = e;
else
siftUp(i, e);
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) != -1;
}
/**
* 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 = 0;
/**
* 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 = null;
/**
* Element returned by the most recent call to next iff that
* element was drawn from the forgetMeNot list.
*/
private E lastRetElt = null;
/**
* 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;
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")
private 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.
*/
@SuppressWarnings("unchecked")
private void heapify() {
for (int i = (size >>> 1) - 1; i >= 0; i--)
siftDown(i, (E) queue[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).
*
* @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.
* @param s the stream
*/
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
*/
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();
SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, size);
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.
*
* <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<E>(this, 0, -1, 0);
}
static final class PriorityQueueSpliterator<E> implements Spliterator<E> {
/*
* This is very similar to ArrayList Spliterator, except for
* extra null checks.
*/
private final PriorityQueue<E> pq;
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(PriorityQueue<E> pq, int origin, int fence,
int expectedModCount) {
this.pq = pq;
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 = pq.modCount;
hi = fence = pq.size;
}
return hi;
}
public PriorityQueueSpliterator<E> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null :
new PriorityQueueSpliterator<E>(pq, lo, index = mid,
expectedModCount);
}
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> action) {
int i, hi, mc; // hoist accesses and checks from loop
PriorityQueue<E> q; Object[] a;
if (action == null)
throw new NullPointerException();
if ((q = pq) != null && (a = q.queue) != null) {
if ((hi = fence) < 0) {
mc = q.modCount;
hi = q.size;
}
else
mc = expectedModCount;
if ((i = index) >= 0 && (index = hi) <= a.length) {
for (E e;; ++i) {
if (i < hi) {
if ((e = (E) a[i]) == null) // must be CME
break;
action.accept(e);
}
else if (q.modCount != mc)
break;
else
return;
}
}
}
throw new ConcurrentModificationException();
}
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
int hi = getFence(), lo = index;
if (lo >= 0 && lo < hi) {
index = lo + 1;
@SuppressWarnings("unchecked") E e = (E)pq.queue[lo];
if (e == null)
throw new ConcurrentModificationException();
action.accept(e);
if (pq.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
public long estimateSize() {
return (long) (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,657 @@
/*
* 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.Serializable;
import java.io.IOException;
import java.security.*;
import java.util.Map;
import java.util.HashMap;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Collections;
import java.io.ObjectStreamField;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
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 final static int READ = 0x1;
/**
* Write action.
*/
private final static int WRITE = 0x2;
/**
* All actions (read,write);
*/
private final static int ALL = READ|WRITE;
/**
* No actions.
*/
private final static 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));
}
/**
* 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.
*/
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.
* <P>
* @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.
*/
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.
*/
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) {
StringBuilder sb = new StringBuilder();
boolean comma = false;
if ((mask & READ) == READ) {
comma = true;
sb.append("read");
}
if ((mask & WRITE) == WRITE) {
if (comma) sb.append(',');
else comma = true;
sb.append("write");
}
return sb.toString();
}
/**
* 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.
*/
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.
* <p>
*
* @return a new PermissionCollection object suitable for storing
* PropertyPermissions.
*/
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 Map<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 HashMap<>(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
*/
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();
synchronized (this) {
PropertyPermission existing = perms.get(propName);
if (existing != null) {
int oldMask = existing.getMask();
int newMask = pp.getMask();
if (oldMask != newMask) {
int effective = oldMask | newMask;
String actions = PropertyPermission.getActions(effective);
perms.put(propName, new PropertyPermission(propName, actions));
}
} else {
perms.put(propName, pp);
}
}
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.
*/
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) {
synchronized (this) {
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);
synchronized (this) {
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);
synchronized (this) {
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.
*/
@SuppressWarnings("unchecked")
public Enumeration<Permission> elements() {
// Convert Iterator of Map values into an Enumeration
synchronized (this) {
/**
* Casting to rawtype since Enumeration<PropertyPermission>
* cannot be directly cast to Enumeration<Permission>
*/
return (Enumeration)Collections.enumeration(perms.values());
}
}
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);
synchronized (this) {
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 HashMap<>(permissions.size()*2);
perms.putAll(permissions);
}
}

View File

@@ -0,0 +1,201 @@
/*
* Copyright (c) 1996, 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.
*/
/*
* (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.Reader;
import java.io.IOException;
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(java.lang.String, java.util.Locale, java.lang.ClassLoader) ResourceBundle.getBundle}
* for a complete description of the search and instantiation strategy.
*
* <p>
* The following <a name="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>
*
* <p>
* 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.
*
* <p>
* <strong>Note:</strong> PropertyResourceBundle can be constructed either
* from an InputStream or a Reader, which represents a property file.
* Constructing a PropertyResourceBundle instance from an InputStream requires
* that the input stream be encoded in ISO-8859-1. In that case, 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 Reader does not have that limitation.
*
* @see ResourceBundle
* @see ListResourceBundle
* @see Properties
* @since JDK1.1
*/
public class PropertyResourceBundle extends ResourceBundle {
/**
* Creates a property resource bundle from an {@link java.io.InputStream
* InputStream}. The property file read with this constructor
* must be encoded in ISO-8859-1.
*
* @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.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public PropertyResourceBundle (InputStream stream) throws IOException {
Properties properties = new Properties();
properties.load(stream);
lookup = new HashMap(properties);
}
/**
* 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 Map<String,Object> lookup;
}

View File

@@ -0,0 +1,218 @@
/*
* 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 java.util.Collection 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 BORDER CELLPADDING=3 CELLSPACING=1>
* <caption>Summary of Queue methods</caption>
* <tr>
* <td></td>
* <td ALIGN=CENTER><em>Throws exception</em></td>
* <td ALIGN=CENTER><em>Returns special value</em></td>
* </tr>
* <tr>
* <td><b>Insert</b></td>
* <td>{@link Queue#add add(e)}</td>
* <td>{@link Queue#offer offer(e)}</td>
* </tr>
* <tr>
* <td><b>Remove</b></td>
* <td>{@link Queue#remove remove()}</td>
* <td>{@link Queue#poll poll()}</td>
* </tr>
* <tr>
* <td><b>Examine</b></td>
* <td>{@link Queue#element element()}</td>
* <td>{@link Queue#peek peek()}</td>
* </tr>
* </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}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @see java.util.Collection
* @see LinkedList
* @see PriorityQueue
* @see java.util.concurrent.LinkedBlockingQueue
* @see java.util.concurrent.BlockingQueue
* @see java.util.concurrent.ArrayBlockingQueue
* @see java.util.concurrent.LinkedBlockingQueue
* @see java.util.concurrent.PriorityBlockingQueue
* @since 1.5
* @author Doug Lea
* @param <E> the type of elements held in this collection
*/
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 <tt>List</tt> 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
* <tt>ArrayList</tt>) can produce quadratic behavior when applied to
* sequential access lists (such as <tt>LinkedList</tt>). Generic list
* algorithms are encouraged to check whether the given list is an
* <tt>instanceof</tt> 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 <tt>List</tt> implementations
* provide asymptotically linear access times if they get huge, but constant
* access times in practice. Such a <tt>List</tt> implementation
* should generally implement this interface. As a rule of thumb, a
* <tt>List</tt> 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}/../technotes/guides/collections/index.html">
* 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 <tt>true</tt> if this set contains no elements.
*
* @return <tt>true</tt> if this set contains no elements
*/
public boolean isEmpty() {
return elements == 0;
}
/**
* Returns <tt>true</tt> if this set contains the specified element.
*
* @param e element to be checked for containment in this collection
* @return <tt>true</tt> 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 <tt>true</tt> if the set changed as a result of the call
*
* @throws NullPointerException if <tt>e</tt> 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 <tt>true</tt> 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 <tt>true</tt> if this set contains all of the elements
* in the specified collection.
*
* @param c collection to be checked for containment in this set
* @return <tt>true</tt> 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 <tt>true</tt> 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 <tt>true</tt> 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 <tt>true</tt> 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
* <tt>true</tt> 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 <tt>true</tt> 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,87 @@
/*
* Copyright (c) 2005, 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;
/**
* Error thrown when something goes wrong while loading a service provider.
*
* <p> This error will be thrown in the following situations:
*
* <ul>
*
* <li> The format of a provider-configuration file violates the <a
* href="ServiceLoader.html#format">specification</a>; </li>
*
* <li> An {@link java.io.IOException IOException} occurs while reading a
* provider-configuration file; </li>
*
* <li> A concrete provider class named in a provider-configuration file
* cannot be found; </li>
*
* <li> A concrete provider class is not a subclass of the service class;
* </li>
*
* <li> A concrete provider class cannot be instantiated; or
*
* <li> Some other kind of error occurs. </li>
*
* </ul>
*
*
* @author Mark Reinhold
* @since 1.6
*/
public class ServiceConfigurationError
extends Error
{
private static final long serialVersionUID = 74132770414881L;
/**
* Constructs a new instance with the specified message.
*
* @param msg The message, or <tt>null</tt> 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 <tt>null</tt> if there is no message
*
* @param cause The cause, or <tt>null</tt> if the cause is nonexistent
* or unknown
*/
public ServiceConfigurationError(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -0,0 +1,586 @@
/*
* Copyright (c) 2005, 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.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* A simple service-provider loading facility.
*
* <p> A <i>service</i> is a well-known set of interfaces and (usually
* abstract) classes. A <i>service provider</i> is a specific implementation
* of a service. The classes in a provider typically implement the interfaces
* and subclass the classes defined in the service itself. Service providers
* can be installed in an implementation of the Java platform in the form of
* extensions, that is, jar files placed into any of the usual extension
* directories. Providers can also be made available by adding them to the
* application's class path or by some other platform-specific means.
*
* <p> For the purpose of loading, a service is represented by a single type,
* that is, a single interface or abstract class. (A concrete class can be
* used, but this is not recommended.) A provider of a given service contains
* one or more concrete classes that extend this <i>service type</i> with data
* and code specific to the provider. The <i>provider class</i> is typically
* not the entire provider itself but rather a proxy which contains enough
* information to decide whether the provider is able to satisfy a particular
* request together with code that can create the actual provider on demand.
* The details of provider classes tend to be highly service-specific; no
* single class or interface could possibly unify them, so no such type is
* defined here. The only requirement enforced by this facility is that
* provider classes must have a zero-argument constructor so that they can be
* instantiated during loading.
*
* <p><a name="format"> A service provider is identified by placing a
* <i>provider-configuration file</i> in the resource directory
* <tt>META-INF/services</tt>.</a> The file's name is the fully-qualified <a
* href="../lang/ClassLoader.html#name">binary name</a> of the service's type.
* The file contains a list of fully-qualified binary names of concrete
* provider classes, one per line. Space and tab characters surrounding each
* name, as well as blank lines, are ignored. The comment character is
* <tt>'#'</tt> (<tt>'&#92;u0023'</tt>,
* <font style="font-size:smaller;">NUMBER SIGN</font>); on
* each line all characters following the first comment character are ignored.
* The file must be encoded in UTF-8.
*
* <p> If a particular concrete provider class is named in more than one
* configuration file, or is named in the same configuration file more than
* once, then the duplicates are ignored. The configuration file naming a
* particular provider need not be in the same jar file or other distribution
* unit as the provider itself. The provider must be accessible from the same
* class loader that was initially queried to locate the configuration file;
* note that this is not necessarily the class loader from which the file was
* actually loaded.
*
* <p> Providers are located and instantiated lazily, that is, on demand. A
* service loader maintains a cache of the providers that have been loaded so
* far. Each invocation of the {@link #iterator iterator} method returns an
* iterator that first yields all of the elements of the cache, in
* instantiation order, and then lazily locates and instantiates any remaining
* providers, adding each one to the cache in turn. The cache can be cleared
* via the {@link #reload reload} method.
*
* <p> Service loaders always execute in the security context of the caller.
* Trusted system code should typically invoke the methods in this class, and
* the methods of the iterators which they return, from within a privileged
* security context.
*
* <p> Instances of this class are not safe for use by multiple concurrent
* threads.
*
* <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
* method in this class will cause a {@link NullPointerException} to be thrown.
*
*
* <p><span style="font-weight: bold; padding-right: 1em">Example</span>
* Suppose we have a service type <tt>com.example.CodecSet</tt> which is
* intended to represent sets of encoder/decoder pairs for some protocol. In
* this case it is an abstract class with two abstract methods:
*
* <blockquote><pre>
* public abstract Encoder getEncoder(String encodingName);
* public abstract Decoder getDecoder(String encodingName);</pre></blockquote>
*
* Each method returns an appropriate object or <tt>null</tt> if the provider
* does not support the given encoding. Typical providers support more than
* one encoding.
*
* <p> If <tt>com.example.impl.StandardCodecs</tt> is an implementation of the
* <tt>CodecSet</tt> service then its jar file also contains a file named
*
* <blockquote><pre>
* META-INF/services/com.example.CodecSet</pre></blockquote>
*
* <p> This file contains the single line:
*
* <blockquote><pre>
* com.example.impl.StandardCodecs # Standard codecs</pre></blockquote>
*
* <p> The <tt>CodecSet</tt> class creates and saves a single service instance
* at initialization:
*
* <blockquote><pre>
* private static ServiceLoader&lt;CodecSet&gt; codecSetLoader
* = ServiceLoader.load(CodecSet.class);</pre></blockquote>
*
* <p> To locate an encoder for a given encoding name it defines a static
* factory method which iterates through the known and available providers,
* returning only when it has located a suitable encoder or has run out of
* providers.
*
* <blockquote><pre>
* public static Encoder getEncoder(String encodingName) {
* for (CodecSet cp : codecSetLoader) {
* Encoder enc = cp.getEncoder(encodingName);
* if (enc != null)
* return enc;
* }
* return null;
* }</pre></blockquote>
*
* <p> A <tt>getDecoder</tt> method is defined similarly.
*
*
* <p><span style="font-weight: bold; padding-right: 1em">Usage Note</span> If
* the class path of a class loader that is used for provider loading includes
* remote network URLs then those URLs will be dereferenced in the process of
* searching for provider-configuration files.
*
* <p> This activity is normal, although it may cause puzzling entries to be
* created in web-server logs. If a web server is not configured correctly,
* however, then this activity may cause the provider-loading algorithm to fail
* spuriously.
*
* <p> A web server should return an HTTP 404 (Not Found) response when a
* requested resource does not exist. Sometimes, however, web servers are
* erroneously configured to return an HTTP 200 (OK) response along with a
* helpful HTML error page in such cases. This will cause a {@link
* ServiceConfigurationError} to be thrown when this class attempts to parse
* the HTML page as a provider-configuration file. The best solution to this
* problem is to fix the misconfigured web server to return the correct
* response code (HTTP 404) along with the HTML error page.
*
* @param <S>
* The type of the service to be loaded by this loader
*
* @author Mark Reinhold
* @since 1.6
*/
public final class ServiceLoader<S>
implements Iterable<S>
{
private static final String PREFIX = "META-INF/services/";
// The class or interface representing the service being loaded
private final Class<S> service;
// The class loader used to locate, load, and instantiate providers
private final ClassLoader loader;
// The access control context taken when the ServiceLoader is created
private final AccessControlContext acc;
// Cached providers, in instantiation order
private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
// The current lazy-lookup iterator
private LazyIterator lookupIterator;
/**
* Clear this loader's provider cache so that all providers will be
* reloaded.
*
* <p> After invoking this method, subsequent invocations of the {@link
* #iterator() iterator} method will lazily look up and instantiate
* providers from scratch, just as is done by a newly-created loader.
*
* <p> This method is intended for use in situations in which new providers
* can be installed into a running Java virtual machine.
*/
public void reload() {
providers.clear();
lookupIterator = new LazyIterator(service, loader);
}
private ServiceLoader(Class<S> svc, ClassLoader cl) {
service = Objects.requireNonNull(svc, "Service interface cannot be null");
loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
reload();
}
private static void fail(Class<?> service, String msg, Throwable cause)
throws ServiceConfigurationError
{
throw new ServiceConfigurationError(service.getName() + ": " + msg,
cause);
}
private static void fail(Class<?> service, String msg)
throws ServiceConfigurationError
{
throw new ServiceConfigurationError(service.getName() + ": " + msg);
}
private static void fail(Class<?> service, URL u, int line, String msg)
throws ServiceConfigurationError
{
fail(service, u + ":" + line + ": " + msg);
}
// Parse a single line from the given configuration file, adding the name
// on the line to the names list.
//
private int parseLine(Class<?> service, URL u, BufferedReader r, int lc,
List<String> names)
throws IOException, ServiceConfigurationError
{
String ln = r.readLine();
if (ln == null) {
return -1;
}
int ci = ln.indexOf('#');
if (ci >= 0) ln = ln.substring(0, ci);
ln = ln.trim();
int n = ln.length();
if (n != 0) {
if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
fail(service, u, lc, "Illegal configuration-file syntax");
int cp = ln.codePointAt(0);
if (!Character.isJavaIdentifierStart(cp))
fail(service, u, lc, "Illegal provider-class name: " + ln);
for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
cp = ln.codePointAt(i);
if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
fail(service, u, lc, "Illegal provider-class name: " + ln);
}
if (!providers.containsKey(ln) && !names.contains(ln))
names.add(ln);
}
return lc + 1;
}
// Parse the content of the given URL as a provider-configuration file.
//
// @param service
// The service type for which providers are being sought;
// used to construct error detail strings
//
// @param u
// The URL naming the configuration file to be parsed
//
// @return A (possibly empty) iterator that will yield the provider-class
// names in the given configuration file that are not yet members
// of the returned set
//
// @throws ServiceConfigurationError
// If an I/O error occurs while reading from the given URL, or
// if a configuration-file format error is detected
//
private Iterator<String> parse(Class<?> service, URL u)
throws ServiceConfigurationError
{
InputStream in = null;
BufferedReader r = null;
ArrayList<String> names = new ArrayList<>();
try {
in = u.openStream();
r = new BufferedReader(new InputStreamReader(in, "utf-8"));
int lc = 1;
while ((lc = parseLine(service, u, r, lc, names)) >= 0);
} catch (IOException x) {
fail(service, "Error reading configuration file", x);
} finally {
try {
if (r != null) r.close();
if (in != null) in.close();
} catch (IOException y) {
fail(service, "Error closing configuration file", y);
}
}
return names.iterator();
}
// Private inner class implementing fully-lazy provider lookup
//
private class LazyIterator
implements Iterator<S>
{
Class<S> service;
ClassLoader loader;
Enumeration<URL> configs = null;
Iterator<String> pending = null;
String nextName = null;
private LazyIterator(Class<S> service, ClassLoader loader) {
this.service = service;
this.loader = loader;
}
private boolean hasNextService() {
if (nextName != null) {
return true;
}
if (configs == null) {
try {
String fullName = PREFIX + service.getName();
if (loader == null)
configs = ClassLoader.getSystemResources(fullName);
else
configs = loader.getResources(fullName);
} catch (IOException x) {
fail(service, "Error locating configuration files", x);
}
}
while ((pending == null) || !pending.hasNext()) {
if (!configs.hasMoreElements()) {
return false;
}
pending = parse(service, configs.nextElement());
}
nextName = pending.next();
return true;
}
private S nextService() {
if (!hasNextService())
throw new NoSuchElementException();
String cn = nextName;
nextName = null;
Class<?> c = null;
try {
c = Class.forName(cn, false, loader);
} catch (ClassNotFoundException x) {
fail(service,
"Provider " + cn + " not found");
}
if (!service.isAssignableFrom(c)) {
fail(service,
"Provider " + cn + " not a subtype");
}
try {
S p = service.cast(c.newInstance());
providers.put(cn, p);
return p;
} catch (Throwable x) {
fail(service,
"Provider " + cn + " could not be instantiated",
x);
}
throw new Error(); // This cannot happen
}
public boolean hasNext() {
if (acc == null) {
return hasNextService();
} else {
PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
public Boolean run() { return hasNextService(); }
};
return AccessController.doPrivileged(action, acc);
}
}
public S next() {
if (acc == null) {
return nextService();
} else {
PrivilegedAction<S> action = new PrivilegedAction<S>() {
public S run() { return nextService(); }
};
return AccessController.doPrivileged(action, acc);
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
/**
* Lazily loads the available providers of this loader's service.
*
* <p> The iterator returned by this method first yields all of the
* elements of the provider cache, in instantiation order. It then lazily
* loads and instantiates any remaining providers, adding each one to the
* cache in turn.
*
* <p> To achieve laziness the actual work of parsing the available
* provider-configuration files and instantiating providers must be done by
* the iterator itself. Its {@link java.util.Iterator#hasNext hasNext} and
* {@link java.util.Iterator#next next} methods can therefore throw a
* {@link ServiceConfigurationError} if a provider-configuration file
* violates the specified format, or if it names a provider class that
* cannot be found and instantiated, or if the result of instantiating the
* class is not assignable to the service type, or if any other kind of
* exception or error is thrown as the next provider is located and
* instantiated. To write robust code it is only necessary to catch {@link
* ServiceConfigurationError} when using a service iterator.
*
* <p> If such an error is thrown then subsequent invocations of the
* iterator will make a best effort to locate and instantiate the next
* available provider, but in general such recovery cannot be guaranteed.
*
* <blockquote style="font-size: smaller; line-height: 1.2"><span
* style="padding-right: 1em; font-weight: bold">Design Note</span>
* Throwing an error in these cases may seem extreme. The rationale for
* this behavior is that a malformed provider-configuration file, like a
* malformed class file, indicates a serious problem with the way the Java
* virtual machine is configured or is being used. As such it is
* preferable to throw an error rather than try to recover or, even worse,
* fail silently.</blockquote>
*
* <p> The iterator returned by this method does not support removal.
* Invoking its {@link java.util.Iterator#remove() remove} method will
* cause an {@link UnsupportedOperationException} to be thrown.
*
* @implNote When adding providers to the cache, the {@link #iterator
* Iterator} processes resources in the order that the {@link
* java.lang.ClassLoader#getResources(java.lang.String)
* ClassLoader.getResources(String)} method finds the service configuration
* files.
*
* @return An iterator that lazily loads providers for this loader's
* service
*/
public Iterator<S> iterator() {
return new Iterator<S>() {
Iterator<Map.Entry<String,S>> knownProviders
= providers.entrySet().iterator();
public boolean hasNext() {
if (knownProviders.hasNext())
return true;
return lookupIterator.hasNext();
}
public S next() {
if (knownProviders.hasNext())
return knownProviders.next().getValue();
return lookupIterator.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Creates a new service loader for the given service type and class
* loader.
*
* @param <S> the class of the service type
*
* @param service
* The interface or abstract class representing the service
*
* @param loader
* The class loader to be used to load provider-configuration files
* and provider classes, or <tt>null</tt> if the system class
* loader (or, failing that, the bootstrap class loader) is to be
* used
*
* @return A new service loader
*/
public static <S> ServiceLoader<S> load(Class<S> service,
ClassLoader loader)
{
return new ServiceLoader<>(service, loader);
}
/**
* Creates a new service loader for the given service type, using the
* current thread's {@linkplain java.lang.Thread#getContextClassLoader
* context class loader}.
*
* <p> An invocation of this convenience method of the form
*
* <blockquote><pre>
* ServiceLoader.load(<i>service</i>)</pre></blockquote>
*
* is equivalent to
*
* <blockquote><pre>
* ServiceLoader.load(<i>service</i>,
* Thread.currentThread().getContextClassLoader())</pre></blockquote>
*
* @param <S> the class of the service type
*
* @param service
* The interface or abstract class representing the service
*
* @return A new service loader
*/
public static <S> ServiceLoader<S> load(Class<S> service) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
return ServiceLoader.load(service, cl);
}
/**
* Creates a new service loader for the given service type, using the
* extension class loader.
*
* <p> This convenience method simply locates the extension class loader,
* call it <tt><i>extClassLoader</i></tt>, and then returns
*
* <blockquote><pre>
* ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
*
* <p> If the extension class loader cannot be found then the system class
* loader is used; if there is no system class loader then the bootstrap
* class loader is used.
*
* <p> This method is intended for use when only installed providers are
* desired. The resulting service will only find and load providers that
* have been installed into the current Java virtual machine; providers on
* the application's class path will be ignored.
*
* @param <S> the class of the service type
*
* @param service
* The interface or abstract class representing the service
*
* @return A new service loader
*/
public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
ClassLoader cl = ClassLoader.getSystemClassLoader();
ClassLoader prev = null;
while (cl != null) {
prev = cl;
cl = cl.getParent();
}
return ServiceLoader.load(service, prev);
}
/**
* Returns a string describing this service.
*
* @return A descriptive string
*/
public String toString() {
return "java.util.ServiceLoader[" + service.getName() + "]";
}
}

View File

@@ -0,0 +1,413 @@
/*
* 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;
/**
* A collection that contains no duplicate elements. More formally, sets
* contain no pair of elements <code>e1</code> and <code>e2</code> such that
* <code>e1.equals(e2)</code>, and at most one null element. As implied by
* its name, this interface models the mathematical <i>set</i> abstraction.
*
* <p>The <tt>Set</tt> interface places additional stipulations, beyond those
* inherited from the <tt>Collection</tt> interface, on the contracts of all
* constructors and on the contracts of the <tt>add</tt>, <tt>equals</tt> and
* <tt>hashCode</tt> methods. Declarations for other inherited methods are
* also included here for convenience. (The specifications accompanying these
* declarations have been tailored to the <tt>Set</tt> 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 <tt>equals</tt> 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
* <tt>NullPointerException</tt> or <tt>ClassCastException</tt>. 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.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* 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 <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
*
* @return the number of elements in this set (its cardinality)
*/
int size();
/**
* Returns <tt>true</tt> if this set contains no elements.
*
* @return <tt>true</tt> if this set contains no elements
*/
boolean isEmpty();
/**
* Returns <tt>true</tt> if this set contains the specified element.
* More formally, returns <tt>true</tt> if and only if this set
* contains an element <tt>e</tt> such that
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
*
* @param o element whose presence in this set is to be tested
* @return <tt>true</tt> 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
* <tt>null</tt>. (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 <tt>x</tt> is a set known to contain only strings.
* The following code can be used to dump the set into a newly allocated
* array of <tt>String</tt>:
*
* <pre>
* String[] y = x.toArray(new String[0]);</pre>
*
* Note that <tt>toArray(new Object[0])</tt> is identical in function to
* <tt>toArray()</tt>.
*
* @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
* <tt>e</tt> to this set if the set contains no element <tt>e2</tt>
* such that
* <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
* If this set already contains the element, the call leaves the set
* unchanged and returns <tt>false</tt>. 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
* <tt>null</tt>, 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 <tt>true</tt> if this set did not already contain the specified
* element
* @throws UnsupportedOperationException if the <tt>add</tt> 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 <tt>e</tt>
* such that
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>, if
* this set contains such an element. Returns <tt>true</tt> 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 <tt>true</tt> 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 <tt>remove</tt> operation
* is not supported by this set
*/
boolean remove(Object o);
// Bulk Operations
/**
* Returns <tt>true</tt> if this set contains all of the elements of the
* specified collection. If the specified collection is also a set, this
* method returns <tt>true</tt> if it is a <i>subset</i> of this set.
*
* @param c collection to be checked for containment in this set
* @return <tt>true</tt> 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 <tt>addAll</tt> 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 <tt>true</tt> if this set changed as a result of the call
*
* @throws UnsupportedOperationException if the <tt>addAll</tt> 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 <tt>true</tt> if this set changed as a result of the call
* @throws UnsupportedOperationException if the <tt>retainAll</tt> 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 <tt>true</tt> if this set changed as a result of the call
* @throws UnsupportedOperationException if the <tt>removeAll</tt> 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 <tt>clear</tt> method
* is not supported by this set
*/
void clear();
// Comparison and hashing
/**
* Compares the specified object with this set for equality. Returns
* <tt>true</tt> 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 <tt>true</tt> 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 <tt>null</tt> element is defined to be zero.
* This ensures that <tt>s1.equals(s2)</tt> implies that
* <tt>s1.hashCode()==s2.hashCode()</tt> for any two sets <tt>s1</tt>
* and <tt>s2</tt>, 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);
}
}

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}/../technotes/guides/collections/index.html">
* 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 <tt>Comparable</tt>
* interface (or be accepted by the specified comparator). Furthermore, all
* such elements must be <i>mutually comparable</i>: <tt>e1.compareTo(e2)</tt>
* (or <tt>comparator.compare(e1, e2)</tt>) must not throw a
* <tt>ClassCastException</tt> for any elements <tt>e1</tt> and <tt>e2</tt> in
* the sorted set. Attempts to violate this restriction will cause the
* offending method or constructor invocation to throw a
* <tt>ClassCastException</tt>.
*
* <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 <tt>Set</tt> interface. (See
* the <tt>Comparable</tt> interface or <tt>Comparator</tt> interface for a
* precise definition of <i>consistent with equals</i>.) This is so because
* the <tt>Set</tt> interface is defined in terms of the <tt>equals</tt>
* operation, but a sorted set performs all element comparisons using its
* <tt>compareTo</tt> (or <tt>compare</tt>) 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 <tt>Set</tt> 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 <tt>Comparator</tt>, which creates an empty
* sorted set sorted according to the specified comparator. 3) A
* constructor with a single argument of type <tt>Collection</tt>,
* 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 <tt>SortedSet</tt>,
* 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 <tt>lowEndpoint</tt> to
* <tt>successor(highEndpoint)</tt>. For example, suppose that <tt>s</tt>
* is a sorted set of strings. The following idiom obtains a view
* containing all of the strings in <tt>s</tt> from <tt>low</tt> to
* <tt>high</tt>, 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 <tt>s</tt> from <tt>low</tt> to
* <tt>high</tt>, exclusive:<pre>
* SortedSet&lt;String&gt; sub = s.subSet(low+"\0", high);</pre>
*
* <p>This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* 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 <tt>null</tt> if this set uses the {@linkplain Comparable
* natural ordering} of its elements.
*
* @return the comparator used to order the elements in this set,
* or <tt>null</tt> 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 <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
* exclusive. (If <tt>fromElement</tt> and <tt>toElement</tt> 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 <tt>IllegalArgumentException</tt>
* 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
* <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive
* @throws ClassCastException if <tt>fromElement</tt> and
* <tt>toElement</tt> 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 <tt>fromElement</tt> or
* <tt>toElement</tt> cannot be compared to elements currently in
* the set.
* @throws NullPointerException if <tt>fromElement</tt> or
* <tt>toElement</tt> is null and this set does not permit null
* elements
* @throws IllegalArgumentException if <tt>fromElement</tt> is
* greater than <tt>toElement</tt>; or if this set itself
* has a restricted range, and <tt>fromElement</tt> or
* <tt>toElement</tt> 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 <tt>toElement</tt>. 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 <tt>IllegalArgumentException</tt>
* 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 <tt>toElement</tt>
* @throws ClassCastException if <tt>toElement</tt> is not compatible
* with this set's comparator (or, if the set has no comparator,
* if <tt>toElement</tt> does not implement {@link Comparable}).
* Implementations may, but are not required to, throw this
* exception if <tt>toElement</tt> cannot be compared to elements
* currently in the set.
* @throws NullPointerException if <tt>toElement</tt> is null and
* this set does not permit null elements
* @throws IllegalArgumentException if this set itself has a
* restricted range, and <tt>toElement</tt> 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 <tt>fromElement</tt>. 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 <tt>IllegalArgumentException</tt>
* 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 <tt>fromElement</tt>
* @throws ClassCastException if <tt>fromElement</tt> is not compatible
* with this set's comparator (or, if the set has no comparator,
* if <tt>fromElement</tt> does not implement {@link Comparable}).
* Implementations may, but are not required to, throw this
* exception if <tt>fromElement</tt> cannot be compared to elements
* currently in the set.
* @throws NullPointerException if <tt>fromElement</tt> is null
* and this set does not permit null elements
* @throws IllegalArgumentException if this set itself has a
* restricted range, and <tt>fromElement</tt> 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();
}
};
}
}

View File

@@ -0,0 +1,832 @@
/*
* 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;
/**
* An object for traversing and partitioning elements of a source. The source
* of elements covered by a Spliterator could be, for example, an array, a
* {@link Collection}, an IO channel, or a generator function.
*
* <p>A Spliterator may traverse elements individually ({@link
* #tryAdvance tryAdvance()}) or sequentially in bulk
* ({@link #forEachRemaining forEachRemaining()}).
*
* <p>A Spliterator may also partition off some of its elements (using
* {@link #trySplit}) as another Spliterator, to be used in
* possibly-parallel operations. Operations using a Spliterator that
* cannot split, or does so in a highly imbalanced or inefficient
* manner, are unlikely to benefit from parallelism. Traversal
* and splitting exhaust elements; each Spliterator is useful for only a single
* bulk computation.
*
* <p>A Spliterator also reports a set of {@link #characteristics()} of its
* structure, source, and elements from among {@link #ORDERED},
* {@link #DISTINCT}, {@link #SORTED}, {@link #SIZED}, {@link #NONNULL},
* {@link #IMMUTABLE}, {@link #CONCURRENT}, and {@link #SUBSIZED}. These may
* be employed by Spliterator clients to control, specialize or simplify
* computation. For example, a Spliterator for a {@link Collection} would
* report {@code SIZED}, a Spliterator for a {@link Set} would report
* {@code DISTINCT}, and a Spliterator for a {@link SortedSet} would also
* report {@code SORTED}. Characteristics are reported as a simple unioned bit
* set.
*
* Some characteristics additionally constrain method behavior; for example if
* {@code ORDERED}, traversal methods must conform to their documented ordering.
* New characteristics may be defined in the future, so implementors should not
* assign meanings to unlisted values.
*
* <p><a name="binding">A Spliterator that does not report {@code IMMUTABLE} or
* {@code CONCURRENT} is expected to have a documented policy concerning:
* when the spliterator <em>binds</em> to the element source; and detection of
* structural interference of the element source detected after binding.</a> A
* <em>late-binding</em> Spliterator binds to the source of elements at the
* point of first traversal, first split, or first query for estimated size,
* rather than at the time the Spliterator is created. A Spliterator that is
* not <em>late-binding</em> binds to the source of elements at the point of
* construction or first invocation of any method. Modifications made to the
* source prior to binding are reflected when the Spliterator is traversed.
* After binding a Spliterator should, on a best-effort basis, throw
* {@link ConcurrentModificationException} if structural interference is
* detected. Spliterators that do this are called <em>fail-fast</em>. The
* bulk traversal method ({@link #forEachRemaining forEachRemaining()}) of a
* Spliterator may optimize traversal and check for structural interference
* after all elements have been traversed, rather than checking per-element and
* failing immediately.
*
* <p>Spliterators can provide an estimate of the number of remaining elements
* via the {@link #estimateSize} method. Ideally, as reflected in characteristic
* {@link #SIZED}, this value corresponds exactly to the number of elements
* that would be encountered in a successful traversal. However, even when not
* exactly known, an estimated value value may still be useful to operations
* being performed on the source, such as helping to determine whether it is
* preferable to split further or traverse the remaining elements sequentially.
*
* <p>Despite their obvious utility in parallel algorithms, spliterators are not
* expected to be thread-safe; instead, implementations of parallel algorithms
* using spliterators should ensure that the spliterator is only used by one
* thread at a time. This is generally easy to attain via <em>serial
* thread-confinement</em>, which often is a natural consequence of typical
* parallel algorithms that work by recursive decomposition. A thread calling
* {@link #trySplit()} may hand over the returned Spliterator to another thread,
* which in turn may traverse or further split that Spliterator. The behaviour
* of splitting and traversal is undefined if two or more threads operate
* concurrently on the same spliterator. If the original thread hands a
* spliterator off to another thread for processing, it is best if that handoff
* occurs before any elements are consumed with {@link #tryAdvance(Consumer)
* tryAdvance()}, as certain guarantees (such as the accuracy of
* {@link #estimateSize()} for {@code SIZED} spliterators) are only valid before
* traversal has begun.
*
* <p>Primitive subtype specializations of {@code Spliterator} are provided for
* {@link OfInt int}, {@link OfLong long}, and {@link OfDouble double} values.
* The subtype default implementations of
* {@link Spliterator#tryAdvance(java.util.function.Consumer)}
* and {@link Spliterator#forEachRemaining(java.util.function.Consumer)} box
* primitive values to instances of their corresponding wrapper class. Such
* boxing may undermine any performance advantages gained by using the primitive
* specializations. To avoid boxing, the corresponding primitive-based methods
* should be used. For example,
* {@link Spliterator.OfInt#tryAdvance(java.util.function.IntConsumer)}
* and {@link Spliterator.OfInt#forEachRemaining(java.util.function.IntConsumer)}
* should be used in preference to
* {@link Spliterator.OfInt#tryAdvance(java.util.function.Consumer)} and
* {@link Spliterator.OfInt#forEachRemaining(java.util.function.Consumer)}.
* Traversal of primitive values using boxing-based methods
* {@link #tryAdvance tryAdvance()} and
* {@link #forEachRemaining(java.util.function.Consumer) forEachRemaining()}
* does not affect the order in which the values, transformed to boxed values,
* are encountered.
*
* @apiNote
* <p>Spliterators, like {@code Iterator}s, are for traversing the elements of
* a source. The {@code Spliterator} API was designed to support efficient
* parallel traversal in addition to sequential traversal, by supporting
* decomposition as well as single-element iteration. In addition, the
* protocol for accessing elements via a Spliterator is designed to impose
* smaller per-element overhead than {@code Iterator}, and to avoid the inherent
* race involved in having separate methods for {@code hasNext()} and
* {@code next()}.
*
* <p>For mutable sources, arbitrary and non-deterministic behavior may occur if
* the source is structurally interfered with (elements added, replaced, or
* removed) between the time that the Spliterator binds to its data source and
* the end of traversal. For example, such interference will produce arbitrary,
* non-deterministic results when using the {@code java.util.stream} framework.
*
* <p>Structural interference of a source can be managed in the following ways
* (in approximate order of decreasing desirability):
* <ul>
* <li>The source cannot be structurally interfered with.
* <br>For example, an instance of
* {@link java.util.concurrent.CopyOnWriteArrayList} is an immutable source.
* A Spliterator created from the source reports a characteristic of
* {@code IMMUTABLE}.</li>
* <li>The source manages concurrent modifications.
* <br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
* is a concurrent source. A Spliterator created from the source reports a
* characteristic of {@code CONCURRENT}.</li>
* <li>The mutable source provides a late-binding and fail-fast Spliterator.
* <br>Late binding narrows the window during which interference can affect
* the calculation; fail-fast detects, on a best-effort basis, that structural
* interference has occurred after traversal has commenced and throws
* {@link ConcurrentModificationException}. For example, {@link ArrayList},
* and many other non-concurrent {@code Collection} classes in the JDK, provide
* a late-binding, fail-fast spliterator.</li>
* <li>The mutable source provides a non-late-binding but fail-fast Spliterator.
* <br>The source increases the likelihood of throwing
* {@code ConcurrentModificationException} since the window of potential
* interference is larger.</li>
* <li>The mutable source provides a late-binding and non-fail-fast Spliterator.
* <br>The source risks arbitrary, non-deterministic behavior after traversal
* has commenced since interference is not detected.
* </li>
* <li>The mutable source provides a non-late-binding and non-fail-fast
* Spliterator.
* <br>The source increases the risk of arbitrary, non-deterministic behavior
* since non-detected interference may occur after construction.
* </li>
* </ul>
*
* <p><b>Example.</b> Here is a class (not a very useful one, except
* for illustration) that maintains an array in which the actual data
* are held in even locations, and unrelated tag data are held in odd
* locations. Its Spliterator ignores the tags.
*
* <pre> {@code
* class TaggedArray<T> {
* private final Object[] elements; // immutable after construction
* TaggedArray(T[] data, Object[] tags) {
* int size = data.length;
* if (tags.length != size) throw new IllegalArgumentException();
* this.elements = new Object[2 * size];
* for (int i = 0, j = 0; i < size; ++i) {
* elements[j++] = data[i];
* elements[j++] = tags[i];
* }
* }
*
* public Spliterator<T> spliterator() {
* return new TaggedArraySpliterator<>(elements, 0, elements.length);
* }
*
* static class TaggedArraySpliterator<T> implements Spliterator<T> {
* private final Object[] array;
* private int origin; // current index, advanced on split or traversal
* private final int fence; // one past the greatest index
*
* TaggedArraySpliterator(Object[] array, int origin, int fence) {
* this.array = array; this.origin = origin; this.fence = fence;
* }
*
* public void forEachRemaining(Consumer<? super T> action) {
* for (; origin < fence; origin += 2)
* action.accept((T) array[origin]);
* }
*
* public boolean tryAdvance(Consumer<? super T> action) {
* if (origin < fence) {
* action.accept((T) array[origin]);
* origin += 2;
* return true;
* }
* else // cannot advance
* return false;
* }
*
* public Spliterator<T> trySplit() {
* int lo = origin; // divide range in half
* int mid = ((lo + fence) >>> 1) & ~1; // force midpoint to be even
* if (lo < mid) { // split out left half
* origin = mid; // reset this Spliterator's origin
* return new TaggedArraySpliterator<>(array, lo, mid);
* }
* else // too small to split
* return null;
* }
*
* public long estimateSize() {
* return (long)((fence - origin) / 2);
* }
*
* public int characteristics() {
* return ORDERED | SIZED | IMMUTABLE | SUBSIZED;
* }
* }
* }}</pre>
*
* <p>As an example how a parallel computation framework, such as the
* {@code java.util.stream} package, would use Spliterator in a parallel
* computation, here is one way to implement an associated parallel forEach,
* that illustrates the primary usage idiom of splitting off subtasks until
* the estimated amount of work is small enough to perform
* sequentially. Here we assume that the order of processing across
* subtasks doesn't matter; different (forked) tasks may further split
* and process elements concurrently in undetermined order. This
* example uses a {@link java.util.concurrent.CountedCompleter};
* similar usages apply to other parallel task constructions.
*
* <pre>{@code
* static <T> void parEach(TaggedArray<T> a, Consumer<T> action) {
* Spliterator<T> s = a.spliterator();
* long targetBatchSize = s.estimateSize() / (ForkJoinPool.getCommonPoolParallelism() * 8);
* new ParEach(null, s, action, targetBatchSize).invoke();
* }
*
* static class ParEach<T> extends CountedCompleter<Void> {
* final Spliterator<T> spliterator;
* final Consumer<T> action;
* final long targetBatchSize;
*
* ParEach(ParEach<T> parent, Spliterator<T> spliterator,
* Consumer<T> action, long targetBatchSize) {
* super(parent);
* this.spliterator = spliterator; this.action = action;
* this.targetBatchSize = targetBatchSize;
* }
*
* public void compute() {
* Spliterator<T> sub;
* while (spliterator.estimateSize() > targetBatchSize &&
* (sub = spliterator.trySplit()) != null) {
* addToPendingCount(1);
* new ParEach<>(this, sub, action, targetBatchSize).fork();
* }
* spliterator.forEachRemaining(action);
* propagateCompletion();
* }
* }}</pre>
*
* @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 Spliterator
*
* @see Collection
* @since 1.8
*/
public interface Spliterator<T> {
/**
* If a remaining element exists, performs the given action on it,
* returning {@code true}; else returns {@code false}. If this
* Spliterator is {@link #ORDERED} the action is performed on the
* next element in encounter order. Exceptions thrown by the
* action are relayed to the caller.
*
* @param action The action
* @return {@code false} if no remaining elements existed
* upon entry to this method, else {@code true}.
* @throws NullPointerException if the specified action is null
*/
boolean tryAdvance(Consumer<? super T> action);
/**
* Performs the given action for each remaining element, sequentially in
* the current thread, until all elements have been processed or the action
* throws an exception. If this Spliterator is {@link #ORDERED}, actions
* are performed in encounter order. Exceptions thrown by the action
* are relayed to the caller.
*
* @implSpec
* The default implementation repeatedly invokes {@link #tryAdvance} until
* it returns {@code false}. It should be overridden whenever possible.
*
* @param action The action
* @throws NullPointerException if the specified action is null
*/
default void forEachRemaining(Consumer<? super T> action) {
do { } while (tryAdvance(action));
}
/**
* If this spliterator can be partitioned, returns a Spliterator
* covering elements, that will, upon return from this method, not
* be covered by this Spliterator.
*
* <p>If this Spliterator is {@link #ORDERED}, the returned Spliterator
* must cover a strict prefix of the elements.
*
* <p>Unless this Spliterator covers an infinite number of elements,
* repeated calls to {@code trySplit()} must eventually return {@code null}.
* Upon non-null return:
* <ul>
* <li>the value reported for {@code estimateSize()} before splitting,
* must, after splitting, be greater than or equal to {@code estimateSize()}
* for this and the returned Spliterator; and</li>
* <li>if this Spliterator is {@code SUBSIZED}, then {@code estimateSize()}
* for this spliterator before splitting must be equal to the sum of
* {@code estimateSize()} for this and the returned Spliterator after
* splitting.</li>
* </ul>
*
* <p>This method may return {@code null} for any reason,
* including emptiness, inability to split after traversal has
* commenced, data structure constraints, and efficiency
* considerations.
*
* @apiNote
* An ideal {@code trySplit} method efficiently (without
* traversal) divides its elements exactly in half, allowing
* balanced parallel computation. Many departures from this ideal
* remain highly effective; for example, only approximately
* splitting an approximately balanced tree, or for a tree in
* which leaf nodes may contain either one or two elements,
* failing to further split these nodes. However, large
* deviations in balance and/or overly inefficient {@code
* trySplit} mechanics typically result in poor parallel
* performance.
*
* @return a {@code Spliterator} covering some portion of the
* elements, or {@code null} if this spliterator cannot be split
*/
Spliterator<T> trySplit();
/**
* Returns an estimate of the number of elements that would be
* encountered by a {@link #forEachRemaining} traversal, or returns {@link
* Long#MAX_VALUE} if infinite, unknown, or too expensive to compute.
*
* <p>If this Spliterator is {@link #SIZED} and has not yet been partially
* traversed or split, or this Spliterator is {@link #SUBSIZED} and has
* not yet been partially traversed, this estimate must be an accurate
* count of elements that would be encountered by a complete traversal.
* Otherwise, this estimate may be arbitrarily inaccurate, but must decrease
* as specified across invocations of {@link #trySplit}.
*
* @apiNote
* Even an inexact estimate is often useful and inexpensive to compute.
* For example, a sub-spliterator of an approximately balanced binary tree
* may return a value that estimates the number of elements to be half of
* that of its parent; if the root Spliterator does not maintain an
* accurate count, it could estimate size to be the power of two
* corresponding to its maximum depth.
*
* @return the estimated size, or {@code Long.MAX_VALUE} if infinite,
* unknown, or too expensive to compute.
*/
long estimateSize();
/**
* Convenience method that returns {@link #estimateSize()} if this
* Spliterator is {@link #SIZED}, else {@code -1}.
* @implSpec
* The default implementation returns the result of {@code estimateSize()}
* if the Spliterator reports a characteristic of {@code SIZED}, and
* {@code -1} otherwise.
*
* @return the exact size, if known, else {@code -1}.
*/
default long getExactSizeIfKnown() {
return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
}
/**
* Returns a set of characteristics of this Spliterator and its
* elements. The result is represented as ORed values from {@link
* #ORDERED}, {@link #DISTINCT}, {@link #SORTED}, {@link #SIZED},
* {@link #NONNULL}, {@link #IMMUTABLE}, {@link #CONCURRENT},
* {@link #SUBSIZED}. Repeated calls to {@code characteristics()} on
* a given spliterator, prior to or in-between calls to {@code trySplit},
* should always return the same result.
*
* <p>If a Spliterator reports an inconsistent set of
* characteristics (either those returned from a single invocation
* or across multiple invocations), no guarantees can be made
* about any computation using this Spliterator.
*
* @apiNote The characteristics of a given spliterator before splitting
* may differ from the characteristics after splitting. For specific
* examples see the characteristic values {@link #SIZED}, {@link #SUBSIZED}
* and {@link #CONCURRENT}.
*
* @return a representation of characteristics
*/
int characteristics();
/**
* Returns {@code true} if this Spliterator's {@link
* #characteristics} contain all of the given characteristics.
*
* @implSpec
* The default implementation returns true if the corresponding bits
* of the given characteristics are set.
*
* @param characteristics the characteristics to check for
* @return {@code true} if all the specified characteristics are present,
* else {@code false}
*/
default boolean hasCharacteristics(int characteristics) {
return (characteristics() & characteristics) == characteristics;
}
/**
* If this Spliterator's source is {@link #SORTED} by a {@link Comparator},
* returns that {@code Comparator}. If the source is {@code SORTED} in
* {@linkplain Comparable natural order}, returns {@code null}. Otherwise,
* if the source is not {@code SORTED}, throws {@link IllegalStateException}.
*
* @implSpec
* The default implementation always throws {@link IllegalStateException}.
*
* @return a Comparator, or {@code null} if the elements are sorted in the
* natural order.
* @throws IllegalStateException if the spliterator does not report
* a characteristic of {@code SORTED}.
*/
default Comparator<? super T> getComparator() {
throw new IllegalStateException();
}
/**
* Characteristic value signifying that an encounter order is defined for
* elements. If so, this Spliterator guarantees that method
* {@link #trySplit} splits a strict prefix of elements, that method
* {@link #tryAdvance} steps by one element in prefix order, and that
* {@link #forEachRemaining} performs actions in encounter order.
*
* <p>A {@link Collection} has an encounter order if the corresponding
* {@link Collection#iterator} documents an order. If so, the encounter
* order is the same as the documented order. Otherwise, a collection does
* not have an encounter order.
*
* @apiNote Encounter order is guaranteed to be ascending index order for
* any {@link List}. But no order is guaranteed for hash-based collections
* such as {@link HashSet}. Clients of a Spliterator that reports
* {@code ORDERED} are expected to preserve ordering constraints in
* non-commutative parallel computations.
*/
public static final int ORDERED = 0x00000010;
/**
* Characteristic value signifying that, for each pair of
* encountered elements {@code x, y}, {@code !x.equals(y)}. This
* applies for example, to a Spliterator based on a {@link Set}.
*/
public static final int DISTINCT = 0x00000001;
/**
* Characteristic value signifying that encounter order follows a defined
* sort order. If so, method {@link #getComparator()} returns the associated
* Comparator, or {@code null} if all elements are {@link Comparable} and
* are sorted by their natural ordering.
*
* <p>A Spliterator that reports {@code SORTED} must also report
* {@code ORDERED}.
*
* @apiNote The spliterators for {@code Collection} classes in the JDK that
* implement {@link NavigableSet} or {@link SortedSet} report {@code SORTED}.
*/
public static final int SORTED = 0x00000004;
/**
* Characteristic value signifying that the value returned from
* {@code estimateSize()} prior to traversal or splitting represents a
* finite size that, in the absence of structural source modification,
* represents an exact count of the number of elements that would be
* encountered by a complete traversal.
*
* @apiNote Most Spliterators for Collections, that cover all elements of a
* {@code Collection} report this characteristic. Sub-spliterators, such as
* those for {@link HashSet}, that cover a sub-set of elements and
* approximate their reported size do not.
*/
public static final int SIZED = 0x00000040;
/**
* Characteristic value signifying that the source guarantees that
* encountered elements will not be {@code null}. (This applies,
* for example, to most concurrent collections, queues, and maps.)
*/
public static final int NONNULL = 0x00000100;
/**
* Characteristic value signifying that the element source cannot be
* structurally modified; that is, elements cannot be added, replaced, or
* removed, so such changes cannot occur during traversal. A Spliterator
* that does not report {@code IMMUTABLE} or {@code CONCURRENT} is expected
* to have a documented policy (for example throwing
* {@link ConcurrentModificationException}) concerning structural
* interference detected during traversal.
*/
public static final int IMMUTABLE = 0x00000400;
/**
* Characteristic value signifying that the element source may be safely
* concurrently modified (allowing additions, replacements, and/or removals)
* by multiple threads without external synchronization. If so, the
* Spliterator is expected to have a documented policy concerning the impact
* of modifications during traversal.
*
* <p>A top-level Spliterator should not report both {@code CONCURRENT} and
* {@code SIZED}, since the finite size, if known, may change if the source
* is concurrently modified during traversal. Such a Spliterator is
* inconsistent and no guarantees can be made about any computation using
* that Spliterator. Sub-spliterators may report {@code SIZED} if the
* sub-split size is known and additions or removals to the source are not
* reflected when traversing.
*
* @apiNote Most concurrent collections maintain a consistency policy
* guaranteeing accuracy with respect to elements present at the point of
* Spliterator construction, but possibly not reflecting subsequent
* additions or removals.
*/
public static final int CONCURRENT = 0x00001000;
/**
* Characteristic value signifying that all Spliterators resulting from
* {@code trySplit()} will be both {@link #SIZED} and {@link #SUBSIZED}.
* (This means that all child Spliterators, whether direct or indirect, will
* be {@code SIZED}.)
*
* <p>A Spliterator that does not report {@code SIZED} as required by
* {@code SUBSIZED} is inconsistent and no guarantees can be made about any
* computation using that Spliterator.
*
* @apiNote Some spliterators, such as the top-level spliterator for an
* approximately balanced binary tree, will report {@code SIZED} but not
* {@code SUBSIZED}, since it is common to know the size of the entire tree
* but not the exact sizes of subtrees.
*/
public static final int SUBSIZED = 0x00004000;
/**
* A Spliterator specialized for primitive values.
*
* @param <T> the type of elements returned by this Spliterator. 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}.
* @param <T_SPLITR> the type of primitive Spliterator. The type must be
* a primitive specialization of Spliterator for {@code T}, such as
* {@link Spliterator.OfInt} for {@code Integer}.
*
* @see Spliterator.OfInt
* @see Spliterator.OfLong
* @see Spliterator.OfDouble
* @since 1.8
*/
public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
extends Spliterator<T> {
@Override
T_SPLITR trySplit();
/**
* If a remaining element exists, performs the given action on it,
* returning {@code true}; else returns {@code false}. If this
* Spliterator is {@link #ORDERED} the action is performed on the
* next element in encounter order. Exceptions thrown by the
* action are relayed to the caller.
*
* @param action The action
* @return {@code false} if no remaining elements existed
* upon entry to this method, else {@code true}.
* @throws NullPointerException if the specified action is null
*/
@SuppressWarnings("overloads")
boolean tryAdvance(T_CONS action);
/**
* Performs the given action for each remaining element, sequentially in
* the current thread, until all elements have been processed or the
* action throws an exception. If this Spliterator is {@link #ORDERED},
* actions are performed in encounter order. Exceptions thrown by the
* action are relayed to the caller.
*
* @implSpec
* The default implementation repeatedly invokes {@link #tryAdvance}
* until it returns {@code false}. It should be overridden whenever
* possible.
*
* @param action The action
* @throws NullPointerException if the specified action is null
*/
@SuppressWarnings("overloads")
default void forEachRemaining(T_CONS action) {
do { } while (tryAdvance(action));
}
}
/**
* A Spliterator specialized for {@code int} values.
* @since 1.8
*/
public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {
@Override
OfInt trySplit();
@Override
boolean tryAdvance(IntConsumer action);
@Override
default void forEachRemaining(IntConsumer action) {
do { } while (tryAdvance(action));
}
/**
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code IntConsumer} then it is cast
* to {@code IntConsumer} and passed to
* {@link #tryAdvance(java.util.function.IntConsumer)}; otherwise
* the action is adapted to an instance of {@code IntConsumer}, by
* boxing the argument of {@code IntConsumer}, and then passed to
* {@link #tryAdvance(java.util.function.IntConsumer)}.
*/
@Override
default boolean tryAdvance(Consumer<? super Integer> action) {
if (action instanceof IntConsumer) {
return tryAdvance((IntConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfInt.tryAdvance((IntConsumer) action::accept)");
return tryAdvance((IntConsumer) action::accept);
}
}
/**
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code IntConsumer} then it is cast
* to {@code IntConsumer} and passed to
* {@link #forEachRemaining(java.util.function.IntConsumer)}; otherwise
* the action is adapted to an instance of {@code IntConsumer}, by
* boxing the argument of {@code IntConsumer}, and then passed to
* {@link #forEachRemaining(java.util.function.IntConsumer)}.
*/
@Override
default void forEachRemaining(Consumer<? super Integer> action) {
if (action instanceof IntConsumer) {
forEachRemaining((IntConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfInt.forEachRemaining((IntConsumer) action::accept)");
forEachRemaining((IntConsumer) action::accept);
}
}
}
/**
* A Spliterator specialized for {@code long} values.
* @since 1.8
*/
public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {
@Override
OfLong trySplit();
@Override
boolean tryAdvance(LongConsumer action);
@Override
default void forEachRemaining(LongConsumer action) {
do { } while (tryAdvance(action));
}
/**
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code LongConsumer} then it is cast
* to {@code LongConsumer} and passed to
* {@link #tryAdvance(java.util.function.LongConsumer)}; otherwise
* the action is adapted to an instance of {@code LongConsumer}, by
* boxing the argument of {@code LongConsumer}, and then passed to
* {@link #tryAdvance(java.util.function.LongConsumer)}.
*/
@Override
default boolean tryAdvance(Consumer<? super Long> action) {
if (action instanceof LongConsumer) {
return tryAdvance((LongConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfLong.tryAdvance((LongConsumer) action::accept)");
return tryAdvance((LongConsumer) action::accept);
}
}
/**
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code LongConsumer} then it is cast
* to {@code LongConsumer} and passed to
* {@link #forEachRemaining(java.util.function.LongConsumer)}; otherwise
* the action is adapted to an instance of {@code LongConsumer}, by
* boxing the argument of {@code LongConsumer}, and then passed to
* {@link #forEachRemaining(java.util.function.LongConsumer)}.
*/
@Override
default void forEachRemaining(Consumer<? super Long> action) {
if (action instanceof LongConsumer) {
forEachRemaining((LongConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfLong.forEachRemaining((LongConsumer) action::accept)");
forEachRemaining((LongConsumer) action::accept);
}
}
}
/**
* A Spliterator specialized for {@code double} values.
* @since 1.8
*/
public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {
@Override
OfDouble trySplit();
@Override
boolean tryAdvance(DoubleConsumer action);
@Override
default void forEachRemaining(DoubleConsumer action) {
do { } while (tryAdvance(action));
}
/**
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code DoubleConsumer} then it is
* cast to {@code DoubleConsumer} and passed to
* {@link #tryAdvance(java.util.function.DoubleConsumer)}; otherwise
* the action is adapted to an instance of {@code DoubleConsumer}, by
* boxing the argument of {@code DoubleConsumer}, and then passed to
* {@link #tryAdvance(java.util.function.DoubleConsumer)}.
*/
@Override
default boolean tryAdvance(Consumer<? super Double> action) {
if (action instanceof DoubleConsumer) {
return tryAdvance((DoubleConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfDouble.tryAdvance((DoubleConsumer) action::accept)");
return tryAdvance((DoubleConsumer) action::accept);
}
}
/**
* {@inheritDoc}
* @implSpec
* If the action is an instance of {@code DoubleConsumer} then it is
* cast to {@code DoubleConsumer} and passed to
* {@link #forEachRemaining(java.util.function.DoubleConsumer)};
* otherwise the action is adapted to an instance of
* {@code DoubleConsumer}, by boxing the argument of
* {@code DoubleConsumer}, and then passed to
* {@link #forEachRemaining(java.util.function.DoubleConsumer)}.
*/
@Override
default void forEachRemaining(Consumer<? super Double> action) {
if (action instanceof DoubleConsumer) {
forEachRemaining((DoubleConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfDouble.forEachRemaining((DoubleConsumer) action::accept)");
forEachRemaining((DoubleConsumer) action::accept);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,991 @@
/*
* 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.concurrent.atomic.AtomicLong;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
import java.util.function.DoubleConsumer;
import java.util.stream.StreamSupport;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.DoubleStream;
/**
* A generator of uniform pseudorandom values applicable for use in
* (among other contexts) isolated parallel computations that may
* generate subtasks. Class {@code SplittableRandom} supports methods for
* producing pseudorandom numbers of type {@code int}, {@code long},
* and {@code double} with similar usages as for class
* {@link java.util.Random} but differs in the following ways:
*
* <ul>
*
* <li>Series of generated values pass the DieHarder suite testing
* independence and uniformity properties of random number generators.
* (Most recently validated with <a
* href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version
* 3.31.1</a>.) These tests validate only the methods for certain
* types and ranges, but similar properties are expected to hold, at
* least approximately, for others as well. The <em>period</em>
* (length of any series of generated values before it repeats) is at
* least 2<sup>64</sup>. </li>
*
* <li> Method {@link #split} constructs and returns a new
* SplittableRandom instance that shares no mutable state with the
* current instance. However, with very high probability, the
* values collectively generated by the two objects have the same
* statistical properties as if the same quantity of values were
* generated by a single thread using a single {@code
* SplittableRandom} object. </li>
*
* <li>Instances of SplittableRandom are <em>not</em> thread-safe.
* They are designed to be split, not shared, across threads. For
* example, a {@link java.util.concurrent.ForkJoinTask
* fork/join-style} computation using random numbers might include a
* construction of the form {@code new
* Subtask(aSplittableRandom.split()).fork()}.
*
* <li>This class provides additional methods for generating random
* streams, that employ the above techniques when used in {@code
* stream.parallel()} mode.</li>
*
* </ul>
*
* <p>Instances of {@code SplittableRandom} are not cryptographically
* secure. Consider instead using {@link java.security.SecureRandom}
* in security-sensitive applications. Additionally,
* default-constructed instances do not use a cryptographically random
* seed unless the {@linkplain System#getProperty system property}
* {@code java.util.secureRandomSeed} is set to {@code true}.
*
* @author Guy Steele
* @author Doug Lea
* @since 1.8
*/
public final class SplittableRandom {
/*
* Implementation Overview.
*
* This algorithm was inspired by the "DotMix" algorithm by
* Leiserson, Schardl, and Sukha "Deterministic Parallel
* Random-Number Generation for Dynamic-Multithreading Platforms",
* PPoPP 2012, as well as those in "Parallel random numbers: as
* easy as 1, 2, 3" by Salmon, Morae, Dror, and Shaw, SC 2011. It
* differs mainly in simplifying and cheapening operations.
*
* The primary update step (method nextSeed()) is to add a
* constant ("gamma") to the current (64 bit) seed, forming a
* simple sequence. The seed and the gamma values for any two
* SplittableRandom instances are highly likely to be different.
*
* Methods nextLong, nextInt, and derivatives do not return the
* sequence (seed) values, but instead a hash-like bit-mix of
* their bits, producing more independently distributed sequences.
* For nextLong, the mix64 function is based on David Stafford's
* (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)
* "Mix13" variant of the "64-bit finalizer" function in Austin
* Appleby's MurmurHash3 algorithm (see
* http://code.google.com/p/smhasher/wiki/MurmurHash3). The mix32
* function is based on Stafford's Mix04 mix function, but returns
* the upper 32 bits cast as int.
*
* The split operation uses the current generator to form the seed
* and gamma for another SplittableRandom. To conservatively
* avoid potential correlations between seed and value generation,
* gamma selection (method mixGamma) uses different
* (Murmurhash3's) mix constants. To avoid potential weaknesses
* in bit-mixing transformations, we restrict gammas to odd values
* with at least 24 0-1 or 1-0 bit transitions. Rather than
* rejecting candidates with too few or too many bits set, method
* mixGamma flips some bits (which has the effect of mapping at
* most 4 to any given gamma value). This reduces the effective
* set of 64bit odd gamma values by about 2%, and serves as an
* automated screening for sequence constant selection that is
* left as an empirical decision in some other hashing and crypto
* algorithms.
*
* The resulting generator thus transforms a sequence in which
* (typically) many bits change on each step, with an inexpensive
* mixer with good (but less than cryptographically secure)
* avalanching.
*
* The default (no-argument) constructor, in essence, invokes
* split() for a common "defaultGen" SplittableRandom. Unlike
* other cases, this split must be performed in a thread-safe
* manner, so we use an AtomicLong to represent the seed rather
* than use an explicit SplittableRandom. To bootstrap the
* defaultGen, we start off using a seed based on current time
* unless the java.util.secureRandomSeed property is set. This
* serves as a slimmed-down (and insecure) variant of SecureRandom
* that also avoids stalls that may occur when using /dev/random.
*
* It is a relatively simple matter to apply the basic design here
* to use 128 bit seeds. However, emulating 128bit arithmetic and
* carrying around twice the state add more overhead than appears
* warranted for current usages.
*
* File organization: First the non-public methods that constitute
* the main algorithm, then the main public methods, followed by
* some custom spliterator classes needed for stream methods.
*/
/**
* The golden ratio scaled to 64bits, used as the initial gamma
* value for (unsplit) SplittableRandoms.
*/
private static final long GOLDEN_GAMMA = 0x9e3779b97f4a7c15L;
/**
* The least non-zero value returned by nextDouble(). This value
* is scaled by a random value of 53 bits to produce a result.
*/
private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53);
/**
* The seed. Updated only via method nextSeed.
*/
private long seed;
/**
* The step value.
*/
private final long gamma;
/**
* Internal constructor used by all others except default constructor.
*/
private SplittableRandom(long seed, long gamma) {
this.seed = seed;
this.gamma = gamma;
}
/**
* Computes Stafford variant 13 of 64bit mix function.
*/
private static long mix64(long z) {
z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L;
z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
return z ^ (z >>> 31);
}
/**
* Returns the 32 high bits of Stafford variant 4 mix64 function as int.
*/
private static int mix32(long z) {
z = (z ^ (z >>> 33)) * 0x62a9d9ed799705f5L;
return (int)(((z ^ (z >>> 28)) * 0xcb24d0a5c88c35b3L) >>> 32);
}
/**
* Returns the gamma value to use for a new split instance.
*/
private static long mixGamma(long z) {
z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL; // MurmurHash3 mix constants
z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
z = (z ^ (z >>> 33)) | 1L; // force to be odd
int n = Long.bitCount(z ^ (z >>> 1)); // ensure enough transitions
return (n < 24) ? z ^ 0xaaaaaaaaaaaaaaaaL : z;
}
/**
* Adds gamma to seed.
*/
private long nextSeed() {
return seed += gamma;
}
/**
* The seed generator for default constructors.
*/
private static final AtomicLong defaultGen = new AtomicLong(initialSeed());
private static long initialSeed() {
String pp = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(
"java.util.secureRandomSeed"));
if (pp != null && pp.equalsIgnoreCase("true")) {
byte[] seedBytes = java.security.SecureRandom.getSeed(8);
long s = (long)(seedBytes[0]) & 0xffL;
for (int i = 1; i < 8; ++i)
s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
return s;
}
return (mix64(System.currentTimeMillis()) ^
mix64(System.nanoTime()));
}
// IllegalArgumentException messages
static final String BadBound = "bound must be positive";
static final String BadRange = "bound must be greater than origin";
static final String BadSize = "size must be non-negative";
/*
* Internal versions of nextX methods used by streams, as well as
* the public nextX(origin, bound) methods. These exist mainly to
* avoid the need for multiple versions of stream spliterators
* across the different exported forms of streams.
*/
/**
* The form of nextLong used by LongStream Spliterators. If
* origin is greater than bound, acts as unbounded form of
* nextLong, else as bounded form.
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final long internalNextLong(long origin, long bound) {
/*
* Four Cases:
*
* 1. If the arguments indicate unbounded form, act as
* nextLong().
*
* 2. If the range is an exact power of two, apply the
* associated bit mask.
*
* 3. If the range is positive, loop to avoid potential bias
* when the implicit nextLong() bound (2<sup>64</sup>) is not
* evenly divisible by the range. The loop rejects candidates
* computed from otherwise over-represented values. The
* expected number of iterations under an ideal generator
* varies from 1 to 2, depending on the bound. The loop itself
* takes an unlovable form. Because the first candidate is
* already available, we need a break-in-the-middle
* construction, which is concisely but cryptically performed
* within the while-condition of a body-less for loop.
*
* 4. Otherwise, the range cannot be represented as a positive
* long. The loop repeatedly generates unbounded longs until
* obtaining a candidate meeting constraints (with an expected
* number of iterations of less than two).
*/
long r = mix64(nextSeed());
if (origin < bound) {
long n = bound - origin, m = n - 1;
if ((n & m) == 0L) // power of two
r = (r & m) + origin;
else if (n > 0L) { // reject over-represented candidates
for (long u = r >>> 1; // ensure nonnegative
u + m - (r = u % n) < 0L; // rejection check
u = mix64(nextSeed()) >>> 1) // retry
;
r += origin;
}
else { // range not representable as long
while (r < origin || r >= bound)
r = mix64(nextSeed());
}
}
return r;
}
/**
* The form of nextInt used by IntStream Spliterators.
* Exactly the same as long version, except for types.
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final int internalNextInt(int origin, int bound) {
int r = mix32(nextSeed());
if (origin < bound) {
int n = bound - origin, m = n - 1;
if ((n & m) == 0)
r = (r & m) + origin;
else if (n > 0) {
for (int u = r >>> 1;
u + m - (r = u % n) < 0;
u = mix32(nextSeed()) >>> 1)
;
r += origin;
}
else {
while (r < origin || r >= bound)
r = mix32(nextSeed());
}
}
return r;
}
/**
* The form of nextDouble used by DoubleStream Spliterators.
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final double internalNextDouble(double origin, double bound) {
double r = (nextLong() >>> 11) * DOUBLE_UNIT;
if (origin < bound) {
r = r * (bound - origin) + origin;
if (r >= bound) // correct for rounding
r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
}
return r;
}
/* ---------------- public methods ---------------- */
/**
* Creates a new SplittableRandom instance using the specified
* initial seed. SplittableRandom instances created with the same
* seed in the same program generate identical sequences of values.
*
* @param seed the initial seed
*/
public SplittableRandom(long seed) {
this(seed, GOLDEN_GAMMA);
}
/**
* Creates a new SplittableRandom instance that is likely to
* generate sequences of values that are statistically independent
* of those of any other instances in the current program; and
* may, and typically does, vary across program invocations.
*/
public SplittableRandom() { // emulate defaultGen.split()
long s = defaultGen.getAndAdd(2 * GOLDEN_GAMMA);
this.seed = mix64(s);
this.gamma = mixGamma(s + GOLDEN_GAMMA);
}
/**
* Constructs and returns a new SplittableRandom instance that
* shares no mutable state with this instance. However, with very
* high probability, the set of values collectively generated by
* the two objects has the same statistical properties as if the
* same quantity of values were generated by a single thread using
* a single SplittableRandom object. Either or both of the two
* objects may be further split using the {@code split()} method,
* and the same expected statistical properties apply to the
* entire set of generators constructed by such recursive
* splitting.
*
* @return the new SplittableRandom instance
*/
public SplittableRandom split() {
return new SplittableRandom(nextLong(), mixGamma(nextSeed()));
}
/**
* Returns a pseudorandom {@code int} value.
*
* @return a pseudorandom {@code int} value
*/
public int nextInt() {
return mix32(nextSeed());
}
/**
* Returns a pseudorandom {@code int} value between zero (inclusive)
* and the specified bound (exclusive).
*
* @param bound the upper bound (exclusive). Must be positive.
* @return a pseudorandom {@code int} value between zero
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code bound} is not positive
*/
public int nextInt(int bound) {
if (bound <= 0)
throw new IllegalArgumentException(BadBound);
// Specialize internalNextInt for origin 0
int r = mix32(nextSeed());
int m = bound - 1;
if ((bound & m) == 0) // power of two
r &= m;
else { // reject over-represented candidates
for (int u = r >>> 1;
u + m - (r = u % bound) < 0;
u = mix32(nextSeed()) >>> 1)
;
}
return r;
}
/**
* Returns a pseudorandom {@code int} value between the specified
* origin (inclusive) and the specified bound (exclusive).
*
* @param origin the least value returned
* @param bound the upper bound (exclusive)
* @return a pseudorandom {@code int} value between the origin
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*/
public int nextInt(int origin, int bound) {
if (origin >= bound)
throw new IllegalArgumentException(BadRange);
return internalNextInt(origin, bound);
}
/**
* Returns a pseudorandom {@code long} value.
*
* @return a pseudorandom {@code long} value
*/
public long nextLong() {
return mix64(nextSeed());
}
/**
* Returns a pseudorandom {@code long} value between zero (inclusive)
* and the specified bound (exclusive).
*
* @param bound the upper bound (exclusive). Must be positive.
* @return a pseudorandom {@code long} value between zero
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code bound} is not positive
*/
public long nextLong(long bound) {
if (bound <= 0)
throw new IllegalArgumentException(BadBound);
// Specialize internalNextLong for origin 0
long r = mix64(nextSeed());
long m = bound - 1;
if ((bound & m) == 0L) // power of two
r &= m;
else { // reject over-represented candidates
for (long u = r >>> 1;
u + m - (r = u % bound) < 0L;
u = mix64(nextSeed()) >>> 1)
;
}
return r;
}
/**
* Returns a pseudorandom {@code long} value between the specified
* origin (inclusive) and the specified bound (exclusive).
*
* @param origin the least value returned
* @param bound the upper bound (exclusive)
* @return a pseudorandom {@code long} value between the origin
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*/
public long nextLong(long origin, long bound) {
if (origin >= bound)
throw new IllegalArgumentException(BadRange);
return internalNextLong(origin, bound);
}
/**
* Returns a pseudorandom {@code double} value between zero
* (inclusive) and one (exclusive).
*
* @return a pseudorandom {@code double} value between zero
* (inclusive) and one (exclusive)
*/
public double nextDouble() {
return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
}
/**
* Returns a pseudorandom {@code double} value between 0.0
* (inclusive) and the specified bound (exclusive).
*
* @param bound the upper bound (exclusive). Must be positive.
* @return a pseudorandom {@code double} value between zero
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code bound} is not positive
*/
public double nextDouble(double bound) {
if (!(bound > 0.0))
throw new IllegalArgumentException(BadBound);
double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
return (result < bound) ? result : // correct for rounding
Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
}
/**
* Returns a pseudorandom {@code double} value between the specified
* origin (inclusive) and bound (exclusive).
*
* @param origin the least value returned
* @param bound the upper bound (exclusive)
* @return a pseudorandom {@code double} value between the origin
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*/
public double nextDouble(double origin, double bound) {
if (!(origin < bound))
throw new IllegalArgumentException(BadRange);
return internalNextDouble(origin, bound);
}
/**
* Returns a pseudorandom {@code boolean} value.
*
* @return a pseudorandom {@code boolean} value
*/
public boolean nextBoolean() {
return mix32(nextSeed()) < 0;
}
// stream methods, coded in a way intended to better isolate for
// maintenance purposes the small differences across forms.
/**
* Returns a stream producing the given {@code streamSize} number
* of pseudorandom {@code int} values from this generator and/or
* one split from it.
*
* @param streamSize the number of values to generate
* @return a stream of pseudorandom {@code int} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
*/
public IntStream ints(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, streamSize, Integer.MAX_VALUE, 0),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code int}
* values from this generator and/or one split from it.
*
* @implNote This method is implemented to be equivalent to {@code
* ints(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code int} values
*/
public IntStream ints() {
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number
* of pseudorandom {@code int} values from this generator and/or one split
* from it; each value conforms to the given origin (inclusive) and bound
* (exclusive).
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code int} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero, or {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public IntStream ints(long streamSize, int randomNumberOrigin,
int randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* int} values from this generator and/or one split from it; each value
* conforms to the given origin (inclusive) and bound (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code int} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number
* of pseudorandom {@code long} values from this generator and/or
* one split from it.
*
* @param streamSize the number of values to generate
* @return a stream of pseudorandom {@code long} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
*/
public LongStream longs(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, streamSize, Long.MAX_VALUE, 0L),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* long} values from this generator and/or one split from it.
*
* @implNote This method is implemented to be equivalent to {@code
* longs(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code long} values
*/
public LongStream longs() {
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code long} values from this generator and/or one split
* from it; each value conforms to the given origin (inclusive) and bound
* (exclusive).
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code long} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero, or {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public LongStream longs(long streamSize, long randomNumberOrigin,
long randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* long} values from this generator and/or one split from it; each value
* conforms to the given origin (inclusive) and bound (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code long} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code double} values from this generator and/or one split
* from it; each value is between zero (inclusive) and one (exclusive).
*
* @param streamSize the number of values to generate
* @return a stream of {@code double} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
*/
public DoubleStream doubles(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, streamSize, Double.MAX_VALUE, 0.0),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* double} values from this generator and/or one split from it; each value
* is between zero (inclusive) and one (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* doubles(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code double} values
*/
public DoubleStream doubles() {
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code double} values from this generator and/or one split
* from it; each value conforms to the given origin (inclusive) and bound
* (exclusive).
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public DoubleStream doubles(long streamSize, double randomNumberOrigin,
double randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (!(randomNumberOrigin < randomNumberBound))
throw new IllegalArgumentException(BadRange);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* double} values from this generator and/or one split from it; each value
* conforms to the given origin (inclusive) and bound (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
if (!(randomNumberOrigin < randomNumberBound))
throw new IllegalArgumentException(BadRange);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Spliterator for int streams. We multiplex the four int
* versions into one class by treating a bound less than origin as
* unbounded, and also by treating "infinite" as equivalent to
* Long.MAX_VALUE. For splits, it uses the standard divide-by-two
* approach. The long and double versions of this class are
* identical except for types.
*/
static final class RandomIntsSpliterator implements Spliterator.OfInt {
final SplittableRandom rng;
long index;
final long fence;
final int origin;
final int bound;
RandomIntsSpliterator(SplittableRandom rng, long index, long fence,
int origin, int bound) {
this.rng = rng; this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomIntsSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomIntsSpliterator(rng.split(), i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(IntConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(rng.internalNextInt(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(IntConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
SplittableRandom r = rng;
int o = origin, b = bound;
do {
consumer.accept(r.internalNextInt(o, b));
} while (++i < f);
}
}
}
/**
* Spliterator for long streams.
*/
static final class RandomLongsSpliterator implements Spliterator.OfLong {
final SplittableRandom rng;
long index;
final long fence;
final long origin;
final long bound;
RandomLongsSpliterator(SplittableRandom rng, long index, long fence,
long origin, long bound) {
this.rng = rng; this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomLongsSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomLongsSpliterator(rng.split(), i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(LongConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(rng.internalNextLong(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(LongConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
SplittableRandom r = rng;
long o = origin, b = bound;
do {
consumer.accept(r.internalNextLong(o, b));
} while (++i < f);
}
}
}
/**
* Spliterator for double streams.
*/
static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
final SplittableRandom rng;
long index;
final long fence;
final double origin;
final double bound;
RandomDoublesSpliterator(SplittableRandom rng, long index, long fence,
double origin, double bound) {
this.rng = rng; this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomDoublesSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomDoublesSpliterator(rng.split(), i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(DoubleConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(rng.internalNextDouble(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(DoubleConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
SplittableRandom r = rng;
double o = origin, b = bound;
do {
consumer.accept(r.internalNextDouble(o, b));
} while (++i < f);
}
}
}
}

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