# HG changeset patch # User Jaroslav Tulach # Date 1359376253 -3600 # Node ID 41b8defdf15890f44c4009c9b4e671002c401b1d # Parent 784aaf9ee1790cf2ea816e9921515ae37fe0076a# Parent ee8a922f4268ce8c8cc86cbe5ea371e1d506c6b2 Merge of new classes requested by FX team diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/AbstractQueue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/AbstractQueue.java Mon Jan 28 13:30:53 2013 +0100 @@ -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 not allow null + * elements. Methods {@link #add add}, {@link #remove remove}, and + * {@link #element element} are based on {@link #offer offer}, {@link + * #poll poll}, and {@link #peek peek}, respectively, but throw + * exceptions instead of indicating failure via false or + * null returns. + * + *

A Queue implementation that extends this class must + * minimally define a method {@link Queue#offer} which does not permit + * insertion of null elements, along with methods {@link + * Queue#peek}, {@link Queue#poll}, {@link Collection#size}, and + * {@link Collection#iterator}. Typically, additional methods will be + * overridden as well. If these requirements cannot be met, consider + * instead subclassing {@link AbstractCollection}. + * + *

This class is a member of the + * + * Java Collections Framework. + * + * @since 1.5 + * @author Doug Lea + * @param the type of elements held in this collection + */ +public abstract class AbstractQueue + extends AbstractCollection + implements Queue { + + /** + * 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 + * true upon success and throwing an IllegalStateException + * if no space is currently available. + * + *

This implementation returns true if offer succeeds, + * else throws an IllegalStateException. + * + * @param e the element to add + * @return true (as specified by {@link Collection#add}) + * @throws IllegalStateException if the element cannot be added at this + * time due to capacity restrictions + * @throws ClassCastException if the class of the specified element + * prevents it from being added to this queue + * @throws NullPointerException if the specified element is null and + * this queue does not permit null elements + * @throws IllegalArgumentException if some property of this element + * prevents it from being added to this queue + */ + public boolean add(E e) { + if (offer(e)) + return true; + else + throw new IllegalStateException("Queue full"); + } + + /** + * Retrieves and removes the head of this queue. This method differs + * from {@link #poll poll} only in that it throws an exception if this + * queue is empty. + * + *

This implementation returns the result of poll + * unless the queue is empty. + * + * @return the head of this queue + * @throws NoSuchElementException if this queue is empty + */ + public E remove() { + E x = poll(); + if (x != null) + return x; + else + throw new NoSuchElementException(); + } + + /** + * Retrieves, but does not remove, the head of this queue. This method + * differs from {@link #peek peek} only in that it throws an exception if + * this queue is empty. + * + *

This implementation returns the result of peek + * unless the queue is empty. + * + * @return the head of this queue + * @throws NoSuchElementException if this queue is empty + */ + public E element() { + E x = peek(); + if (x != null) + return x; + else + throw new NoSuchElementException(); + } + + /** + * Removes all of the elements from this queue. + * The queue will be empty after this call returns. + * + *

This implementation repeatedly invokes {@link #poll poll} until it + * returns null. + */ + public void clear() { + while (poll() != null) + ; + } + + /** + * Adds all of the elements in the specified collection to this + * queue. Attempts to addAll of a queue to itself result in + * IllegalArgumentException. Further, the behavior of + * this operation is undefined if the specified collection is + * modified while the operation is in progress. + * + *

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 + * null element) may result in only some of the elements + * having been successfully added when the associated exception is + * thrown. + * + * @param c collection containing elements to be added to this queue + * @return true if this queue changed as a result of the call + * @throws ClassCastException if the class of an element of the specified + * collection prevents it from being added to this queue + * @throws NullPointerException if the specified collection contains a + * null element and this queue does not permit null elements, + * or if the specified collection is null + * @throws IllegalArgumentException if some property of an element of the + * specified collection prevents it from being added to this + * queue, or if the specified collection is this queue + * @throws IllegalStateException if not all the elements can be added at + * this time due to insertion restrictions + * @see #add(Object) + */ + public boolean addAll(Collection 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; + } + +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/AbstractSequentialList.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/AbstractSequentialList.java Mon Jan 28 13:30:53 2013 +0100 @@ -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 List + * interface to minimize the effort required to implement this interface + * backed by a "sequential access" data store (such as a linked list). For + * random access data (such as an array), AbstractList should be used + * in preference to this class.

+ * + * This class is the opposite of the AbstractList class in the sense + * that it implements the "random access" methods (get(int index), + * set(int index, E element), add(int index, E element) and + * remove(int index)) on top of the list's list iterator, instead of + * the other way around.

+ * + * To implement a list the programmer needs only to extend this class and + * provide implementations for the listIterator and size + * methods. For an unmodifiable list, the programmer need only implement the + * list iterator's hasNext, next, hasPrevious, + * previous and index methods.

+ * + * For a modifiable list the programmer should additionally implement the list + * iterator's set method. For a variable-size list the programmer + * should additionally implement the list iterator's remove and + * add methods.

+ * + * The programmer should generally provide a void (no argument) and collection + * constructor, as per the recommendation in the Collection interface + * specification.

+ * + * This class is a member of the + * + * Java Collections Framework. + * + * @author Josh Bloch + * @author Neal Gafter + * @see Collection + * @see List + * @see AbstractList + * @see AbstractCollection + * @since 1.2 + */ + +public abstract class AbstractSequentialList extends AbstractList { + /** + * Sole constructor. (For invocation by subclass constructors, typically + * implicit.) + */ + protected AbstractSequentialList() { + } + + /** + * Returns the element at the specified position in this list. + * + *

This implementation first gets a list iterator pointing to the + * indexed element (with listIterator(index)). Then, it gets + * the element using ListIterator.next and returns it. + * + * @throws IndexOutOfBoundsException {@inheritDoc} + */ + public E get(int index) { + try { + return listIterator(index).next(); + } catch (NoSuchElementException exc) { + throw new IndexOutOfBoundsException("Index: "+index); + } + } + + /** + * Replaces the element at the specified position in this list with the + * specified element (optional operation). + * + *

This implementation first gets a list iterator pointing to the + * indexed element (with listIterator(index)). Then, it gets + * the current element using ListIterator.next and replaces it + * with ListIterator.set. + * + *

Note that this implementation will throw an + * UnsupportedOperationException if the list iterator does not + * implement the set operation. + * + * @throws UnsupportedOperationException {@inheritDoc} + * @throws ClassCastException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} + * @throws IndexOutOfBoundsException {@inheritDoc} + */ + public E set(int index, E element) { + try { + ListIterator e = 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). + * + *

This implementation first gets a list iterator pointing to the + * indexed element (with listIterator(index)). Then, it + * inserts the specified element with ListIterator.add. + * + *

Note that this implementation will throw an + * UnsupportedOperationException if the list iterator does not + * implement the add operation. + * + * @throws UnsupportedOperationException {@inheritDoc} + * @throws ClassCastException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} + * @throws IndexOutOfBoundsException {@inheritDoc} + */ + public void add(int index, E element) { + try { + listIterator(index).add(element); + } catch (NoSuchElementException exc) { + throw new IndexOutOfBoundsException("Index: "+index); + } + } + + /** + * Removes the element at the specified position in this list (optional + * operation). Shifts any subsequent elements to the left (subtracts one + * from their indices). Returns the element that was removed from the + * list. + * + *

This implementation first gets a list iterator pointing to the + * indexed element (with listIterator(index)). Then, it removes + * the element with ListIterator.remove. + * + *

Note that this implementation will throw an + * UnsupportedOperationException if the list iterator does not + * implement the remove operation. + * + * @throws UnsupportedOperationException {@inheritDoc} + * @throws IndexOutOfBoundsException {@inheritDoc} + */ + public E remove(int index) { + try { + ListIterator 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.) + * + *

This implementation gets an iterator over the specified collection and + * a list iterator over this list pointing to the indexed element (with + * listIterator(index)). Then, it iterates over the specified + * collection, inserting the elements obtained from the iterator into this + * list, one at a time, using ListIterator.add followed by + * ListIterator.next (to skip over the added element). + * + *

Note that this implementation will throw an + * UnsupportedOperationException if the list iterator returned by + * the listIterator method does not implement the add + * operation. + * + * @throws UnsupportedOperationException {@inheritDoc} + * @throws ClassCastException {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} + * @throws IndexOutOfBoundsException {@inheritDoc} + */ + public boolean addAll(int index, Collection c) { + try { + boolean modified = false; + ListIterator e1 = listIterator(index); + Iterator 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).

+ * + * This implementation merely returns a list iterator over the list. + * + * @return an iterator over the elements in this list (in proper sequence) + */ + public Iterator 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 next method) + * @return a list iterator over the elements in this list (in proper + * sequence) + * @throws IndexOutOfBoundsException {@inheritDoc} + */ + public abstract ListIterator listIterator(int index); +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/ArrayDeque.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/ArrayDeque.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,866 @@ +/* + * 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.*; + +/** + * 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. + * + *

Most 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. + * + *

The iterators returned by this class's iterator method are + * fail-fast: If the deque is modified at any time after the iterator + * is created, in any way except through the iterator's own 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. + * + *

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 ConcurrentModificationException on a best-effort basis. + * Therefore, it would be wrong to write a program that depended on this + * exception for its correctness: the fail-fast behavior of iterators + * should be used only to detect bugs. + * + *

This class and its iterator implement all of the + * optional methods of the {@link Collection} and {@link + * Iterator} interfaces. + * + *

This class is a member of the + * + * Java Collections Framework. + * + * @author Josh Bloch and Doug Lea + * @since 1.6 + * @param the type of elements held in this collection + */ +public class ArrayDeque extends AbstractCollection + implements Deque, 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. + */ + private transient E[] elements; + + /** + * 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. + */ + private 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)). + */ + private 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 ****** + + /** + * Allocate empty array to hold the given number of elements. + * + * @param numElements the number of elements to hold + */ + private void allocateElements(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 + } + elements = (E[]) new Object[initialCapacity]; + } + + /** + * Double 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 = (E[])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[] 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 = (E[]) 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 front 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 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. + * + *

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 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 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; + E result = 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); + E result = elements[t]; + if (result == null) + return null; + elements[t] = null; + tail = t; + return result; + } + + /** + * @throws NoSuchElementException {@inheritDoc} + */ + public E getFirst() { + E x = elements[head]; + if (x == null) + throw new NoSuchElementException(); + return x; + } + + /** + * @throws NoSuchElementException {@inheritDoc} + */ + public E getLast() { + E x = elements[(tail - 1) & (elements.length - 1)]; + if (x == null) + throw new NoSuchElementException(); + return x; + } + + public E peekFirst() { + return elements[head]; // elements[head] is null if deque empty + } + + public E peekLast() { + return 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 e such that + * o.equals(e) (if such an element exists). + * Returns 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 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; + E 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 e such that + * o.equals(e) (if such an element exists). + * Returns 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 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; + E 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. + * + *

This method is equivalent to {@link #addLast}. + * + * @param e the element to add + * @return 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. + * + *

This method is equivalent to {@link #offerLast}. + * + * @param e the element to add + * @return 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. + * + *

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 + * null if this deque is empty. + * + *

This method is equivalent to {@link #pollFirst}. + * + * @return the head of the queue represented by this deque, or + * 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. + * + *

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 null if this deque is empty. + * + *

This method is equivalent to {@link #peekFirst}. + * + * @return the head of the queue represented by this deque, or + * 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. + * + *

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. + * + *

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. + * + *

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 E[] 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 true if this deque contains no elements. + * + * @return 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 iterator() { + return new DeqIterator(); + } + + public Iterator descendingIterator() { + return new DescendingIterator(); + } + + private class DeqIterator implements Iterator { + /** + * 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(); + E result = 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; + } + } + + private class DescendingIterator implements Iterator { + /* + * 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); + E result = 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 true if this deque contains the specified element. + * More formally, returns true if and only if this deque contains + * at least one element e such that o.equals(e). + * + * @param o object to be checked for containment in this deque + * @return 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; + E 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 e such that + * o.equals(e) (if such an element exists). + * Returns true if this deque contained the specified element + * (or equivalently, if this deque changed as a result of the call). + * + *

This method is equivalent to {@link #removeFirstOccurrence}. + * + * @param o element to be removed from this deque, if present + * @return 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). + * + *

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. + * + *

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. + * + *

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 + * null. + * + *

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. + * + *

Suppose 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 String: + * + *

+     *     String[] y = x.toArray(new String[0]);
+ * + * Note that toArray(new Object[0]) is identical in function to + * 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 + */ + public 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 clone() { + try { + ArrayDeque result = (ArrayDeque) super.clone(); + result.elements = Arrays.copyOf(elements, elements.length); + return result; + + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } + + /** + * Appease the serialization gods. + */ + private static final long serialVersionUID = 2340985798034038923L; + + /** + * Serialize this deque. + * + * @serialData The current size (int) of the deque, + * followed by all of its elements (each an object reference) in + * first-to-last order. + */ + private void writeObject(ObjectOutputStream s) throws 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]); + } + + /** + * Deserialize this deque. + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + + // Read in size and allocate array + int size = s.readInt(); + allocateElements(size); + head = 0; + tail = size; + + // Read in all elements in the proper order. + for (int i = 0; i < size; i++) + elements[i] = (E)s.readObject(); + } +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/Collections.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/Collections.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,3966 @@ +/* + * 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; +import java.io.Serializable; +import java.io.ObjectOutputStream; +import java.io.IOException; +import java.lang.reflect.Array; + +/** + * This class consists exclusively of static methods that operate on or return + * collections. It contains polymorphic algorithms that operate on + * collections, "wrappers", which return a new collection backed by a + * specified collection, and a few other odds and ends. + * + *

The methods of this class all throw a NullPointerException + * if the collections or class objects provided to them are null. + * + *

The documentation for the polymorphic algorithms contained in this class + * generally includes a brief description of the implementation. Such + * descriptions should be regarded as implementation notes, rather than + * parts of the specification. Implementors should feel free to + * substitute other algorithms, so long as the specification itself is adhered + * to. (For example, the algorithm used by sort does not have to be + * a mergesort, but it does have to be stable.) + * + *

The "destructive" algorithms contained in this class, that is, the + * algorithms that modify the collection on which they operate, are specified + * to throw UnsupportedOperationException if the collection does not + * support the appropriate mutation primitive(s), such as the set + * method. These algorithms may, but are not required to, throw this + * exception if an invocation would have no effect on the collection. For + * example, invoking the sort method on an unmodifiable list that is + * already sorted may or may not throw UnsupportedOperationException. + * + *

This class is a member of the + * + * Java Collections Framework. + * + * @author Josh Bloch + * @author Neal Gafter + * @see Collection + * @see Set + * @see List + * @see Map + * @since 1.2 + */ + +public class Collections { + // Suppresses default constructor, ensuring non-instantiability. + private Collections() { + } + + // Algorithms + + /* + * Tuning parameters for algorithms - Many of the List algorithms have + * two implementations, one of which is appropriate for RandomAccess + * lists, the other for "sequential." Often, the random access variant + * yields better performance on small sequential access lists. The + * tuning parameters below determine the cutoff point for what constitutes + * a "small" sequential access list for each algorithm. The values below + * were empirically determined to work well for LinkedList. Hopefully + * they should be reasonable for other sequential access List + * implementations. Those doing performance work on this code would + * do well to validate the values of these parameters from time to time. + * (The first word of each tuning parameter name is the algorithm to which + * it applies.) + */ + private static final int BINARYSEARCH_THRESHOLD = 5000; + private static final int REVERSE_THRESHOLD = 18; + private static final int SHUFFLE_THRESHOLD = 5; + private static final int FILL_THRESHOLD = 25; + private static final int ROTATE_THRESHOLD = 100; + private static final int COPY_THRESHOLD = 10; + private static final int REPLACEALL_THRESHOLD = 11; + private static final int INDEXOFSUBLIST_THRESHOLD = 35; + + /** + * Sorts the specified list into ascending order, according to the + * {@linkplain Comparable natural ordering} of its elements. + * All elements in the list must implement the {@link Comparable} + * interface. Furthermore, all elements in the list must be + * mutually comparable (that is, {@code e1.compareTo(e2)} + * must not throw a {@code ClassCastException} for any elements + * {@code e1} and {@code e2} in the list). + * + *

This sort is guaranteed to be stable: equal elements will + * not be reordered as a result of the sort. + * + *

The specified list must be modifiable, but need not be resizable. + * + *

Implementation note: 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. + * + *

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. + * + *

The implementation was adapted from Tim Peters's list sort for Python + * ( + * TimSort). It uses techiques 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. + * + *

This implementation dumps the specified list into an array, sorts + * the array, and iterates over the list resetting each element + * from the corresponding position in the array. This avoids the + * n2 log(n) performance that would result from attempting + * to sort a linked list in place. + * + * @param list the list to be sorted. + * @throws ClassCastException if the list contains elements that are not + * mutually comparable (for example, strings and integers). + * @throws UnsupportedOperationException if the specified list's + * list-iterator does not support the {@code set} operation. + * @throws IllegalArgumentException (optional) if the implementation + * detects that the natural ordering of the list elements is + * found to violate the {@link Comparable} contract + */ + public static > void sort(List list) { + Object[] a = list.toArray(); + Arrays.sort(a); + ListIterator i = list.listIterator(); + for (int j=0; jmutually + * comparable 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). + * + *

This sort is guaranteed to be stable: equal elements will + * not be reordered as a result of the sort. + * + *

The specified list must be modifiable, but need not be resizable. + * + *

Implementation note: 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. + * + *

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. + * + *

The implementation was adapted from Tim Peters's list sort for Python + * ( + * TimSort). It uses techiques 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. + * + *

This implementation dumps the specified list into an array, sorts + * the array, and iterates over the list resetting each element + * from the corresponding position in the array. This avoids the + * n2 log(n) performance that would result from attempting + * to sort a linked list in place. + * + * @param list the list to be sorted. + * @param c the comparator to determine the order of the list. A + * {@code null} value indicates that the elements' natural + * ordering should be used. + * @throws ClassCastException if the list contains elements that are not + * mutually comparable using the specified comparator. + * @throws UnsupportedOperationException if the specified list's + * list-iterator does not support the {@code set} operation. + * @throws IllegalArgumentException (optional) if the comparator is + * found to violate the {@link Comparator} contract + */ + public static void sort(List list, Comparator c) { + Object[] a = list.toArray(); + Arrays.sort(a, (Comparator)c); + ListIterator i = list.listIterator(); + for (int j=0; jThis method runs in log(n) time for a "random access" list (which + * provides near-constant-time positional access). If the specified list + * does not implement the {@link RandomAccess} interface and is large, + * this method will do an iterator-based binary search that performs + * O(n) link traversals and O(log n) element comparisons. + * + * @param list the list to be searched. + * @param key the key to be searched for. + * @return the index of the search key, if it is contained in the list; + * otherwise, (-(insertion point) - 1). The + * insertion point is defined as the point at which the + * key would be inserted into the list: the index of the first + * element greater than the key, or list.size() if all + * elements in the list are less than the specified key. Note + * that this guarantees that the return value will be >= 0 if + * and only if the key is found. + * @throws ClassCastException if the list contains elements that are not + * mutually comparable (for example, strings and + * integers), or the search key is not mutually comparable + * with the elements of the list. + */ + public static + int binarySearch(List> list, T key) { + if (list instanceof RandomAccess || list.size() + int indexedBinarySearch(List> list, T key) + { + int low = 0; + int high = list.size()-1; + + while (low <= high) { + int mid = (low + high) >>> 1; + Comparable midVal = list.get(mid); + int cmp = midVal.compareTo(key); + + if (cmp < 0) + low = mid + 1; + else if (cmp > 0) + high = mid - 1; + else + return mid; // key found + } + return -(low + 1); // key not found + } + + private static + int iteratorBinarySearch(List> list, T key) + { + int low = 0; + int high = list.size()-1; + ListIterator> i = list.listIterator(); + + while (low <= high) { + int mid = (low + high) >>> 1; + Comparable midVal = get(i, mid); + int cmp = midVal.compareTo(key); + + if (cmp < 0) + low = mid + 1; + else if (cmp > 0) + high = mid - 1; + else + return mid; // key found + } + return -(low + 1); // key not found + } + + /** + * Gets the ith element from the given list by repositioning the specified + * list listIterator. + */ + private static T get(ListIterator i, int index) { + T obj = null; + int pos = i.nextIndex(); + if (pos <= index) { + do { + obj = i.next(); + } while (pos++ < index); + } else { + do { + obj = i.previous(); + } while (--pos > index); + } + return obj; + } + + /** + * Searches the specified list for the specified object using the binary + * search algorithm. The list must be sorted into ascending order + * according to the specified comparator (as by the + * {@link #sort(List, Comparator) sort(List, Comparator)} + * method), prior to making this call. If it is + * not sorted, the results are undefined. If the list contains multiple + * elements equal to the specified object, there is no guarantee which one + * will be found. + * + *

This method runs in log(n) time for a "random access" list (which + * provides near-constant-time positional access). If the specified list + * does not implement the {@link RandomAccess} interface and is large, + * this method will do an iterator-based binary search that performs + * O(n) link traversals and O(log n) element comparisons. + * + * @param list the list to be searched. + * @param key the key to be searched for. + * @param c the comparator by which the list is ordered. + * A null value indicates that the elements' + * {@linkplain Comparable natural ordering} should be used. + * @return the index of the search key, if it is contained in the list; + * otherwise, (-(insertion point) - 1). The + * insertion point is defined as the point at which the + * key would be inserted into the list: the index of the first + * element greater than the key, or list.size() if all + * elements in the list are less than the specified key. Note + * that this guarantees that the return value will be >= 0 if + * and only if the key is found. + * @throws ClassCastException if the list contains elements that are not + * mutually comparable using the specified comparator, + * or the search key is not mutually comparable with the + * elements of the list using this comparator. + */ + public static int binarySearch(List list, T key, Comparator c) { + if (c==null) + return binarySearch((List) list, key); + + if (list instanceof RandomAccess || list.size() int indexedBinarySearch(List l, T key, Comparator c) { + int low = 0; + int high = l.size()-1; + + while (low <= high) { + int mid = (low + high) >>> 1; + T midVal = l.get(mid); + int cmp = c.compare(midVal, key); + + if (cmp < 0) + low = mid + 1; + else if (cmp > 0) + high = mid - 1; + else + return mid; // key found + } + return -(low + 1); // key not found + } + + private static int iteratorBinarySearch(List l, T key, Comparator c) { + int low = 0; + int high = l.size()-1; + ListIterator i = l.listIterator(); + + while (low <= high) { + int mid = (low + high) >>> 1; + T midVal = get(i, mid); + int cmp = c.compare(midVal, key); + + if (cmp < 0) + low = mid + 1; + else if (cmp > 0) + high = mid - 1; + else + return mid; // key found + } + return -(low + 1); // key not found + } + + private interface SelfComparable extends Comparable {} + + + /** + * Reverses the order of the elements in the specified list.

+ * + * This method runs in linear time. + * + * @param list the list whose elements are to be reversed. + * @throws UnsupportedOperationException if the specified list or + * its list-iterator does not support the set operation. + */ + public static void reverse(List list) { + int size = list.size(); + if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) { + for (int i=0, mid=size>>1, j=size-1; i>1; i + * + * The hedge "approximately" is used in the foregoing description because + * default source of randomness is only approximately an unbiased source + * of independently chosen bits. If it were a perfect source of randomly + * chosen bits, then the algorithm would choose permutations with perfect + * uniformity.

+ * + * This implementation traverses the list backwards, from the last element + * up to the second, repeatedly swapping a randomly selected element into + * the "current position". Elements are randomly selected from the + * portion of the list that runs from the first element to the current + * position, inclusive.

+ * + * This method runs in linear time. If the specified list does not + * implement the {@link RandomAccess} interface and is large, this + * implementation dumps the specified list into an array before shuffling + * it, and dumps the shuffled array back into the list. This avoids the + * quadratic behavior that would result from shuffling a "sequential + * access" list in place. + * + * @param list the list to be shuffled. + * @throws UnsupportedOperationException if the specified list or + * its list-iterator does not support the set operation. + */ + public static void shuffle(List list) { + Random rnd = r; + if (rnd == null) + r = rnd = new Random(); + shuffle(list, rnd); + } + private static Random r; + + /** + * Randomly permute the specified list using the specified source of + * randomness. All permutations occur with equal likelihood + * assuming that the source of randomness is fair.

+ * + * This implementation traverses the list backwards, from the last element + * up to the second, repeatedly swapping a randomly selected element into + * the "current position". Elements are randomly selected from the + * portion of the list that runs from the first element to the current + * position, inclusive.

+ * + * This method runs in linear time. If the specified list does not + * implement the {@link RandomAccess} interface and is large, this + * implementation dumps the specified list into an array before shuffling + * it, and dumps the shuffled array back into the list. This avoids the + * quadratic behavior that would result from shuffling a "sequential + * access" list in place. + * + * @param list the list to be shuffled. + * @param rnd the source of randomness to use to shuffle the list. + * @throws UnsupportedOperationException if the specified list or its + * list-iterator does not support the set operation. + */ + public static void shuffle(List list, Random rnd) { + int size = list.size(); + if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) { + for (int i=size; i>1; i--) + swap(list, i-1, rnd.nextInt(i)); + } else { + Object arr[] = list.toArray(); + + // Shuffle array + for (int i=size; i>1; i--) + swap(arr, i-1, rnd.nextInt(i)); + + // Dump array back into list + ListIterator it = list.listIterator(); + for (int i=0; ii or j + * is out of range (i < 0 || i >= list.size() + * || j < 0 || j >= list.size()). + * @since 1.4 + */ + public static void swap(List list, int i, int j) { + final List l = list; + l.set(i, l.set(j, l.get(i))); + } + + /** + * Swaps the two specified elements in the specified array. + */ + private static void swap(Object[] arr, int i, int j) { + Object tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + /** + * Replaces all of the elements of the specified list with the specified + * element.

+ * + * This method runs in linear time. + * + * @param list the list to be filled with the specified element. + * @param obj The element with which to fill the specified list. + * @throws UnsupportedOperationException if the specified list or its + * list-iterator does not support the set operation. + */ + public static void fill(List list, T obj) { + int size = list.size(); + + if (size < FILL_THRESHOLD || list instanceof RandomAccess) { + for (int i=0; i itr = list.listIterator(); + for (int i=0; i + * + * This method runs in linear time. + * + * @param dest The destination list. + * @param src The source list. + * @throws IndexOutOfBoundsException if the destination list is too small + * to contain the entire source List. + * @throws UnsupportedOperationException if the destination list's + * list-iterator does not support the set operation. + */ + public static void copy(List dest, List src) { + int srcSize = src.size(); + if (srcSize > dest.size()) + throw new IndexOutOfBoundsException("Source does not fit in dest"); + + if (srcSize < COPY_THRESHOLD || + (src instanceof RandomAccess && dest instanceof RandomAccess)) { + for (int i=0; i di=dest.listIterator(); + ListIterator si=src.listIterator(); + for (int i=0; inatural ordering of its elements. All elements in the + * collection must implement the Comparable interface. + * Furthermore, all elements in the collection must be mutually + * comparable (that is, e1.compareTo(e2) must not throw a + * ClassCastException for any elements e1 and + * e2 in the collection).

+ * + * This method iterates over the entire collection, hence it requires + * time proportional to the size of the collection. + * + * @param coll the collection whose minimum element is to be determined. + * @return the minimum element of the given collection, according + * to the natural ordering of its elements. + * @throws ClassCastException if the collection contains elements that are + * not mutually comparable (for example, strings and + * integers). + * @throws NoSuchElementException if the collection is empty. + * @see Comparable + */ + public static > T min(Collection coll) { + Iterator i = coll.iterator(); + T candidate = i.next(); + + while (i.hasNext()) { + T next = i.next(); + if (next.compareTo(candidate) < 0) + candidate = next; + } + return candidate; + } + + /** + * Returns the minimum element of the given collection, according to the + * order induced by the specified comparator. All elements in the + * collection must be mutually comparable by the specified + * comparator (that is, comp.compare(e1, e2) must not throw a + * ClassCastException for any elements e1 and + * e2 in the collection).

+ * + * This method iterates over the entire collection, hence it requires + * time proportional to the size of the collection. + * + * @param coll the collection whose minimum element is to be determined. + * @param comp the comparator with which to determine the minimum element. + * A null value indicates that the elements' natural + * ordering should be used. + * @return the minimum element of the given collection, according + * to the specified comparator. + * @throws ClassCastException if the collection contains elements that are + * not mutually comparable using the specified comparator. + * @throws NoSuchElementException if the collection is empty. + * @see Comparable + */ + public static T min(Collection coll, Comparator comp) { + if (comp==null) + return (T)min((Collection) (Collection) coll); + + Iterator i = coll.iterator(); + T candidate = i.next(); + + while (i.hasNext()) { + T next = i.next(); + if (comp.compare(next, candidate) < 0) + candidate = next; + } + return candidate; + } + + /** + * Returns the maximum element of the given collection, according to the + * natural ordering of its elements. All elements in the + * collection must implement the Comparable interface. + * Furthermore, all elements in the collection must be mutually + * comparable (that is, e1.compareTo(e2) must not throw a + * ClassCastException for any elements e1 and + * e2 in the collection).

+ * + * This method iterates over the entire collection, hence it requires + * time proportional to the size of the collection. + * + * @param coll the collection whose maximum element is to be determined. + * @return the maximum element of the given collection, according + * to the natural ordering of its elements. + * @throws ClassCastException if the collection contains elements that are + * not mutually comparable (for example, strings and + * integers). + * @throws NoSuchElementException if the collection is empty. + * @see Comparable + */ + public static > T max(Collection coll) { + Iterator i = coll.iterator(); + T candidate = i.next(); + + while (i.hasNext()) { + T next = i.next(); + if (next.compareTo(candidate) > 0) + candidate = next; + } + return candidate; + } + + /** + * Returns the maximum element of the given collection, according to the + * order induced by the specified comparator. All elements in the + * collection must be mutually comparable by the specified + * comparator (that is, comp.compare(e1, e2) must not throw a + * ClassCastException for any elements e1 and + * e2 in the collection).

+ * + * This method iterates over the entire collection, hence it requires + * time proportional to the size of the collection. + * + * @param coll the collection whose maximum element is to be determined. + * @param comp the comparator with which to determine the maximum element. + * A null value indicates that the elements' natural + * ordering should be used. + * @return the maximum element of the given collection, according + * to the specified comparator. + * @throws ClassCastException if the collection contains elements that are + * not mutually comparable using the specified comparator. + * @throws NoSuchElementException if the collection is empty. + * @see Comparable + */ + public static T max(Collection coll, Comparator comp) { + if (comp==null) + return (T)max((Collection) (Collection) coll); + + Iterator i = coll.iterator(); + T candidate = i.next(); + + while (i.hasNext()) { + T next = i.next(); + if (comp.compare(next, candidate) > 0) + candidate = next; + } + return candidate; + } + + /** + * Rotates the elements in the specified list by the specified distance. + * After calling this method, the element at index i will be + * the element previously at index (i - distance) mod + * list.size(), for all values of i between 0 + * and list.size()-1, inclusive. (This method has no effect on + * the size of the list.) + * + *

For example, suppose list comprises [t, a, n, k, s]. + * After invoking Collections.rotate(list, 1) (or + * Collections.rotate(list, -4)), list will comprise + * [s, t, a, n, k]. + * + *

Note that this method can usefully be applied to sublists to + * move one or more elements within a list while preserving the + * order of the remaining elements. For example, the following idiom + * moves the element at index j forward to position + * k (which must be greater than or equal to j): + *

+     *     Collections.rotate(list.subList(j, k+1), -1);
+     * 
+ * To make this concrete, suppose list comprises + * [a, b, c, d, e]. To move the element at index 1 + * (b) forward two positions, perform the following invocation: + *
+     *     Collections.rotate(l.subList(1, 4), -1);
+     * 
+ * The resulting list is [a, c, d, b, e]. + * + *

To move more than one element forward, increase the absolute value + * of the rotation distance. To move elements backward, use a positive + * shift distance. + * + *

If the specified list is small or implements the {@link + * RandomAccess} interface, this implementation exchanges the first + * element into the location it should go, and then repeatedly exchanges + * the displaced element into the location it should go until a displaced + * element is swapped into the first element. If necessary, the process + * is repeated on the second and successive elements, until the rotation + * is complete. If the specified list is large and doesn't implement the + * RandomAccess interface, this implementation breaks the + * list into two sublist views around index -distance mod size. + * Then the {@link #reverse(List)} method is invoked on each sublist view, + * and finally it is invoked on the entire list. For a more complete + * description of both algorithms, see Section 2.3 of Jon Bentley's + * Programming Pearls (Addison-Wesley, 1986). + * + * @param list the list to be rotated. + * @param distance the distance to rotate the list. There are no + * constraints on this value; it may be zero, negative, or + * greater than list.size(). + * @throws UnsupportedOperationException if the specified list or + * its list-iterator does not support the set operation. + * @since 1.4 + */ + public static void rotate(List list, int distance) { + if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD) + rotate1(list, distance); + else + rotate2(list, distance); + } + + private static void rotate1(List list, int distance) { + int size = list.size(); + if (size == 0) + return; + distance = distance % size; + if (distance < 0) + distance += size; + if (distance == 0) + return; + + for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) { + T displaced = list.get(cycleStart); + int i = cycleStart; + do { + i += distance; + if (i >= size) + i -= size; + displaced = list.set(i, displaced); + nMoved ++; + } while (i != cycleStart); + } + } + + private static void rotate2(List list, int distance) { + int size = list.size(); + if (size == 0) + return; + int mid = -distance % size; + if (mid < 0) + mid += size; + if (mid == 0) + return; + + reverse(list.subList(0, mid)); + reverse(list.subList(mid, size)); + reverse(list); + } + + /** + * Replaces all occurrences of one specified value in a list with another. + * More formally, replaces with newVal each element e + * in list such that + * (oldVal==null ? e==null : oldVal.equals(e)). + * (This method has no effect on the size of the list.) + * + * @param list the list in which replacement is to occur. + * @param oldVal the old value to be replaced. + * @param newVal the new value with which oldVal is to be + * replaced. + * @return true if list contained one or more elements + * e such that + * (oldVal==null ? e==null : oldVal.equals(e)). + * @throws UnsupportedOperationException if the specified list or + * its list-iterator does not support the set operation. + * @since 1.4 + */ + public static boolean replaceAll(List list, T oldVal, T newVal) { + boolean result = false; + int size = list.size(); + if (size < REPLACEALL_THRESHOLD || list instanceof RandomAccess) { + if (oldVal==null) { + for (int i=0; i itr=list.listIterator(); + if (oldVal==null) { + for (int i=0; ii + * such that source.subList(i, i+target.size()).equals(target), + * or -1 if there is no such index. (Returns -1 if + * target.size() > source.size().) + * + *

This implementation uses the "brute force" technique of scanning + * over the source list, looking for a match with the target at each + * location in turn. + * + * @param source the list in which to search for the first occurrence + * of target. + * @param target the list to search for as a subList of source. + * @return the starting position of the first occurrence of the specified + * target list within the specified source list, or -1 if there + * is no such occurrence. + * @since 1.4 + */ + public static int indexOfSubList(List source, List target) { + int sourceSize = source.size(); + int targetSize = target.size(); + int maxCandidate = sourceSize - targetSize; + + if (sourceSize < INDEXOFSUBLIST_THRESHOLD || + (source instanceof RandomAccess&&target instanceof RandomAccess)) { + nextCand: + for (int candidate = 0; candidate <= maxCandidate; candidate++) { + for (int i=0, j=candidate; i si = source.listIterator(); + nextCand: + for (int candidate = 0; candidate <= maxCandidate; candidate++) { + ListIterator ti = target.listIterator(); + for (int i=0; ii + * such that source.subList(i, i+target.size()).equals(target), + * or -1 if there is no such index. (Returns -1 if + * target.size() > source.size().) + * + *

This implementation uses the "brute force" technique of iterating + * over the source list, looking for a match with the target at each + * location in turn. + * + * @param source the list in which to search for the last occurrence + * of target. + * @param target the list to search for as a subList of source. + * @return the starting position of the last occurrence of the specified + * target list within the specified source list, or -1 if there + * is no such occurrence. + * @since 1.4 + */ + public static int lastIndexOfSubList(List source, List target) { + int sourceSize = source.size(); + int targetSize = target.size(); + int maxCandidate = sourceSize - targetSize; + + if (sourceSize < INDEXOFSUBLIST_THRESHOLD || + source instanceof RandomAccess) { // Index access version + nextCand: + for (int candidate = maxCandidate; candidate >= 0; candidate--) { + for (int i=0, j=candidate; i si = source.listIterator(maxCandidate); + nextCand: + for (int candidate = maxCandidate; candidate >= 0; candidate--) { + ListIterator ti = target.listIterator(); + for (int i=0; iUnsupportedOperationException.

+ * + * The returned collection does not pass the hashCode and equals + * operations through to the backing collection, but relies on + * Object's equals and hashCode methods. This + * is necessary to preserve the contracts of these operations in the case + * that the backing collection is a set or a list.

+ * + * The returned collection will be serializable if the specified collection + * is serializable. + * + * @param c the collection for which an unmodifiable view is to be + * returned. + * @return an unmodifiable view of the specified collection. + */ + public static Collection unmodifiableCollection(Collection c) { + return new UnmodifiableCollection<>(c); + } + + /** + * @serial include + */ + static class UnmodifiableCollection implements Collection, Serializable { + private static final long serialVersionUID = 1820017752578914078L; + + final Collection c; + + UnmodifiableCollection(Collection c) { + if (c==null) + throw new NullPointerException(); + this.c = c; + } + + public int size() {return c.size();} + public boolean isEmpty() {return c.isEmpty();} + public boolean contains(Object o) {return c.contains(o);} + public Object[] toArray() {return c.toArray();} + public T[] toArray(T[] a) {return c.toArray(a);} + public String toString() {return c.toString();} + + public Iterator iterator() { + return new Iterator() { + private final Iterator i = c.iterator(); + + public boolean hasNext() {return i.hasNext();} + public E next() {return i.next();} + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + public boolean add(E e) { + throw new UnsupportedOperationException(); + } + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + public boolean containsAll(Collection coll) { + return c.containsAll(coll); + } + public boolean addAll(Collection coll) { + throw new UnsupportedOperationException(); + } + public boolean removeAll(Collection coll) { + throw new UnsupportedOperationException(); + } + public boolean retainAll(Collection coll) { + throw new UnsupportedOperationException(); + } + public void clear() { + throw new UnsupportedOperationException(); + } + } + + /** + * Returns an unmodifiable view of the specified set. This method allows + * modules to provide users with "read-only" access to internal sets. + * Query operations on the returned set "read through" to the specified + * set, and attempts to modify the returned set, whether direct or via its + * iterator, result in an UnsupportedOperationException.

+ * + * The returned set will be serializable if the specified set + * is serializable. + * + * @param s the set for which an unmodifiable view is to be returned. + * @return an unmodifiable view of the specified set. + */ + public static Set unmodifiableSet(Set s) { + return new UnmodifiableSet<>(s); + } + + /** + * @serial include + */ + static class UnmodifiableSet extends UnmodifiableCollection + implements Set, Serializable { + private static final long serialVersionUID = -9215047833775013803L; + + UnmodifiableSet(Set s) {super(s);} + public boolean equals(Object o) {return o == this || c.equals(o);} + public int hashCode() {return c.hashCode();} + } + + /** + * Returns an unmodifiable view of the specified sorted set. This method + * allows modules to provide users with "read-only" access to internal + * sorted sets. Query operations on the returned sorted set "read + * through" to the specified sorted set. Attempts to modify the returned + * sorted set, whether direct, via its iterator, or via its + * subSet, headSet, or tailSet views, result in + * an UnsupportedOperationException.

+ * + * The returned sorted set will be serializable if the specified sorted set + * is serializable. + * + * @param s the sorted set for which an unmodifiable view is to be + * returned. + * @return an unmodifiable view of the specified sorted set. + */ + public static SortedSet unmodifiableSortedSet(SortedSet s) { + return new UnmodifiableSortedSet<>(s); + } + + /** + * @serial include + */ + static class UnmodifiableSortedSet + extends UnmodifiableSet + implements SortedSet, Serializable { + private static final long serialVersionUID = -4929149591599911165L; + private final SortedSet ss; + + UnmodifiableSortedSet(SortedSet s) {super(s); ss = s;} + + public Comparator comparator() {return ss.comparator();} + + public SortedSet subSet(E fromElement, E toElement) { + return new UnmodifiableSortedSet<>(ss.subSet(fromElement,toElement)); + } + public SortedSet headSet(E toElement) { + return new UnmodifiableSortedSet<>(ss.headSet(toElement)); + } + public SortedSet tailSet(E fromElement) { + return new UnmodifiableSortedSet<>(ss.tailSet(fromElement)); + } + + public E first() {return ss.first();} + public E last() {return ss.last();} + } + + /** + * Returns an unmodifiable view of the specified list. This method allows + * modules to provide users with "read-only" access to internal + * lists. Query operations on the returned list "read through" to the + * specified list, and attempts to modify the returned list, whether + * direct or via its iterator, result in an + * UnsupportedOperationException.

+ * + * The returned list will be serializable if the specified list + * is serializable. Similarly, the returned list will implement + * {@link RandomAccess} if the specified list does. + * + * @param list the list for which an unmodifiable view is to be returned. + * @return an unmodifiable view of the specified list. + */ + public static List unmodifiableList(List list) { + return (list instanceof RandomAccess ? + new UnmodifiableRandomAccessList<>(list) : + new UnmodifiableList<>(list)); + } + + /** + * @serial include + */ + static class UnmodifiableList extends UnmodifiableCollection + implements List { + private static final long serialVersionUID = -283967356065247728L; + final List list; + + UnmodifiableList(List list) { + super(list); + this.list = list; + } + + public boolean equals(Object o) {return o == this || list.equals(o);} + public int hashCode() {return list.hashCode();} + + public E get(int index) {return list.get(index);} + public E set(int index, E element) { + throw new UnsupportedOperationException(); + } + public void add(int index, E element) { + throw new UnsupportedOperationException(); + } + public E remove(int index) { + throw new UnsupportedOperationException(); + } + public int indexOf(Object o) {return list.indexOf(o);} + public int lastIndexOf(Object o) {return list.lastIndexOf(o);} + public boolean addAll(int index, Collection c) { + throw new UnsupportedOperationException(); + } + public ListIterator listIterator() {return listIterator(0);} + + public ListIterator listIterator(final int index) { + return new ListIterator() { + private final ListIterator i + = list.listIterator(index); + + public boolean hasNext() {return i.hasNext();} + public E next() {return i.next();} + public boolean hasPrevious() {return i.hasPrevious();} + public E previous() {return i.previous();} + public int nextIndex() {return i.nextIndex();} + public int previousIndex() {return i.previousIndex();} + + public void remove() { + throw new UnsupportedOperationException(); + } + public void set(E e) { + throw new UnsupportedOperationException(); + } + public void add(E e) { + throw new UnsupportedOperationException(); + } + }; + } + + public List subList(int fromIndex, int toIndex) { + return new UnmodifiableList<>(list.subList(fromIndex, toIndex)); + } + + /** + * UnmodifiableRandomAccessList instances are serialized as + * UnmodifiableList instances to allow them to be deserialized + * in pre-1.4 JREs (which do not have UnmodifiableRandomAccessList). + * This method inverts the transformation. As a beneficial + * side-effect, it also grafts the RandomAccess marker onto + * UnmodifiableList instances that were serialized in pre-1.4 JREs. + * + * Note: Unfortunately, UnmodifiableRandomAccessList instances + * serialized in 1.4.1 and deserialized in 1.4 will become + * UnmodifiableList instances, as this method was missing in 1.4. + */ + private Object readResolve() { + return (list instanceof RandomAccess + ? new UnmodifiableRandomAccessList<>(list) + : this); + } + } + + /** + * @serial include + */ + static class UnmodifiableRandomAccessList extends UnmodifiableList + implements RandomAccess + { + UnmodifiableRandomAccessList(List list) { + super(list); + } + + public List subList(int fromIndex, int toIndex) { + return new UnmodifiableRandomAccessList<>( + list.subList(fromIndex, toIndex)); + } + + private static final long serialVersionUID = -2542308836966382001L; + + /** + * Allows instances to be deserialized in pre-1.4 JREs (which do + * not have UnmodifiableRandomAccessList). UnmodifiableList has + * a readResolve method that inverts this transformation upon + * deserialization. + */ + private Object writeReplace() { + return new UnmodifiableList<>(list); + } + } + + /** + * Returns an unmodifiable view of the specified map. This method + * allows modules to provide users with "read-only" access to internal + * maps. Query operations on the returned map "read through" + * to the specified map, and attempts to modify the returned + * map, whether direct or via its collection views, result in an + * UnsupportedOperationException.

+ * + * The returned map will be serializable if the specified map + * is serializable. + * + * @param m the map for which an unmodifiable view is to be returned. + * @return an unmodifiable view of the specified map. + */ + public static Map unmodifiableMap(Map m) { + return new UnmodifiableMap<>(m); + } + + /** + * @serial include + */ + private static class UnmodifiableMap implements Map, Serializable { + private static final long serialVersionUID = -1034234728574286014L; + + private final Map m; + + UnmodifiableMap(Map m) { + if (m==null) + throw new NullPointerException(); + this.m = m; + } + + public int size() {return m.size();} + public boolean isEmpty() {return m.isEmpty();} + public boolean containsKey(Object key) {return m.containsKey(key);} + public boolean containsValue(Object val) {return m.containsValue(val);} + public V get(Object key) {return m.get(key);} + + public V put(K key, V value) { + throw new UnsupportedOperationException(); + } + public V remove(Object key) { + throw new UnsupportedOperationException(); + } + public void putAll(Map m) { + throw new UnsupportedOperationException(); + } + public void clear() { + throw new UnsupportedOperationException(); + } + + private transient Set keySet = null; + private transient Set> entrySet = null; + private transient Collection values = null; + + public Set keySet() { + if (keySet==null) + keySet = unmodifiableSet(m.keySet()); + return keySet; + } + + public Set> entrySet() { + if (entrySet==null) + entrySet = new UnmodifiableEntrySet<>(m.entrySet()); + return entrySet; + } + + public Collection values() { + if (values==null) + values = unmodifiableCollection(m.values()); + return values; + } + + public boolean equals(Object o) {return o == this || m.equals(o);} + public int hashCode() {return m.hashCode();} + public String toString() {return m.toString();} + + /** + * We need this class in addition to UnmodifiableSet as + * Map.Entries themselves permit modification of the backing Map + * via their setValue operation. This class is subtle: there are + * many possible attacks that must be thwarted. + * + * @serial include + */ + static class UnmodifiableEntrySet + extends UnmodifiableSet> { + private static final long serialVersionUID = 7854390611657943733L; + + UnmodifiableEntrySet(Set> s) { + super((Set)s); + } + public Iterator> iterator() { + return new Iterator>() { + private final Iterator> i = c.iterator(); + + public boolean hasNext() { + return i.hasNext(); + } + public Map.Entry next() { + return new UnmodifiableEntry<>(i.next()); + } + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + public Object[] toArray() { + Object[] a = c.toArray(); + for (int i=0; i((Map.Entry)a[i]); + return a; + } + + public T[] toArray(T[] a) { + // We don't pass a to c.toArray, to avoid window of + // vulnerability wherein an unscrupulous multithreaded client + // could get his hands on raw (unwrapped) Entries from c. + Object[] arr = c.toArray(a.length==0 ? a : Arrays.copyOf(a, 0)); + + for (int i=0; i((Map.Entry)arr[i]); + + if (arr.length > a.length) + return (T[])arr; + + System.arraycopy(arr, 0, a, 0, arr.length); + if (a.length > arr.length) + a[arr.length] = null; + return a; + } + + /** + * This method is overridden to protect the backing set against + * an object with a nefarious equals function that senses + * that the equality-candidate is Map.Entry and calls its + * setValue method. + */ + public boolean contains(Object o) { + if (!(o instanceof Map.Entry)) + return false; + return c.contains( + new UnmodifiableEntry<>((Map.Entry) o)); + } + + /** + * The next two methods are overridden to protect against + * an unscrupulous List whose contains(Object o) method senses + * when o is a Map.Entry, and calls o.setValue. + */ + public boolean containsAll(Collection coll) { + for (Object e : coll) { + if (!contains(e)) // Invokes safe contains() above + return false; + } + return true; + } + public boolean equals(Object o) { + if (o == this) + return true; + + if (!(o instanceof Set)) + return false; + Set s = (Set) o; + if (s.size() != c.size()) + return false; + return containsAll(s); // Invokes safe containsAll() above + } + + /** + * This "wrapper class" serves two purposes: it prevents + * the client from modifying the backing Map, by short-circuiting + * the setValue method, and it protects the backing Map against + * an ill-behaved Map.Entry that attempts to modify another + * Map Entry when asked to perform an equality check. + */ + private static class UnmodifiableEntry implements Map.Entry { + private Map.Entry e; + + UnmodifiableEntry(Map.Entry e) {this.e = e;} + + public K getKey() {return e.getKey();} + public V getValue() {return e.getValue();} + public V setValue(V value) { + throw new UnsupportedOperationException(); + } + public int hashCode() {return e.hashCode();} + public boolean equals(Object o) { + if (!(o instanceof Map.Entry)) + return false; + Map.Entry t = (Map.Entry)o; + return eq(e.getKey(), t.getKey()) && + eq(e.getValue(), t.getValue()); + } + public String toString() {return e.toString();} + } + } + } + + /** + * Returns an unmodifiable view of the specified sorted map. This method + * allows modules to provide users with "read-only" access to internal + * sorted maps. Query operations on the returned sorted map "read through" + * to the specified sorted map. Attempts to modify the returned + * sorted map, whether direct, via its collection views, or via its + * subMap, headMap, or tailMap views, result in + * an UnsupportedOperationException.

+ * + * The returned sorted map will be serializable if the specified sorted map + * is serializable. + * + * @param m the sorted map for which an unmodifiable view is to be + * returned. + * @return an unmodifiable view of the specified sorted map. + */ + public static SortedMap unmodifiableSortedMap(SortedMap m) { + return new UnmodifiableSortedMap<>(m); + } + + /** + * @serial include + */ + static class UnmodifiableSortedMap + extends UnmodifiableMap + implements SortedMap, Serializable { + private static final long serialVersionUID = -8806743815996713206L; + + private final SortedMap sm; + + UnmodifiableSortedMap(SortedMap m) {super(m); sm = m;} + + public Comparator comparator() {return sm.comparator();} + + public SortedMap subMap(K fromKey, K toKey) { + return new UnmodifiableSortedMap<>(sm.subMap(fromKey, toKey)); + } + public SortedMap headMap(K toKey) { + return new UnmodifiableSortedMap<>(sm.headMap(toKey)); + } + public SortedMap tailMap(K fromKey) { + return new UnmodifiableSortedMap<>(sm.tailMap(fromKey)); + } + + public K firstKey() {return sm.firstKey();} + public K lastKey() {return sm.lastKey();} + } + + + // Synch Wrappers + + /** + * Returns a synchronized (thread-safe) collection backed by the specified + * collection. In order to guarantee serial access, it is critical that + * all access to the backing collection is accomplished + * through the returned collection.

+ * + * It is imperative that the user manually synchronize on the returned + * collection when iterating over it: + *

+     *  Collection c = Collections.synchronizedCollection(myCollection);
+     *     ...
+     *  synchronized (c) {
+     *      Iterator i = c.iterator(); // Must be in the synchronized block
+     *      while (i.hasNext())
+     *         foo(i.next());
+     *  }
+     * 
+ * Failure to follow this advice may result in non-deterministic behavior. + * + *

The returned collection does not pass the hashCode + * and equals operations through to the backing collection, but + * relies on Object's equals and hashCode methods. This is + * necessary to preserve the contracts of these operations in the case + * that the backing collection is a set or a list.

+ * + * The returned collection will be serializable if the specified collection + * is serializable. + * + * @param c the collection to be "wrapped" in a synchronized collection. + * @return a synchronized view of the specified collection. + */ + public static Collection synchronizedCollection(Collection c) { + return new SynchronizedCollection<>(c); + } + + static Collection synchronizedCollection(Collection c, Object mutex) { + return new SynchronizedCollection<>(c, mutex); + } + + /** + * @serial include + */ + static class SynchronizedCollection implements Collection, Serializable { + private static final long serialVersionUID = 3053995032091335093L; + + final Collection c; // Backing Collection + final Object mutex; // Object on which to synchronize + + SynchronizedCollection(Collection c) { + if (c==null) + throw new NullPointerException(); + this.c = c; + mutex = this; + } + SynchronizedCollection(Collection c, Object mutex) { + this.c = c; + this.mutex = mutex; + } + + public int size() { + synchronized (mutex) {return c.size();} + } + public boolean isEmpty() { + synchronized (mutex) {return c.isEmpty();} + } + public boolean contains(Object o) { + synchronized (mutex) {return c.contains(o);} + } + public Object[] toArray() { + synchronized (mutex) {return c.toArray();} + } + public T[] toArray(T[] a) { + synchronized (mutex) {return c.toArray(a);} + } + + public Iterator iterator() { + return c.iterator(); // Must be manually synched by user! + } + + public boolean add(E e) { + synchronized (mutex) {return c.add(e);} + } + public boolean remove(Object o) { + synchronized (mutex) {return c.remove(o);} + } + + public boolean containsAll(Collection coll) { + synchronized (mutex) {return c.containsAll(coll);} + } + public boolean addAll(Collection coll) { + synchronized (mutex) {return c.addAll(coll);} + } + public boolean removeAll(Collection coll) { + synchronized (mutex) {return c.removeAll(coll);} + } + public boolean retainAll(Collection coll) { + synchronized (mutex) {return c.retainAll(coll);} + } + public void clear() { + synchronized (mutex) {c.clear();} + } + public String toString() { + synchronized (mutex) {return c.toString();} + } + private void writeObject(ObjectOutputStream s) throws IOException { + synchronized (mutex) {s.defaultWriteObject();} + } + } + + /** + * Returns a synchronized (thread-safe) set backed by the specified + * set. In order to guarantee serial access, it is critical that + * all access to the backing set is accomplished + * through the returned set.

+ * + * It is imperative that the user manually synchronize on the returned + * set when iterating over it: + *

+     *  Set s = Collections.synchronizedSet(new HashSet());
+     *      ...
+     *  synchronized (s) {
+     *      Iterator i = s.iterator(); // Must be in the synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * 
+ * Failure to follow this advice may result in non-deterministic behavior. + * + *

The returned set will be serializable if the specified set is + * serializable. + * + * @param s the set to be "wrapped" in a synchronized set. + * @return a synchronized view of the specified set. + */ + public static Set synchronizedSet(Set s) { + return new SynchronizedSet<>(s); + } + + static Set synchronizedSet(Set s, Object mutex) { + return new SynchronizedSet<>(s, mutex); + } + + /** + * @serial include + */ + static class SynchronizedSet + extends SynchronizedCollection + implements Set { + private static final long serialVersionUID = 487447009682186044L; + + SynchronizedSet(Set s) { + super(s); + } + SynchronizedSet(Set s, Object mutex) { + super(s, mutex); + } + + public boolean equals(Object o) { + synchronized (mutex) {return c.equals(o);} + } + public int hashCode() { + synchronized (mutex) {return c.hashCode();} + } + } + + /** + * Returns a synchronized (thread-safe) sorted set backed by the specified + * sorted set. In order to guarantee serial access, it is critical that + * all access to the backing sorted set is accomplished + * through the returned sorted set (or its views).

+ * + * It is imperative that the user manually synchronize on the returned + * sorted set when iterating over it or any of its subSet, + * headSet, or tailSet views. + *

+     *  SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
+     *      ...
+     *  synchronized (s) {
+     *      Iterator i = s.iterator(); // Must be in the synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * 
+ * or: + *
+     *  SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
+     *  SortedSet s2 = s.headSet(foo);
+     *      ...
+     *  synchronized (s) {  // Note: s, not s2!!!
+     *      Iterator i = s2.iterator(); // Must be in the synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * 
+ * Failure to follow this advice may result in non-deterministic behavior. + * + *

The returned sorted set will be serializable if the specified + * sorted set is serializable. + * + * @param s the sorted set to be "wrapped" in a synchronized sorted set. + * @return a synchronized view of the specified sorted set. + */ + public static SortedSet synchronizedSortedSet(SortedSet s) { + return new SynchronizedSortedSet<>(s); + } + + /** + * @serial include + */ + static class SynchronizedSortedSet + extends SynchronizedSet + implements SortedSet + { + private static final long serialVersionUID = 8695801310862127406L; + + private final SortedSet ss; + + SynchronizedSortedSet(SortedSet s) { + super(s); + ss = s; + } + SynchronizedSortedSet(SortedSet s, Object mutex) { + super(s, mutex); + ss = s; + } + + public Comparator comparator() { + synchronized (mutex) {return ss.comparator();} + } + + public SortedSet subSet(E fromElement, E toElement) { + synchronized (mutex) { + return new SynchronizedSortedSet<>( + ss.subSet(fromElement, toElement), mutex); + } + } + public SortedSet headSet(E toElement) { + synchronized (mutex) { + return new SynchronizedSortedSet<>(ss.headSet(toElement), mutex); + } + } + public SortedSet tailSet(E fromElement) { + synchronized (mutex) { + return new SynchronizedSortedSet<>(ss.tailSet(fromElement),mutex); + } + } + + public E first() { + synchronized (mutex) {return ss.first();} + } + public E last() { + synchronized (mutex) {return ss.last();} + } + } + + /** + * Returns a synchronized (thread-safe) list backed by the specified + * list. In order to guarantee serial access, it is critical that + * all access to the backing list is accomplished + * through the returned list.

+ * + * It is imperative that the user manually synchronize on the returned + * list when iterating over it: + *

+     *  List list = Collections.synchronizedList(new ArrayList());
+     *      ...
+     *  synchronized (list) {
+     *      Iterator i = list.iterator(); // Must be in synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * 
+ * Failure to follow this advice may result in non-deterministic behavior. + * + *

The returned list will be serializable if the specified list is + * serializable. + * + * @param list the list to be "wrapped" in a synchronized list. + * @return a synchronized view of the specified list. + */ + public static List synchronizedList(List list) { + return (list instanceof RandomAccess ? + new SynchronizedRandomAccessList<>(list) : + new SynchronizedList<>(list)); + } + + static List synchronizedList(List list, Object mutex) { + return (list instanceof RandomAccess ? + new SynchronizedRandomAccessList<>(list, mutex) : + new SynchronizedList<>(list, mutex)); + } + + /** + * @serial include + */ + static class SynchronizedList + extends SynchronizedCollection + implements List { + private static final long serialVersionUID = -7754090372962971524L; + + final List list; + + SynchronizedList(List list) { + super(list); + this.list = list; + } + SynchronizedList(List list, Object mutex) { + super(list, mutex); + this.list = list; + } + + public boolean equals(Object o) { + synchronized (mutex) {return list.equals(o);} + } + public int hashCode() { + synchronized (mutex) {return list.hashCode();} + } + + public E get(int index) { + synchronized (mutex) {return list.get(index);} + } + public E set(int index, E element) { + synchronized (mutex) {return list.set(index, element);} + } + public void add(int index, E element) { + synchronized (mutex) {list.add(index, element);} + } + public E remove(int index) { + synchronized (mutex) {return list.remove(index);} + } + + public int indexOf(Object o) { + synchronized (mutex) {return list.indexOf(o);} + } + public int lastIndexOf(Object o) { + synchronized (mutex) {return list.lastIndexOf(o);} + } + + public boolean addAll(int index, Collection c) { + synchronized (mutex) {return list.addAll(index, c);} + } + + public ListIterator listIterator() { + return list.listIterator(); // Must be manually synched by user + } + + public ListIterator listIterator(int index) { + return list.listIterator(index); // Must be manually synched by user + } + + public List subList(int fromIndex, int toIndex) { + synchronized (mutex) { + return new SynchronizedList<>(list.subList(fromIndex, toIndex), + mutex); + } + } + + /** + * SynchronizedRandomAccessList instances are serialized as + * SynchronizedList instances to allow them to be deserialized + * in pre-1.4 JREs (which do not have SynchronizedRandomAccessList). + * This method inverts the transformation. As a beneficial + * side-effect, it also grafts the RandomAccess marker onto + * SynchronizedList instances that were serialized in pre-1.4 JREs. + * + * Note: Unfortunately, SynchronizedRandomAccessList instances + * serialized in 1.4.1 and deserialized in 1.4 will become + * SynchronizedList instances, as this method was missing in 1.4. + */ + private Object readResolve() { + return (list instanceof RandomAccess + ? new SynchronizedRandomAccessList<>(list) + : this); + } + } + + /** + * @serial include + */ + static class SynchronizedRandomAccessList + extends SynchronizedList + implements RandomAccess { + + SynchronizedRandomAccessList(List list) { + super(list); + } + + SynchronizedRandomAccessList(List list, Object mutex) { + super(list, mutex); + } + + public List subList(int fromIndex, int toIndex) { + synchronized (mutex) { + return new SynchronizedRandomAccessList<>( + list.subList(fromIndex, toIndex), mutex); + } + } + + private static final long serialVersionUID = 1530674583602358482L; + + /** + * Allows instances to be deserialized in pre-1.4 JREs (which do + * not have SynchronizedRandomAccessList). SynchronizedList has + * a readResolve method that inverts this transformation upon + * deserialization. + */ + private Object writeReplace() { + return new SynchronizedList<>(list); + } + } + + /** + * Returns a synchronized (thread-safe) map backed by the specified + * map. In order to guarantee serial access, it is critical that + * all access to the backing map is accomplished + * through the returned map.

+ * + * It is imperative that the user manually synchronize on the returned + * map when iterating over any of its collection views: + *

+     *  Map m = Collections.synchronizedMap(new HashMap());
+     *      ...
+     *  Set s = m.keySet();  // Needn't be in synchronized block
+     *      ...
+     *  synchronized (m) {  // Synchronizing on m, not s!
+     *      Iterator i = s.iterator(); // Must be in synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * 
+ * Failure to follow this advice may result in non-deterministic behavior. + * + *

The returned map will be serializable if the specified map is + * serializable. + * + * @param m the map to be "wrapped" in a synchronized map. + * @return a synchronized view of the specified map. + */ + public static Map synchronizedMap(Map m) { + return new SynchronizedMap<>(m); + } + + /** + * @serial include + */ + private static class SynchronizedMap + implements Map, Serializable { + private static final long serialVersionUID = 1978198479659022715L; + + private final Map m; // Backing Map + final Object mutex; // Object on which to synchronize + + SynchronizedMap(Map m) { + if (m==null) + throw new NullPointerException(); + this.m = m; + mutex = this; + } + + SynchronizedMap(Map m, Object mutex) { + this.m = m; + this.mutex = mutex; + } + + public int size() { + synchronized (mutex) {return m.size();} + } + public boolean isEmpty() { + synchronized (mutex) {return m.isEmpty();} + } + public boolean containsKey(Object key) { + synchronized (mutex) {return m.containsKey(key);} + } + public boolean containsValue(Object value) { + synchronized (mutex) {return m.containsValue(value);} + } + public V get(Object key) { + synchronized (mutex) {return m.get(key);} + } + + public V put(K key, V value) { + synchronized (mutex) {return m.put(key, value);} + } + public V remove(Object key) { + synchronized (mutex) {return m.remove(key);} + } + public void putAll(Map map) { + synchronized (mutex) {m.putAll(map);} + } + public void clear() { + synchronized (mutex) {m.clear();} + } + + private transient Set keySet = null; + private transient Set> entrySet = null; + private transient Collection values = null; + + public Set keySet() { + synchronized (mutex) { + if (keySet==null) + keySet = new SynchronizedSet<>(m.keySet(), mutex); + return keySet; + } + } + + public Set> entrySet() { + synchronized (mutex) { + if (entrySet==null) + entrySet = new SynchronizedSet<>(m.entrySet(), mutex); + return entrySet; + } + } + + public Collection values() { + synchronized (mutex) { + if (values==null) + values = new SynchronizedCollection<>(m.values(), mutex); + return values; + } + } + + public boolean equals(Object o) { + synchronized (mutex) {return m.equals(o);} + } + public int hashCode() { + synchronized (mutex) {return m.hashCode();} + } + public String toString() { + synchronized (mutex) {return m.toString();} + } + private void writeObject(ObjectOutputStream s) throws IOException { + synchronized (mutex) {s.defaultWriteObject();} + } + } + + /** + * Returns a synchronized (thread-safe) sorted map backed by the specified + * sorted map. In order to guarantee serial access, it is critical that + * all access to the backing sorted map is accomplished + * through the returned sorted map (or its views).

+ * + * It is imperative that the user manually synchronize on the returned + * sorted map when iterating over any of its collection views, or the + * collections views of any of its subMap, headMap or + * tailMap views. + *

+     *  SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
+     *      ...
+     *  Set s = m.keySet();  // Needn't be in synchronized block
+     *      ...
+     *  synchronized (m) {  // Synchronizing on m, not s!
+     *      Iterator i = s.iterator(); // Must be in synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * 
+ * or: + *
+     *  SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
+     *  SortedMap m2 = m.subMap(foo, bar);
+     *      ...
+     *  Set s2 = m2.keySet();  // Needn't be in synchronized block
+     *      ...
+     *  synchronized (m) {  // Synchronizing on m, not m2 or s2!
+     *      Iterator i = s.iterator(); // Must be in synchronized block
+     *      while (i.hasNext())
+     *          foo(i.next());
+     *  }
+     * 
+ * Failure to follow this advice may result in non-deterministic behavior. + * + *

The returned sorted map will be serializable if the specified + * sorted map is serializable. + * + * @param m the sorted map to be "wrapped" in a synchronized sorted map. + * @return a synchronized view of the specified sorted map. + */ + public static SortedMap synchronizedSortedMap(SortedMap m) { + return new SynchronizedSortedMap<>(m); + } + + + /** + * @serial include + */ + static class SynchronizedSortedMap + extends SynchronizedMap + implements SortedMap + { + private static final long serialVersionUID = -8798146769416483793L; + + private final SortedMap sm; + + SynchronizedSortedMap(SortedMap m) { + super(m); + sm = m; + } + SynchronizedSortedMap(SortedMap m, Object mutex) { + super(m, mutex); + sm = m; + } + + public Comparator comparator() { + synchronized (mutex) {return sm.comparator();} + } + + public SortedMap subMap(K fromKey, K toKey) { + synchronized (mutex) { + return new SynchronizedSortedMap<>( + sm.subMap(fromKey, toKey), mutex); + } + } + public SortedMap headMap(K toKey) { + synchronized (mutex) { + return new SynchronizedSortedMap<>(sm.headMap(toKey), mutex); + } + } + public SortedMap tailMap(K fromKey) { + synchronized (mutex) { + return new SynchronizedSortedMap<>(sm.tailMap(fromKey),mutex); + } + } + + public K firstKey() { + synchronized (mutex) {return sm.firstKey();} + } + public K lastKey() { + synchronized (mutex) {return sm.lastKey();} + } + } + + // Dynamically typesafe collection wrappers + + /** + * Returns a dynamically typesafe view of the specified collection. + * Any attempt to insert an element of the wrong type will result in an + * immediate {@link ClassCastException}. Assuming a collection + * contains no incorrectly typed elements prior to the time a + * dynamically typesafe view is generated, and that all subsequent + * access to the collection takes place through the view, it is + * guaranteed that the collection cannot contain an incorrectly + * typed element. + * + *

The generics mechanism in the language provides compile-time + * (static) type checking, but it is possible to defeat this mechanism + * with unchecked casts. Usually this is not a problem, as the compiler + * issues warnings on all such unchecked operations. There are, however, + * times when static type checking alone is not sufficient. For example, + * suppose a collection is passed to a third-party library and it is + * imperative that the library code not corrupt the collection by + * inserting an element of the wrong type. + * + *

Another use of dynamically typesafe views is debugging. Suppose a + * program fails with a {@code ClassCastException}, indicating that an + * incorrectly typed element was put into a parameterized collection. + * Unfortunately, the exception can occur at any time after the erroneous + * element is inserted, so it typically provides little or no information + * as to the real source of the problem. If the problem is reproducible, + * one can quickly determine its source by temporarily modifying the + * program to wrap the collection with a dynamically typesafe view. + * For example, this declaration: + *

 {@code
+     *     Collection c = new HashSet();
+     * }
+ * may be replaced temporarily by this one: + *
 {@code
+     *     Collection c = Collections.checkedCollection(
+     *         new HashSet(), String.class);
+     * }
+ * Running the program again will cause it to fail at the point where + * an incorrectly typed element is inserted into the collection, clearly + * identifying the source of the problem. Once the problem is fixed, the + * modified declaration may be reverted back to the original. + * + *

The returned collection does not pass the hashCode and equals + * operations through to the backing collection, but relies on + * {@code Object}'s {@code equals} and {@code hashCode} methods. This + * is necessary to preserve the contracts of these operations in the case + * that the backing collection is a set or a list. + * + *

The returned collection will be serializable if the specified + * collection is serializable. + * + *

Since {@code null} is considered to be a value of any reference + * type, the returned collection permits insertion of null elements + * whenever the backing collection does. + * + * @param c the collection for which a dynamically typesafe view is to be + * returned + * @param type the type of element that {@code c} is permitted to hold + * @return a dynamically typesafe view of the specified collection + * @since 1.5 + */ + public static Collection checkedCollection(Collection c, + Class type) { + return new CheckedCollection<>(c, type); + } + + @SuppressWarnings("unchecked") + static T[] zeroLengthArray(Class type) { + return (T[]) Array.newInstance(type, 0); + } + + /** + * @serial include + */ + static class CheckedCollection implements Collection, Serializable { + private static final long serialVersionUID = 1578914078182001775L; + + final Collection c; + final Class type; + + void typeCheck(Object o) { + if (o != null && !type.isInstance(o)) + throw new ClassCastException(badElementMsg(o)); + } + + private String badElementMsg(Object o) { + return "Attempt to insert " + o.getClass() + + " element into collection with element type " + type; + } + + CheckedCollection(Collection c, Class type) { + if (c==null || type == null) + throw new NullPointerException(); + this.c = c; + this.type = type; + } + + public int size() { return c.size(); } + public boolean isEmpty() { return c.isEmpty(); } + public boolean contains(Object o) { return c.contains(o); } + public Object[] toArray() { return c.toArray(); } + public T[] toArray(T[] a) { return c.toArray(a); } + public String toString() { return c.toString(); } + public boolean remove(Object o) { return c.remove(o); } + public void clear() { c.clear(); } + + public boolean containsAll(Collection coll) { + return c.containsAll(coll); + } + public boolean removeAll(Collection coll) { + return c.removeAll(coll); + } + public boolean retainAll(Collection coll) { + return c.retainAll(coll); + } + + public Iterator iterator() { + final Iterator it = c.iterator(); + return new Iterator() { + public boolean hasNext() { return it.hasNext(); } + public E next() { return it.next(); } + public void remove() { it.remove(); }}; + } + + public boolean add(E e) { + typeCheck(e); + return c.add(e); + } + + private E[] zeroLengthElementArray = null; // Lazily initialized + + private E[] zeroLengthElementArray() { + return zeroLengthElementArray != null ? zeroLengthElementArray : + (zeroLengthElementArray = zeroLengthArray(type)); + } + + @SuppressWarnings("unchecked") + Collection checkedCopyOf(Collection coll) { + Object[] a = null; + try { + E[] z = zeroLengthElementArray(); + a = coll.toArray(z); + // Defend against coll violating the toArray contract + if (a.getClass() != z.getClass()) + a = Arrays.copyOf(a, a.length, z.getClass()); + } catch (ArrayStoreException ignore) { + // To get better and consistent diagnostics, + // we call typeCheck explicitly on each element. + // We call clone() to defend against coll retaining a + // reference to the returned array and storing a bad + // element into it after it has been type checked. + a = coll.toArray().clone(); + for (Object o : a) + typeCheck(o); + } + // A slight abuse of the type system, but safe here. + return (Collection) Arrays.asList(a); + } + + public boolean addAll(Collection coll) { + // Doing things this way insulates us from concurrent changes + // in the contents of coll and provides all-or-nothing + // semantics (which we wouldn't get if we type-checked each + // element as we added it) + return c.addAll(checkedCopyOf(coll)); + } + } + + /** + * Returns a dynamically typesafe view of the specified set. + * Any attempt to insert an element of the wrong type will result in + * an immediate {@link ClassCastException}. Assuming a set contains + * no incorrectly typed elements prior to the time a dynamically typesafe + * view is generated, and that all subsequent access to the set + * takes place through the view, it is guaranteed that the + * set cannot contain an incorrectly typed element. + * + *

A discussion of the use of dynamically typesafe views may be + * found in the documentation for the {@link #checkedCollection + * checkedCollection} method. + * + *

The returned set will be serializable if the specified set is + * serializable. + * + *

Since {@code null} is considered to be a value of any reference + * type, the returned set permits insertion of null elements whenever + * the backing set does. + * + * @param s the set for which a dynamically typesafe view is to be + * returned + * @param type the type of element that {@code s} is permitted to hold + * @return a dynamically typesafe view of the specified set + * @since 1.5 + */ + public static Set checkedSet(Set s, Class type) { + return new CheckedSet<>(s, type); + } + + /** + * @serial include + */ + static class CheckedSet extends CheckedCollection + implements Set, Serializable + { + private static final long serialVersionUID = 4694047833775013803L; + + CheckedSet(Set s, Class elementType) { super(s, elementType); } + + public boolean equals(Object o) { return o == this || c.equals(o); } + public int hashCode() { return c.hashCode(); } + } + + /** + * Returns a dynamically typesafe view of the specified sorted set. + * Any attempt to insert an element of the wrong type will result in an + * immediate {@link ClassCastException}. Assuming a sorted set + * contains no incorrectly typed elements prior to the time a + * dynamically typesafe view is generated, and that all subsequent + * access to the sorted set takes place through the view, it is + * guaranteed that the sorted set cannot contain an incorrectly + * typed element. + * + *

A discussion of the use of dynamically typesafe views may be + * found in the documentation for the {@link #checkedCollection + * checkedCollection} method. + * + *

The returned sorted set will be serializable if the specified sorted + * set is serializable. + * + *

Since {@code null} is considered to be a value of any reference + * type, the returned sorted set permits insertion of null elements + * whenever the backing sorted set does. + * + * @param s the sorted set for which a dynamically typesafe view is to be + * returned + * @param type the type of element that {@code s} is permitted to hold + * @return a dynamically typesafe view of the specified sorted set + * @since 1.5 + */ + public static SortedSet checkedSortedSet(SortedSet s, + Class type) { + return new CheckedSortedSet<>(s, type); + } + + /** + * @serial include + */ + static class CheckedSortedSet extends CheckedSet + implements SortedSet, Serializable + { + private static final long serialVersionUID = 1599911165492914959L; + private final SortedSet ss; + + CheckedSortedSet(SortedSet s, Class type) { + super(s, type); + ss = s; + } + + public Comparator comparator() { return ss.comparator(); } + public E first() { return ss.first(); } + public E last() { return ss.last(); } + + public SortedSet subSet(E fromElement, E toElement) { + return checkedSortedSet(ss.subSet(fromElement,toElement), type); + } + public SortedSet headSet(E toElement) { + return checkedSortedSet(ss.headSet(toElement), type); + } + public SortedSet tailSet(E fromElement) { + return checkedSortedSet(ss.tailSet(fromElement), type); + } + } + + /** + * Returns a dynamically typesafe view of the specified list. + * Any attempt to insert an element of the wrong type will result in + * an immediate {@link ClassCastException}. Assuming a list contains + * no incorrectly typed elements prior to the time a dynamically typesafe + * view is generated, and that all subsequent access to the list + * takes place through the view, it is guaranteed that the + * list cannot contain an incorrectly typed element. + * + *

A discussion of the use of dynamically typesafe views may be + * found in the documentation for the {@link #checkedCollection + * checkedCollection} method. + * + *

The returned list will be serializable if the specified list + * is serializable. + * + *

Since {@code null} is considered to be a value of any reference + * type, the returned list permits insertion of null elements whenever + * the backing list does. + * + * @param list the list for which a dynamically typesafe view is to be + * returned + * @param type the type of element that {@code list} is permitted to hold + * @return a dynamically typesafe view of the specified list + * @since 1.5 + */ + public static List checkedList(List list, Class type) { + return (list instanceof RandomAccess ? + new CheckedRandomAccessList<>(list, type) : + new CheckedList<>(list, type)); + } + + /** + * @serial include + */ + static class CheckedList + extends CheckedCollection + implements List + { + private static final long serialVersionUID = 65247728283967356L; + final List list; + + CheckedList(List list, Class type) { + super(list, type); + this.list = list; + } + + public boolean equals(Object o) { return o == this || list.equals(o); } + public int hashCode() { return list.hashCode(); } + public E get(int index) { return list.get(index); } + public E remove(int index) { return list.remove(index); } + public int indexOf(Object o) { return list.indexOf(o); } + public int lastIndexOf(Object o) { return list.lastIndexOf(o); } + + public E set(int index, E element) { + typeCheck(element); + return list.set(index, element); + } + + public void add(int index, E element) { + typeCheck(element); + list.add(index, element); + } + + public boolean addAll(int index, Collection c) { + return list.addAll(index, checkedCopyOf(c)); + } + public ListIterator listIterator() { return listIterator(0); } + + public ListIterator listIterator(final int index) { + final ListIterator i = list.listIterator(index); + + return new ListIterator() { + public boolean hasNext() { return i.hasNext(); } + public E next() { return i.next(); } + public boolean hasPrevious() { return i.hasPrevious(); } + public E previous() { return i.previous(); } + public int nextIndex() { return i.nextIndex(); } + public int previousIndex() { return i.previousIndex(); } + public void remove() { i.remove(); } + + public void set(E e) { + typeCheck(e); + i.set(e); + } + + public void add(E e) { + typeCheck(e); + i.add(e); + } + }; + } + + public List subList(int fromIndex, int toIndex) { + return new CheckedList<>(list.subList(fromIndex, toIndex), type); + } + } + + /** + * @serial include + */ + static class CheckedRandomAccessList extends CheckedList + implements RandomAccess + { + private static final long serialVersionUID = 1638200125423088369L; + + CheckedRandomAccessList(List list, Class type) { + super(list, type); + } + + public List subList(int fromIndex, int toIndex) { + return new CheckedRandomAccessList<>( + list.subList(fromIndex, toIndex), type); + } + } + + /** + * Returns a dynamically typesafe view of the specified map. + * Any attempt to insert a mapping whose key or value have the wrong + * type will result in an immediate {@link ClassCastException}. + * Similarly, any attempt to modify the value currently associated with + * a key will result in an immediate {@link ClassCastException}, + * whether the modification is attempted directly through the map + * itself, or through a {@link Map.Entry} instance obtained from the + * map's {@link Map#entrySet() entry set} view. + * + *

Assuming a map contains no incorrectly typed keys or values + * prior to the time a dynamically typesafe view is generated, and + * that all subsequent access to the map takes place through the view + * (or one of its collection views), it is guaranteed that the + * map cannot contain an incorrectly typed key or value. + * + *

A discussion of the use of dynamically typesafe views may be + * found in the documentation for the {@link #checkedCollection + * checkedCollection} method. + * + *

The returned map will be serializable if the specified map is + * serializable. + * + *

Since {@code null} is considered to be a value of any reference + * type, the returned map permits insertion of null keys or values + * whenever the backing map does. + * + * @param m the map for which a dynamically typesafe view is to be + * returned + * @param keyType the type of key that {@code m} is permitted to hold + * @param valueType the type of value that {@code m} is permitted to hold + * @return a dynamically typesafe view of the specified map + * @since 1.5 + */ + public static Map checkedMap(Map m, + Class keyType, + Class valueType) { + return new CheckedMap<>(m, keyType, valueType); + } + + + /** + * @serial include + */ + private static class CheckedMap + implements Map, Serializable + { + private static final long serialVersionUID = 5742860141034234728L; + + private final Map m; + final Class keyType; + final Class valueType; + + private void typeCheck(Object key, Object value) { + if (key != null && !keyType.isInstance(key)) + throw new ClassCastException(badKeyMsg(key)); + + if (value != null && !valueType.isInstance(value)) + throw new ClassCastException(badValueMsg(value)); + } + + private String badKeyMsg(Object key) { + return "Attempt to insert " + key.getClass() + + " key into map with key type " + keyType; + } + + private String badValueMsg(Object value) { + return "Attempt to insert " + value.getClass() + + " value into map with value type " + valueType; + } + + CheckedMap(Map m, Class keyType, Class valueType) { + if (m == null || keyType == null || valueType == null) + throw new NullPointerException(); + this.m = m; + this.keyType = keyType; + this.valueType = valueType; + } + + public int size() { return m.size(); } + public boolean isEmpty() { return m.isEmpty(); } + public boolean containsKey(Object key) { return m.containsKey(key); } + public boolean containsValue(Object v) { return m.containsValue(v); } + public V get(Object key) { return m.get(key); } + public V remove(Object key) { return m.remove(key); } + public void clear() { m.clear(); } + public Set keySet() { return m.keySet(); } + public Collection values() { return m.values(); } + public boolean equals(Object o) { return o == this || m.equals(o); } + public int hashCode() { return m.hashCode(); } + public String toString() { return m.toString(); } + + public V put(K key, V value) { + typeCheck(key, value); + return m.put(key, value); + } + + @SuppressWarnings("unchecked") + public void putAll(Map t) { + // Satisfy the following goals: + // - good diagnostics in case of type mismatch + // - all-or-nothing semantics + // - protection from malicious t + // - correct behavior if t is a concurrent map + Object[] entries = t.entrySet().toArray(); + List> checked = new ArrayList<>(entries.length); + for (Object o : entries) { + Map.Entry e = (Map.Entry) o; + Object k = e.getKey(); + Object v = e.getValue(); + typeCheck(k, v); + checked.add( + new AbstractMap.SimpleImmutableEntry<>((K) k, (V) v)); + } + for (Map.Entry e : checked) + m.put(e.getKey(), e.getValue()); + } + + private transient Set> entrySet = null; + + public Set> entrySet() { + if (entrySet==null) + entrySet = new CheckedEntrySet<>(m.entrySet(), valueType); + return entrySet; + } + + /** + * We need this class in addition to CheckedSet as Map.Entry permits + * modification of the backing Map via the setValue operation. This + * class is subtle: there are many possible attacks that must be + * thwarted. + * + * @serial exclude + */ + static class CheckedEntrySet implements Set> { + private final Set> s; + private final Class valueType; + + CheckedEntrySet(Set> s, Class valueType) { + this.s = s; + this.valueType = valueType; + } + + public int size() { return s.size(); } + public boolean isEmpty() { return s.isEmpty(); } + public String toString() { return s.toString(); } + public int hashCode() { return s.hashCode(); } + public void clear() { s.clear(); } + + public boolean add(Map.Entry e) { + throw new UnsupportedOperationException(); + } + public boolean addAll(Collection> coll) { + throw new UnsupportedOperationException(); + } + + public Iterator> iterator() { + final Iterator> i = s.iterator(); + final Class valueType = this.valueType; + + return new Iterator>() { + public boolean hasNext() { return i.hasNext(); } + public void remove() { i.remove(); } + + public Map.Entry next() { + return checkedEntry(i.next(), valueType); + } + }; + } + + @SuppressWarnings("unchecked") + public Object[] toArray() { + Object[] source = s.toArray(); + + /* + * Ensure that we don't get an ArrayStoreException even if + * s.toArray returns an array of something other than Object + */ + Object[] dest = (CheckedEntry.class.isInstance( + source.getClass().getComponentType()) ? source : + new Object[source.length]); + + for (int i = 0; i < source.length; i++) + dest[i] = checkedEntry((Map.Entry)source[i], + valueType); + return dest; + } + + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + // We don't pass a to s.toArray, to avoid window of + // vulnerability wherein an unscrupulous multithreaded client + // could get his hands on raw (unwrapped) Entries from s. + T[] arr = s.toArray(a.length==0 ? a : Arrays.copyOf(a, 0)); + + for (int i=0; i)arr[i], + valueType); + if (arr.length > a.length) + return arr; + + System.arraycopy(arr, 0, a, 0, arr.length); + if (a.length > arr.length) + a[arr.length] = null; + return a; + } + + /** + * This method is overridden to protect the backing set against + * an object with a nefarious equals function that senses + * that the equality-candidate is Map.Entry and calls its + * setValue method. + */ + public boolean contains(Object o) { + if (!(o instanceof Map.Entry)) + return false; + Map.Entry e = (Map.Entry) o; + return s.contains( + (e instanceof CheckedEntry) ? e : checkedEntry(e, valueType)); + } + + /** + * The bulk collection methods are overridden to protect + * against an unscrupulous collection whose contains(Object o) + * method senses when o is a Map.Entry, and calls o.setValue. + */ + public boolean containsAll(Collection c) { + for (Object o : c) + if (!contains(o)) // Invokes safe contains() above + return false; + return true; + } + + public boolean remove(Object o) { + if (!(o instanceof Map.Entry)) + return false; + return s.remove(new AbstractMap.SimpleImmutableEntry + <>((Map.Entry)o)); + } + + public boolean removeAll(Collection c) { + return batchRemove(c, false); + } + public boolean retainAll(Collection c) { + return batchRemove(c, true); + } + private boolean batchRemove(Collection c, boolean complement) { + boolean modified = false; + Iterator> it = iterator(); + while (it.hasNext()) { + if (c.contains(it.next()) != complement) { + it.remove(); + modified = true; + } + } + return modified; + } + + public boolean equals(Object o) { + if (o == this) + return true; + if (!(o instanceof Set)) + return false; + Set that = (Set) o; + return that.size() == s.size() + && containsAll(that); // Invokes safe containsAll() above + } + + static CheckedEntry checkedEntry(Map.Entry e, + Class valueType) { + return new CheckedEntry<>(e, valueType); + } + + /** + * This "wrapper class" serves two purposes: it prevents + * the client from modifying the backing Map, by short-circuiting + * the setValue method, and it protects the backing Map against + * an ill-behaved Map.Entry that attempts to modify another + * Map.Entry when asked to perform an equality check. + */ + private static class CheckedEntry implements Map.Entry { + private final Map.Entry e; + private final Class valueType; + + CheckedEntry(Map.Entry e, Class valueType) { + this.e = e; + this.valueType = valueType; + } + + public K getKey() { return e.getKey(); } + public V getValue() { return e.getValue(); } + public int hashCode() { return e.hashCode(); } + public String toString() { return e.toString(); } + + public V setValue(V value) { + if (value != null && !valueType.isInstance(value)) + throw new ClassCastException(badValueMsg(value)); + return e.setValue(value); + } + + private String badValueMsg(Object value) { + return "Attempt to insert " + value.getClass() + + " value into map with value type " + valueType; + } + + public boolean equals(Object o) { + if (o == this) + return true; + if (!(o instanceof Map.Entry)) + return false; + return e.equals(new AbstractMap.SimpleImmutableEntry + <>((Map.Entry)o)); + } + } + } + } + + /** + * Returns a dynamically typesafe view of the specified sorted map. + * Any attempt to insert a mapping whose key or value have the wrong + * type will result in an immediate {@link ClassCastException}. + * Similarly, any attempt to modify the value currently associated with + * a key will result in an immediate {@link ClassCastException}, + * whether the modification is attempted directly through the map + * itself, or through a {@link Map.Entry} instance obtained from the + * map's {@link Map#entrySet() entry set} view. + * + *

Assuming a map contains no incorrectly typed keys or values + * prior to the time a dynamically typesafe view is generated, and + * that all subsequent access to the map takes place through the view + * (or one of its collection views), it is guaranteed that the + * map cannot contain an incorrectly typed key or value. + * + *

A discussion of the use of dynamically typesafe views may be + * found in the documentation for the {@link #checkedCollection + * checkedCollection} method. + * + *

The returned map will be serializable if the specified map is + * serializable. + * + *

Since {@code null} is considered to be a value of any reference + * type, the returned map permits insertion of null keys or values + * whenever the backing map does. + * + * @param m the map for which a dynamically typesafe view is to be + * returned + * @param keyType the type of key that {@code m} is permitted to hold + * @param valueType the type of value that {@code m} is permitted to hold + * @return a dynamically typesafe view of the specified map + * @since 1.5 + */ + public static SortedMap checkedSortedMap(SortedMap m, + Class keyType, + Class valueType) { + return new CheckedSortedMap<>(m, keyType, valueType); + } + + /** + * @serial include + */ + static class CheckedSortedMap extends CheckedMap + implements SortedMap, Serializable + { + private static final long serialVersionUID = 1599671320688067438L; + + private final SortedMap sm; + + CheckedSortedMap(SortedMap m, + Class keyType, Class valueType) { + super(m, keyType, valueType); + sm = m; + } + + public Comparator comparator() { return sm.comparator(); } + public K firstKey() { return sm.firstKey(); } + public K lastKey() { return sm.lastKey(); } + + public SortedMap subMap(K fromKey, K toKey) { + return checkedSortedMap(sm.subMap(fromKey, toKey), + keyType, valueType); + } + public SortedMap headMap(K toKey) { + return checkedSortedMap(sm.headMap(toKey), keyType, valueType); + } + public SortedMap tailMap(K fromKey) { + return checkedSortedMap(sm.tailMap(fromKey), keyType, valueType); + } + } + + // Empty collections + + /** + * Returns an iterator that has no elements. More precisely, + * + *

    + * + *
  • {@link Iterator#hasNext hasNext} always returns {@code + * false}. + * + *
  • {@link Iterator#next next} always throws {@link + * NoSuchElementException}. + * + *
  • {@link Iterator#remove remove} always throws {@link + * IllegalStateException}. + * + *
+ * + *

Implementations of this method are permitted, but not + * required, to return the same object from multiple invocations. + * + * @return an empty iterator + * @since 1.7 + */ + @SuppressWarnings("unchecked") + public static Iterator emptyIterator() { + return (Iterator) EmptyIterator.EMPTY_ITERATOR; + } + + private static class EmptyIterator implements Iterator { + static final EmptyIterator EMPTY_ITERATOR + = new EmptyIterator<>(); + + public boolean hasNext() { return false; } + public E next() { throw new NoSuchElementException(); } + public void remove() { throw new IllegalStateException(); } + } + + /** + * Returns a list iterator that has no elements. More precisely, + * + *
    + * + *
  • {@link Iterator#hasNext hasNext} and {@link + * ListIterator#hasPrevious hasPrevious} always return {@code + * false}. + * + *
  • {@link Iterator#next next} and {@link ListIterator#previous + * previous} always throw {@link NoSuchElementException}. + * + *
  • {@link Iterator#remove remove} and {@link ListIterator#set + * set} always throw {@link IllegalStateException}. + * + *
  • {@link ListIterator#add add} always throws {@link + * UnsupportedOperationException}. + * + *
  • {@link ListIterator#nextIndex nextIndex} always returns + * {@code 0} . + * + *
  • {@link ListIterator#previousIndex previousIndex} always + * returns {@code -1}. + * + *
+ * + *

Implementations of this method are permitted, but not + * required, to return the same object from multiple invocations. + * + * @return an empty list iterator + * @since 1.7 + */ + @SuppressWarnings("unchecked") + public static ListIterator emptyListIterator() { + return (ListIterator) EmptyListIterator.EMPTY_ITERATOR; + } + + private static class EmptyListIterator + extends EmptyIterator + implements ListIterator + { + static final EmptyListIterator EMPTY_ITERATOR + = new EmptyListIterator<>(); + + public boolean hasPrevious() { return false; } + public E previous() { throw new NoSuchElementException(); } + public int nextIndex() { return 0; } + public int previousIndex() { return -1; } + public void set(E e) { throw new IllegalStateException(); } + public void add(E e) { throw new UnsupportedOperationException(); } + } + + /** + * Returns an enumeration that has no elements. More precisely, + * + *
    + * + *
  • {@link Enumeration#hasMoreElements hasMoreElements} always + * returns {@code false}. + * + *
  • {@link Enumeration#nextElement nextElement} always throws + * {@link NoSuchElementException}. + * + *
+ * + *

Implementations of this method are permitted, but not + * required, to return the same object from multiple invocations. + * + * @return an empty enumeration + * @since 1.7 + */ + @SuppressWarnings("unchecked") + public static Enumeration emptyEnumeration() { + return (Enumeration) EmptyEnumeration.EMPTY_ENUMERATION; + } + + private static class EmptyEnumeration implements Enumeration { + static final EmptyEnumeration EMPTY_ENUMERATION + = new EmptyEnumeration<>(); + + public boolean hasMoreElements() { return false; } + public E nextElement() { throw new NoSuchElementException(); } + } + + /** + * The empty set (immutable). This set is serializable. + * + * @see #emptySet() + */ + @SuppressWarnings("unchecked") + public static final Set EMPTY_SET = new EmptySet<>(); + + /** + * Returns the empty set (immutable). This set is serializable. + * Unlike the like-named field, this method is parameterized. + * + *

This example illustrates the type-safe way to obtain an empty set: + *

+     *     Set<String> s = Collections.emptySet();
+     * 
+ * Implementation note: Implementations of this method need not + * create a separate Set object for each call. Using this + * method is likely to have comparable cost to using the like-named + * field. (Unlike this method, the field does not provide type safety.) + * + * @see #EMPTY_SET + * @since 1.5 + */ + @SuppressWarnings("unchecked") + public static final Set emptySet() { + return (Set) EMPTY_SET; + } + + /** + * @serial include + */ + private static class EmptySet + extends AbstractSet + implements Serializable + { + private static final long serialVersionUID = 1582296315990362920L; + + public Iterator iterator() { return emptyIterator(); } + + public int size() {return 0;} + public boolean isEmpty() {return true;} + + public boolean contains(Object obj) {return false;} + public boolean containsAll(Collection c) { return c.isEmpty(); } + + public Object[] toArray() { return new Object[0]; } + + public T[] toArray(T[] a) { + if (a.length > 0) + a[0] = null; + return a; + } + + // Preserves singleton property + private Object readResolve() { + return EMPTY_SET; + } + } + + /** + * The empty list (immutable). This list is serializable. + * + * @see #emptyList() + */ + @SuppressWarnings("unchecked") + public static final List EMPTY_LIST = new EmptyList<>(); + + /** + * Returns the empty list (immutable). This list is serializable. + * + *

This example illustrates the type-safe way to obtain an empty list: + *

+     *     List<String> s = Collections.emptyList();
+     * 
+ * Implementation note: Implementations of this method need not + * create a separate List object for each call. Using this + * method is likely to have comparable cost to using the like-named + * field. (Unlike this method, the field does not provide type safety.) + * + * @see #EMPTY_LIST + * @since 1.5 + */ + @SuppressWarnings("unchecked") + public static final List emptyList() { + return (List) EMPTY_LIST; + } + + /** + * @serial include + */ + private static class EmptyList + extends AbstractList + implements RandomAccess, Serializable { + private static final long serialVersionUID = 8842843931221139166L; + + public Iterator iterator() { + return emptyIterator(); + } + public ListIterator listIterator() { + return emptyListIterator(); + } + + public int size() {return 0;} + public boolean isEmpty() {return true;} + + public boolean contains(Object obj) {return false;} + public boolean containsAll(Collection c) { return c.isEmpty(); } + + public Object[] toArray() { return new Object[0]; } + + public T[] toArray(T[] a) { + if (a.length > 0) + a[0] = null; + return a; + } + + public E get(int index) { + throw new IndexOutOfBoundsException("Index: "+index); + } + + public boolean equals(Object o) { + return (o instanceof List) && ((List)o).isEmpty(); + } + + public int hashCode() { return 1; } + + // Preserves singleton property + private Object readResolve() { + return EMPTY_LIST; + } + } + + /** + * The empty map (immutable). This map is serializable. + * + * @see #emptyMap() + * @since 1.3 + */ + @SuppressWarnings("unchecked") + public static final Map EMPTY_MAP = new EmptyMap<>(); + + /** + * Returns the empty map (immutable). This map is serializable. + * + *

This example illustrates the type-safe way to obtain an empty set: + *

+     *     Map<String, Date> s = Collections.emptyMap();
+     * 
+ * Implementation note: Implementations of this method need not + * create a separate Map object for each call. Using this + * method is likely to have comparable cost to using the like-named + * field. (Unlike this method, the field does not provide type safety.) + * + * @see #EMPTY_MAP + * @since 1.5 + */ + @SuppressWarnings("unchecked") + public static final Map emptyMap() { + return (Map) EMPTY_MAP; + } + + /** + * @serial include + */ + private static class EmptyMap + extends AbstractMap + implements Serializable + { + private static final long serialVersionUID = 6428348081105594320L; + + public int size() {return 0;} + public boolean isEmpty() {return true;} + public boolean containsKey(Object key) {return false;} + public boolean containsValue(Object value) {return false;} + public V get(Object key) {return null;} + public Set keySet() {return emptySet();} + public Collection values() {return emptySet();} + public Set> entrySet() {return emptySet();} + + public boolean equals(Object o) { + return (o instanceof Map) && ((Map)o).isEmpty(); + } + + public int hashCode() {return 0;} + + // Preserves singleton property + private Object readResolve() { + return EMPTY_MAP; + } + } + + // Singleton collections + + /** + * Returns an immutable set containing only the specified object. + * The returned set is serializable. + * + * @param o the sole object to be stored in the returned set. + * @return an immutable set containing only the specified object. + */ + public static Set singleton(T o) { + return new SingletonSet<>(o); + } + + static Iterator singletonIterator(final E e) { + return new Iterator() { + private boolean hasNext = true; + public boolean hasNext() { + return hasNext; + } + public E next() { + if (hasNext) { + hasNext = false; + return e; + } + throw new NoSuchElementException(); + } + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + /** + * @serial include + */ + private static class SingletonSet + extends AbstractSet + implements Serializable + { + private static final long serialVersionUID = 3193687207550431679L; + + private final E element; + + SingletonSet(E e) {element = e;} + + public Iterator iterator() { + return singletonIterator(element); + } + + public int size() {return 1;} + + public boolean contains(Object o) {return eq(o, element);} + } + + /** + * Returns an immutable list containing only the specified object. + * The returned list is serializable. + * + * @param o the sole object to be stored in the returned list. + * @return an immutable list containing only the specified object. + * @since 1.3 + */ + public static List singletonList(T o) { + return new SingletonList<>(o); + } + + /** + * @serial include + */ + private static class SingletonList + extends AbstractList + implements RandomAccess, Serializable { + + private static final long serialVersionUID = 3093736618740652951L; + + private final E element; + + SingletonList(E obj) {element = obj;} + + public Iterator iterator() { + return singletonIterator(element); + } + + public int size() {return 1;} + + public boolean contains(Object obj) {return eq(obj, element);} + + public E get(int index) { + if (index != 0) + throw new IndexOutOfBoundsException("Index: "+index+", Size: 1"); + return element; + } + } + + /** + * Returns an immutable map, mapping only the specified key to the + * specified value. The returned map is serializable. + * + * @param key the sole key to be stored in the returned map. + * @param value the value to which the returned map maps key. + * @return an immutable map containing only the specified key-value + * mapping. + * @since 1.3 + */ + public static Map singletonMap(K key, V value) { + return new SingletonMap<>(key, value); + } + + /** + * @serial include + */ + private static class SingletonMap + extends AbstractMap + implements Serializable { + private static final long serialVersionUID = -6979724477215052911L; + + private final K k; + private final V v; + + SingletonMap(K key, V value) { + k = key; + v = value; + } + + public int size() {return 1;} + + public boolean isEmpty() {return false;} + + public boolean containsKey(Object key) {return eq(key, k);} + + public boolean containsValue(Object value) {return eq(value, v);} + + public V get(Object key) {return (eq(key, k) ? v : null);} + + private transient Set keySet = null; + private transient Set> entrySet = null; + private transient Collection values = null; + + public Set keySet() { + if (keySet==null) + keySet = singleton(k); + return keySet; + } + + public Set> entrySet() { + if (entrySet==null) + entrySet = Collections.>singleton( + new SimpleImmutableEntry<>(k, v)); + return entrySet; + } + + public Collection values() { + if (values==null) + values = singleton(v); + return values; + } + + } + + // Miscellaneous + + /** + * Returns an immutable list consisting of n copies of the + * specified object. The newly allocated data object is tiny (it contains + * a single reference to the data object). This method is useful in + * combination with the List.addAll method to grow lists. + * The returned list is serializable. + * + * @param n the number of elements in the returned list. + * @param o the element to appear repeatedly in the returned list. + * @return an immutable list consisting of n copies of the + * specified object. + * @throws IllegalArgumentException if {@code n < 0} + * @see List#addAll(Collection) + * @see List#addAll(int, Collection) + */ + public static List nCopies(int n, T o) { + if (n < 0) + throw new IllegalArgumentException("List length = " + n); + return new CopiesList<>(n, o); + } + + /** + * @serial include + */ + private static class CopiesList + extends AbstractList + implements RandomAccess, Serializable + { + private static final long serialVersionUID = 2739099268398711800L; + + final int n; + final E element; + + CopiesList(int n, E e) { + assert n >= 0; + this.n = n; + element = e; + } + + public int size() { + return n; + } + + public boolean contains(Object obj) { + return n != 0 && eq(obj, element); + } + + public int indexOf(Object o) { + return contains(o) ? 0 : -1; + } + + public int lastIndexOf(Object o) { + return contains(o) ? n - 1 : -1; + } + + public E get(int index) { + if (index < 0 || index >= n) + throw new IndexOutOfBoundsException("Index: "+index+ + ", Size: "+n); + return element; + } + + public Object[] toArray() { + final Object[] a = new Object[n]; + if (element != null) + Arrays.fill(a, 0, n, element); + return a; + } + + public T[] toArray(T[] a) { + final int n = this.n; + if (a.length < n) { + a = (T[])java.lang.reflect.Array + .newInstance(a.getClass().getComponentType(), n); + if (element != null) + Arrays.fill(a, 0, n, element); + } else { + Arrays.fill(a, 0, n, element); + if (a.length > n) + a[n] = null; + } + return a; + } + + public List subList(int fromIndex, int toIndex) { + if (fromIndex < 0) + throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); + if (toIndex > n) + throw new IndexOutOfBoundsException("toIndex = " + toIndex); + if (fromIndex > toIndex) + throw new IllegalArgumentException("fromIndex(" + fromIndex + + ") > toIndex(" + toIndex + ")"); + return new CopiesList<>(toIndex - fromIndex, element); + } + } + + /** + * Returns a comparator that imposes the reverse of the natural + * ordering on a collection of objects that implement the + * {@code Comparable} interface. (The natural ordering is the ordering + * imposed by the objects' own {@code compareTo} method.) This enables a + * simple idiom for sorting (or maintaining) collections (or arrays) of + * objects that implement the {@code Comparable} interface in + * reverse-natural-order. For example, suppose {@code a} is an array of + * strings. Then:
+     *          Arrays.sort(a, Collections.reverseOrder());
+     * 
sorts the array in reverse-lexicographic (alphabetical) order.

+ * + * The returned comparator is serializable. + * + * @return A comparator that imposes the reverse of the natural + * ordering on a collection of objects that implement + * the Comparable interface. + * @see Comparable + */ + public static Comparator reverseOrder() { + return (Comparator) ReverseComparator.REVERSE_ORDER; + } + + /** + * @serial include + */ + private static class ReverseComparator + implements Comparator>, Serializable { + + private static final long serialVersionUID = 7207038068494060240L; + + static final ReverseComparator REVERSE_ORDER + = new ReverseComparator(); + + public int compare(Comparable c1, Comparable c2) { + return c2.compareTo(c1); + } + + private Object readResolve() { return reverseOrder(); } + } + + /** + * Returns a comparator that imposes the reverse ordering of the specified + * comparator. If the specified comparator is {@code null}, this method is + * equivalent to {@link #reverseOrder()} (in other words, it returns a + * comparator that imposes the reverse of the natural ordering on + * a collection of objects that implement the Comparable interface). + * + *

The returned comparator is serializable (assuming the specified + * comparator is also serializable or {@code null}). + * + * @param cmp a comparator who's ordering is to be reversed by the returned + * comparator or {@code null} + * @return A comparator that imposes the reverse ordering of the + * specified comparator. + * @since 1.5 + */ + public static Comparator reverseOrder(Comparator cmp) { + if (cmp == null) + return reverseOrder(); + + if (cmp instanceof ReverseComparator2) + return ((ReverseComparator2)cmp).cmp; + + return new ReverseComparator2<>(cmp); + } + + /** + * @serial include + */ + private static class ReverseComparator2 implements Comparator, + Serializable + { + private static final long serialVersionUID = 4374092139857L; + + /** + * The comparator specified in the static factory. This will never + * be null, as the static factory returns a ReverseComparator + * instance if its argument is null. + * + * @serial + */ + final Comparator cmp; + + ReverseComparator2(Comparator cmp) { + assert cmp != null; + this.cmp = cmp; + } + + public int compare(T t1, T t2) { + return cmp.compare(t2, t1); + } + + public boolean equals(Object o) { + return (o == this) || + (o instanceof ReverseComparator2 && + cmp.equals(((ReverseComparator2)o).cmp)); + } + + public int hashCode() { + return cmp.hashCode() ^ Integer.MIN_VALUE; + } + } + + /** + * Returns an enumeration over the specified collection. This provides + * interoperability with legacy APIs that require an enumeration + * as input. + * + * @param c the collection for which an enumeration is to be returned. + * @return an enumeration over the specified collection. + * @see Enumeration + */ + public static Enumeration enumeration(final Collection c) { + return new Enumeration() { + private final Iterator i = c.iterator(); + + public boolean hasMoreElements() { + return i.hasNext(); + } + + public T nextElement() { + return i.next(); + } + }; + } + + /** + * Returns an array list containing the elements returned by the + * specified enumeration in the order they are returned by the + * enumeration. This method provides interoperability between + * legacy APIs that return enumerations and new APIs that require + * collections. + * + * @param e enumeration providing elements for the returned + * array list + * @return an array list containing the elements returned + * by the specified enumeration. + * @since 1.4 + * @see Enumeration + * @see ArrayList + */ + public static ArrayList list(Enumeration e) { + ArrayList l = new ArrayList<>(); + while (e.hasMoreElements()) + l.add(e.nextElement()); + return l; + } + + /** + * Returns true if the specified arguments are equal, or both null. + */ + static boolean eq(Object o1, Object o2) { + return o1==null ? o2==null : o1.equals(o2); + } + + /** + * Returns the number of elements in the specified collection equal to the + * specified object. More formally, returns the number of elements + * e in the collection such that + * (o == null ? e == null : o.equals(e)). + * + * @param c the collection in which to determine the frequency + * of o + * @param o the object whose frequency is to be determined + * @throws NullPointerException if c is null + * @since 1.5 + */ + public static int frequency(Collection c, Object o) { + int result = 0; + if (o == null) { + for (Object e : c) + if (e == null) + result++; + } else { + for (Object e : c) + if (o.equals(e)) + result++; + } + return result; + } + + /** + * Returns {@code true} if the two specified collections have no + * elements in common. + * + *

Care must be exercised if this method is used on collections that + * do not comply with the general contract for {@code Collection}. + * Implementations may elect to iterate over either collection and test + * for containment in the other collection (or to perform any equivalent + * computation). If either collection uses a nonstandard equality test + * (as does a {@link SortedSet} whose ordering is not compatible with + * equals, or the key set of an {@link IdentityHashMap}), both + * collections must use the same nonstandard equality test, or the + * result of this method is undefined. + * + *

Care must also be exercised when using collections that have + * restrictions on the elements that they may contain. Collection + * implementations are allowed to throw exceptions for any operation + * involving elements they deem ineligible. For absolute safety the + * specified collections should contain only elements which are + * eligible elements for both collections. + * + *

Note that it is permissible to pass the same collection in both + * parameters, in which case the method will return {@code true} if and + * only if the collection is empty. + * + * @param c1 a collection + * @param c2 a collection + * @return {@code true} if the two specified collections have no + * elements in common. + * @throws NullPointerException if either collection is {@code null}. + * @throws NullPointerException if one collection contains a {@code null} + * element and {@code null} is not an eligible element for the other collection. + * (optional) + * @throws ClassCastException if one collection contains an element that is + * of a type which is ineligible for the other collection. + * (optional) + * @since 1.5 + */ + public static boolean disjoint(Collection c1, Collection c2) { + // The collection to be used for contains(). Preference is given to + // the collection who's contains() has lower O() complexity. + Collection contains = c2; + // The collection to be iterated. If the collections' contains() impl + // are of different O() complexity, the collection with slower + // contains() will be used for iteration. For collections who's + // contains() are of the same complexity then best performance is + // achieved by iterating the smaller collection. + Collection iterate = c1; + + // Performance optimization cases. The heuristics: + // 1. Generally iterate over c1. + // 2. If c1 is a Set then iterate over c2. + // 3. If either collection is empty then result is always true. + // 4. Iterate over the smaller Collection. + if (c1 instanceof Set) { + // Use c1 for contains as a Set's contains() is expected to perform + // better than O(N/2) + iterate = c2; + contains = c1; + } else if (!(c2 instanceof Set)) { + // Both are mere Collections. Iterate over smaller collection. + // Example: If c1 contains 3 elements and c2 contains 50 elements and + // assuming contains() requires ceiling(N/2) comparisons then + // checking for all c1 elements in c2 would require 75 comparisons + // (3 * ceiling(50/2)) vs. checking all c2 elements in c1 requiring + // 100 comparisons (50 * ceiling(3/2)). + int c1size = c1.size(); + int c2size = c2.size(); + if (c1size == 0 || c2size == 0) { + // At least one collection is empty. Nothing will match. + return true; + } + + if (c1size > c2size) { + iterate = c2; + contains = c1; + } + } + + for (Object e : iterate) { + if (contains.contains(e)) { + // Found a common element. Collections are not disjoint. + return false; + } + } + + // No common elements were found. + return true; + } + + /** + * Adds all of the specified elements to the specified collection. + * Elements to be added may be specified individually or as an array. + * The behavior of this convenience method is identical to that of + * c.addAll(Arrays.asList(elements)), but this method is likely + * to run significantly faster under most implementations. + * + *

When elements are specified individually, this method provides a + * convenient way to add a few elements to an existing collection: + *

+     *     Collections.addAll(flavors, "Peaches 'n Plutonium", "Rocky Racoon");
+     * 
+ * + * @param c the collection into which elements are to be inserted + * @param elements the elements to insert into c + * @return true if the collection changed as a result of the call + * @throws UnsupportedOperationException if c does not support + * the add operation + * @throws NullPointerException if elements contains one or more + * null values and c does not permit null elements, or + * if c or elements are null + * @throws IllegalArgumentException if some property of a value in + * elements prevents it from being added to c + * @see Collection#addAll(Collection) + * @since 1.5 + */ + @SafeVarargs + public static boolean addAll(Collection c, T... elements) { + boolean result = false; + for (T element : elements) + result |= c.add(element); + return result; + } + + /** + * Returns a set backed by the specified map. The resulting set displays + * the same ordering, concurrency, and performance characteristics as the + * backing map. In essence, this factory method provides a {@link Set} + * implementation corresponding to any {@link Map} implementation. There + * is no need to use this method on a {@link Map} implementation that + * already has a corresponding {@link Set} implementation (such as {@link + * HashMap} or {@link TreeMap}). + * + *

Each method invocation on the set returned by this method results in + * exactly one method invocation on the backing map or its keySet + * view, with one exception. The addAll method is implemented + * as a sequence of put invocations on the backing map. + * + *

The specified map must be empty at the time this method is invoked, + * and should not be accessed directly after this method returns. These + * conditions are ensured if the map is created empty, passed directly + * to this method, and no reference to the map is retained, as illustrated + * in the following code fragment: + *

+     *    Set<Object> weakHashSet = Collections.newSetFromMap(
+     *        new WeakHashMap<Object, Boolean>());
+     * 
+ * + * @param map the backing map + * @return the set backed by the map + * @throws IllegalArgumentException if map is not empty + * @since 1.6 + */ + public static Set newSetFromMap(Map map) { + return new SetFromMap<>(map); + } + + /** + * @serial include + */ + private static class SetFromMap extends AbstractSet + implements Set, Serializable + { + private final Map m; // The backing map + private transient Set s; // Its keySet + + SetFromMap(Map map) { + if (!map.isEmpty()) + throw new IllegalArgumentException("Map is non-empty"); + m = map; + s = map.keySet(); + } + + public void clear() { m.clear(); } + public int size() { return m.size(); } + public boolean isEmpty() { return m.isEmpty(); } + public boolean contains(Object o) { return m.containsKey(o); } + public boolean remove(Object o) { return m.remove(o) != null; } + public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; } + public Iterator iterator() { return s.iterator(); } + public Object[] toArray() { return s.toArray(); } + public T[] toArray(T[] a) { return s.toArray(a); } + public String toString() { return s.toString(); } + public int hashCode() { return s.hashCode(); } + public boolean equals(Object o) { return o == this || s.equals(o); } + public boolean containsAll(Collection c) {return s.containsAll(c);} + public boolean removeAll(Collection c) {return s.removeAll(c);} + public boolean retainAll(Collection c) {return s.retainAll(c);} + // addAll is the only inherited implementation + + private static final long serialVersionUID = 2454657854757543876L; + + private void readObject(java.io.ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + s = m.keySet(); + } + } + + /** + * Returns a view of a {@link Deque} as a Last-in-first-out (Lifo) + * {@link Queue}. Method add is mapped to push, + * remove is mapped to pop and so on. This + * view can be useful when you would like to use a method + * requiring a Queue but you need Lifo ordering. + * + *

Each method invocation on the queue returned by this method + * results in exactly one method invocation on the backing deque, with + * one exception. The {@link Queue#addAll addAll} method is + * implemented as a sequence of {@link Deque#addFirst addFirst} + * invocations on the backing deque. + * + * @param deque the deque + * @return the queue + * @since 1.6 + */ + public static Queue asLifoQueue(Deque deque) { + return new AsLIFOQueue<>(deque); + } + + /** + * @serial include + */ + static class AsLIFOQueue extends AbstractQueue + implements Queue, Serializable { + private static final long serialVersionUID = 1802017725587941708L; + private final Deque q; + AsLIFOQueue(Deque q) { this.q = q; } + public boolean add(E e) { q.addFirst(e); return true; } + public boolean offer(E e) { return q.offerFirst(e); } + public E poll() { return q.pollFirst(); } + public E remove() { return q.removeFirst(); } + public E peek() { return q.peekFirst(); } + public E element() { return q.getFirst(); } + public void clear() { q.clear(); } + public int size() { return q.size(); } + public boolean isEmpty() { return q.isEmpty(); } + public boolean contains(Object o) { return q.contains(o); } + public boolean remove(Object o) { return q.remove(o); } + public Iterator iterator() { return q.iterator(); } + public Object[] toArray() { return q.toArray(); } + public T[] toArray(T[] a) { return q.toArray(a); } + public String toString() { return q.toString(); } + public boolean containsAll(Collection c) {return q.containsAll(c);} + public boolean removeAll(Collection c) {return q.removeAll(c);} + public boolean retainAll(Collection c) {return q.retainAll(c);} + // We use inherited addAll; forwarding addAll would be wrong + } +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/Deque.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/Deque.java Mon Jan 28 13:30:53 2013 +0100 @@ -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 deque is short for "double ended queue" + * and is usually pronounced "deck". Most 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. + * + *

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 null or false, depending on + * the operation). The latter form of the insert operation is + * designed specifically for use with capacity-restricted + * Deque implementations; in most implementations, insert + * operations cannot fail. + * + *

The twelve methods described above are summarized in the + * following table: + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
First Element (Head) Last Element (Tail)
Throws exceptionSpecial valueThrows exceptionSpecial value
Insert{@link #addFirst addFirst(e)}{@link #offerFirst offerFirst(e)}{@link #addLast addLast(e)}{@link #offerLast offerLast(e)}
Remove{@link #removeFirst removeFirst()}{@link #pollFirst pollFirst()}{@link #removeLast removeLast()}{@link #pollLast pollLast()}
Examine{@link #getFirst getFirst()}{@link #peekFirst peekFirst()}{@link #getLast getLast()}{@link #peekLast peekLast()}
+ * + *

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 Queue interface are precisely equivalent to + * Deque methods as indicated in the following table: + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Queue Method Equivalent Deque Method
{@link java.util.Queue#add add(e)}{@link #addLast addLast(e)}
{@link java.util.Queue#offer offer(e)}{@link #offerLast offerLast(e)}
{@link java.util.Queue#remove remove()}{@link #removeFirst removeFirst()}
{@link java.util.Queue#poll poll()}{@link #pollFirst pollFirst()}
{@link java.util.Queue#element element()}{@link #getFirst getFirst()}
{@link java.util.Queue#peek peek()}{@link #peek peekFirst()}
+ * + *

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 + * Deque methods as indicated in the table below: + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Stack Method Equivalent Deque Method
{@link #push push(e)}{@link #addFirst addFirst(e)}
{@link #pop pop()}{@link #removeFirst removeFirst()}
{@link #peek peek()}{@link #peekFirst peekFirst()}
+ * + *

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. + * + *

This interface provides two methods to remove interior + * elements, {@link #removeFirstOccurrence removeFirstOccurrence} and + * {@link #removeLastOccurrence removeLastOccurrence}. + * + *

Unlike the {@link List} interface, this interface does not + * provide support for indexed access to elements. + * + *

While Deque implementations are not strictly required + * to prohibit the insertion of null elements, they are strongly + * encouraged to do so. Users of any Deque implementations + * that do allow null elements are strongly encouraged not to + * take advantage of the ability to insert nulls. This is so because + * null is used as a special return value by various methods + * to indicated that the deque is empty. + * + *

Deque implementations generally do not define + * element-based versions of the equals and hashCode + * methods, but instead inherit the identity-based versions from class + * Object. + * + *

This interface is a member of the Java Collections + * Framework. + * + * @author Doug Lea + * @author Josh Bloch + * @since 1.6 + * @param the type of elements held in this collection + */ + +public interface Deque extends Queue { + /** + * Inserts the specified element at the front of this deque if it is + * possible to do so immediately without violating capacity restrictions. + * 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. + * When using a capacity-restricted deque, it is generally preferable to + * use method {@link #offerLast}. + * + *

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 true if the element was added to this deque, else + * 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 true if the element was added to this deque, else + * 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 null if this deque is empty. + * + * @return the head of this deque, or null if this deque is empty + */ + E pollFirst(); + + /** + * Retrieves and removes the last element of this deque, + * or returns null if this deque is empty. + * + * @return the tail of this deque, or 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 null if this deque is empty. + * + * @return the head of this deque, or null if this deque is empty + */ + E peekFirst(); + + /** + * Retrieves, but does not remove, the last element of this deque, + * or returns null if this deque is empty. + * + * @return the tail of this deque, or 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 e such that + * (o==null ? e==null : o.equals(e)) + * (if such an element exists). + * Returns 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 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 + * (optional) + * @throws NullPointerException if the specified element is null and this + * deque does not permit null elements + * (optional) + */ + 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 e such that + * (o==null ? e==null : o.equals(e)) + * (if such an element exists). + * Returns 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 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 + * (optional) + * @throws NullPointerException if the specified element is null and this + * deque does not permit null elements + * (optional) + */ + 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 + * true upon success and throwing an + * IllegalStateException if no space is currently available. + * When using a capacity-restricted deque, it is generally preferable to + * use {@link #offer(Object) offer}. + * + *

This method is equivalent to {@link #addLast}. + * + * @param e the element to add + * @return 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 + * true upon success and 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. + * + *

This method is equivalent to {@link #offerLast}. + * + * @param e the element to add + * @return true if the element was added to this deque, else + * 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. + * + *

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 + * null if this deque is empty. + * + *

This method is equivalent to {@link #pollFirst()}. + * + * @return the first element of this deque, or 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. + * + *

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 null if this deque is empty. + * + *

This method is equivalent to {@link #peekFirst()}. + * + * @return the head of the queue represented by this deque, or + * 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, returning + * true upon success and throwing an + * IllegalStateException if no space is currently available. + * + *

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. + * + *

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 e such that + * (o==null ? e==null : o.equals(e)) + * (if such an element exists). + * Returns true if this deque contained the specified element + * (or equivalently, if this deque changed as a result of the call). + * + *

This method is equivalent to {@link #removeFirstOccurrence}. + * + * @param o element to be removed from this deque, if present + * @return 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 + * (optional) + * @throws NullPointerException if the specified element is null and this + * deque does not permit null elements + * (optional) + */ + boolean remove(Object o); + + /** + * Returns true if this deque contains the specified element. + * More formally, returns true if and only if this deque contains + * at least one element e such that + * (o==null ? e==null : o.equals(e)). + * + * @param o element whose presence in this deque is to be tested + * @return true if this deque contains the specified element + * @throws ClassCastException if the type of the specified element + * is incompatible with this deque + * (optional) + * @throws NullPointerException if the specified element is null and this + * deque does not permit null elements + * (optional) + */ + 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 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 descendingIterator(); + +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/Dictionary.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/Dictionary.java Mon Jan 28 13:30:53 2013 +0100 @@ -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 Dictionary class is the abstract parent of any + * class, such as Hashtable, which maps keys to values. + * Every key and every value is an object. In any one Dictionary + * object, every key is associated with at most one value. Given a + * Dictionary and a key, the associated element can be looked up. + * Any non-null object can be used as a key and as a value. + *

+ * As a rule, the equals method should be used by + * implementations of this class to decide if two keys are the same. + *

+ * NOTE: This class is obsolete. New implementations should + * implement the Map interface, rather than extending this class. + * + * @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 { + /** + * 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 isEmpty method is that the result is true if and only + * if this dictionary contains no entries. + * + * @return true if this dictionary maps no keys to values; + * false otherwise. + */ + abstract public boolean isEmpty(); + + /** + * Returns an enumeration of the keys in this dictionary. The general + * contract for the keys method is that an Enumeration object + * is returned that will generate all the keys for which this dictionary + * contains entries. + * + * @return an enumeration of the keys in this dictionary. + * @see java.util.Dictionary#elements() + * @see java.util.Enumeration + */ + abstract public Enumeration keys(); + + /** + * Returns an enumeration of the values in this dictionary. The general + * contract for the elements method is that an + * Enumeration is returned that will generate all the elements + * contained in entries in this dictionary. + * + * @return an enumeration of the values in this dictionary. + * @see java.util.Dictionary#keys() + * @see java.util.Enumeration + */ + abstract public Enumeration elements(); + + /** + * Returns the value to which the key is mapped in this dictionary. + * The general contract for the isEmpty method is that if this + * dictionary contains an entry for the specified key, the associated + * value is returned; otherwise, null is returned. + * + * @return the value to which the key is mapped in this dictionary; + * @param key a key in this dictionary. + * null if the key is not mapped to any value in + * this dictionary. + * @exception NullPointerException if the key is null. + * @see java.util.Dictionary#put(java.lang.Object, java.lang.Object) + */ + abstract public V get(Object key); + + /** + * Maps the specified key to the specified + * value in this dictionary. Neither the key nor the + * value can be null. + *

+ * If this dictionary already contains an entry for the specified + * key, the value already in this dictionary for that + * key is returned, after modifying the entry to contain the + * new element.

If this dictionary does not already have an entry + * for the specified key, an entry is created for the + * specified key and value, and null is + * returned. + *

+ * The value can be retrieved by calling the + * get method with a key that is equal to + * the original key. + * + * @param key the hashtable key. + * @param value the value. + * @return the previous value to which the key was mapped + * in this dictionary, or null if the key did not + * have a previous mapping. + * @exception NullPointerException if the key or + * value is null. + * @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 key (and its corresponding + * value) from this dictionary. This method does nothing + * if the key is not in this dictionary. + * + * @param key the key that needs to be removed. + * @return the value to which the key had been mapped in this + * dictionary, or null if the key did not have a + * mapping. + * @exception NullPointerException if key is null. + */ + abstract public V remove(Object key); +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/EmptyStackException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/EmptyStackException.java Mon Jan 28 13:30:53 2013 +0100 @@ -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 Stack 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 EmptyStackException with null + * as its error message string. + */ + public EmptyStackException() { + } +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/EventListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/EventListener.java Mon Jan 28 13:30:53 2013 +0100 @@ -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 { +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/EventObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/EventObject.java Mon Jan 28 13:30:53 2013 +0100 @@ -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; + +/** + *

+ * The root class from which all event state objects shall be derived. + *

+ * 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 + "]"; + } +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/Hashtable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/Hashtable.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,1115 @@ +/* + * Copyright (c) 1994, 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; +import java.io.*; + +/** + * This class implements a hash table, which maps keys to values. Any + * non-null object can be used as a key or as a value.

+ * + * To successfully store and retrieve objects from a hashtable, the + * objects used as keys must implement the hashCode + * method and the equals method.

+ * + * An instance of Hashtable has two parameters that affect its + * performance: initial capacity and load factor. The + * capacity is the number of buckets in the hash table, and the + * initial capacity is simply the capacity at the time the hash table + * is created. Note that the hash table is open: in the case of a "hash + * collision", a single bucket stores multiple entries, which must be searched + * sequentially. The load factor is a measure of how full the hash + * table is allowed to get before its capacity is automatically increased. + * The initial capacity and load factor parameters are merely hints to + * the implementation. The exact details as to when and whether the rehash + * method is invoked are implementation-dependent.

+ * + * Generally, the default load factor (.75) offers a good tradeoff between + * time and space costs. Higher values decrease the space overhead but + * increase the time cost to look up an entry (which is reflected in most + * Hashtable operations, including get and put).

+ * + * The initial capacity controls a tradeoff between wasted space and the + * need for rehash operations, which are time-consuming. + * No rehash operations will ever occur if the initial + * capacity is greater than the maximum number of entries the + * Hashtable will contain divided by its load factor. However, + * setting the initial capacity too high can waste space.

+ * + * If many entries are to be made into a Hashtable, + * creating it with a sufficiently large capacity may allow the + * entries to be inserted more efficiently than letting it perform + * automatic rehashing as needed to grow the table.

+ * + * This example creates a hashtable of numbers. It uses the names of + * the numbers as keys: + *

   {@code
+ *   Hashtable numbers
+ *     = new Hashtable();
+ *   numbers.put("one", 1);
+ *   numbers.put("two", 2);
+ *   numbers.put("three", 3);}
+ * + *

To retrieve a number, use the following code: + *

   {@code
+ *   Integer n = numbers.get("two");
+ *   if (n != null) {
+ *     System.out.println("two = " + n);
+ *   }}
+ * + *

The iterators returned by the iterator method of the collections + * returned by all of this class's "collection view methods" are + * fail-fast: if the Hashtable is structurally modified at any time + * after the iterator is created, in any way except through the iterator's own + * remove method, the iterator will throw a {@link + * ConcurrentModificationException}. Thus, in the face of concurrent + * modification, the iterator fails quickly and cleanly, rather than risking + * arbitrary, non-deterministic behavior at an undetermined time in the future. + * The Enumerations returned by Hashtable's keys and elements methods are + * not fail-fast. + * + *

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 ConcurrentModificationException on a best-effort basis. + * Therefore, it would be wrong to write a program that depended on this + * exception for its correctness: the fail-fast behavior of iterators + * should be used only to detect bugs. + * + *

As of the Java 2 platform v1.2, this class was retrofitted to + * implement the {@link Map} interface, making it a member of the + * + * + * Java Collections Framework. Unlike the new collection + * implementations, {@code Hashtable} is synchronized. If a + * thread-safe implementation is not needed, it is recommended to use + * {@link HashMap} in place of {@code Hashtable}. If a thread-safe + * highly-concurrent implementation is desired, then it is recommended + * to use {@link java.util.concurrent.ConcurrentHashMap} in place of + * {@code Hashtable}. + * + * @author Arthur van Hoff + * @author Josh Bloch + * @author Neal Gafter + * @see Object#equals(java.lang.Object) + * @see Object#hashCode() + * @see Hashtable#rehash() + * @see Collection + * @see Map + * @see HashMap + * @see TreeMap + * @since JDK1.0 + */ +public class Hashtable + extends Dictionary + implements Map, Cloneable, java.io.Serializable { + + /** + * The hash table data. + */ + private transient Entry[] table; + + /** + * The total number of entries in the hash table. + */ + private transient int count; + + /** + * The table is rehashed when its size exceeds this threshold. (The + * value of this field is (int)(capacity * loadFactor).) + * + * @serial + */ + private int threshold; + + /** + * The load factor for the hashtable. + * + * @serial + */ + private float loadFactor; + + /** + * The number of times this Hashtable has been structurally modified + * Structural modifications are those that change the number of entries in + * the Hashtable or otherwise modify its internal structure (e.g., + * rehash). This field is used to make iterators on Collection-views of + * the Hashtable fail-fast. (See ConcurrentModificationException). + */ + private transient int modCount = 0; + + /** use serialVersionUID from JDK 1.0.2 for interoperability */ + private static final long serialVersionUID = 1421746759512286392L; + + /** + * Constructs a new, empty hashtable with the specified initial + * capacity and the specified load factor. + * + * @param initialCapacity the initial capacity of the hashtable. + * @param loadFactor the load factor of the hashtable. + * @exception IllegalArgumentException if the initial capacity is less + * than zero, or if the load factor is nonpositive. + */ + public Hashtable(int initialCapacity, float loadFactor) { + if (initialCapacity < 0) + throw new IllegalArgumentException("Illegal Capacity: "+ + initialCapacity); + if (loadFactor <= 0 || Float.isNaN(loadFactor)) + throw new IllegalArgumentException("Illegal Load: "+loadFactor); + + if (initialCapacity==0) + initialCapacity = 1; + this.loadFactor = loadFactor; + table = new Entry[initialCapacity]; + threshold = (int)(initialCapacity * loadFactor); + } + + /** + * Constructs a new, empty hashtable with the specified initial capacity + * and default load factor (0.75). + * + * @param initialCapacity the initial capacity of the hashtable. + * @exception IllegalArgumentException if the initial capacity is less + * than zero. + */ + public Hashtable(int initialCapacity) { + this(initialCapacity, 0.75f); + } + + /** + * Constructs a new, empty hashtable with a default initial capacity (11) + * and load factor (0.75). + */ + public Hashtable() { + this(11, 0.75f); + } + + /** + * Constructs a new hashtable with the same mappings as the given + * Map. The hashtable is created with an initial capacity sufficient to + * hold the mappings in the given Map and a default load factor (0.75). + * + * @param t the map whose mappings are to be placed in this map. + * @throws NullPointerException if the specified map is null. + * @since 1.2 + */ + public Hashtable(Map t) { + this(Math.max(2*t.size(), 11), 0.75f); + putAll(t); + } + + /** + * Returns the number of keys in this hashtable. + * + * @return the number of keys in this hashtable. + */ + public synchronized int size() { + return count; + } + + /** + * Tests if this hashtable maps no keys to values. + * + * @return true if this hashtable maps no keys to values; + * false otherwise. + */ + public synchronized boolean isEmpty() { + return count == 0; + } + + /** + * Returns an enumeration of the keys in this hashtable. + * + * @return an enumeration of the keys in this hashtable. + * @see Enumeration + * @see #elements() + * @see #keySet() + * @see Map + */ + public synchronized Enumeration keys() { + return this.getEnumeration(KEYS); + } + + /** + * Returns an enumeration of the values in this hashtable. + * Use the Enumeration methods on the returned object to fetch the elements + * sequentially. + * + * @return an enumeration of the values in this hashtable. + * @see java.util.Enumeration + * @see #keys() + * @see #values() + * @see Map + */ + public synchronized Enumeration elements() { + return this.getEnumeration(VALUES); + } + + /** + * Tests if some key maps into the specified value in this hashtable. + * This operation is more expensive than the {@link #containsKey + * containsKey} method. + * + *

Note that this method is identical in functionality to + * {@link #containsValue containsValue}, (which is part of the + * {@link Map} interface in the collections framework). + * + * @param value a value to search for + * @return true if and only if some key maps to the + * value argument in this hashtable as + * determined by the equals method; + * false otherwise. + * @exception NullPointerException if the value is null + */ + public synchronized boolean contains(Object value) { + if (value == null) { + throw new NullPointerException(); + } + + Entry tab[] = table; + for (int i = tab.length ; i-- > 0 ;) { + for (Entry e = tab[i] ; e != null ; e = e.next) { + if (e.value.equals(value)) { + return true; + } + } + } + return false; + } + + /** + * Returns true if this hashtable maps one or more keys to this value. + * + *

Note that this method is identical in functionality to {@link + * #contains contains} (which predates the {@link Map} interface). + * + * @param value value whose presence in this hashtable is to be tested + * @return true if this map maps one or more keys to the + * specified value + * @throws NullPointerException if the value is null + * @since 1.2 + */ + public boolean containsValue(Object value) { + return contains(value); + } + + /** + * Tests if the specified object is a key in this hashtable. + * + * @param key possible key + * @return true if and only if the specified object + * is a key in this hashtable, as determined by the + * equals method; false otherwise. + * @throws NullPointerException if the key is null + * @see #contains(Object) + */ + public synchronized boolean containsKey(Object key) { + Entry tab[] = table; + int hash = key.hashCode(); + int index = (hash & 0x7FFFFFFF) % tab.length; + for (Entry e = tab[index] ; e != null ; e = e.next) { + if ((e.hash == hash) && e.key.equals(key)) { + 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. + * + *

More formally, if this map contains a mapping from a key + * {@code k} to a value {@code v} such that {@code (key.equals(k))}, + * then this method returns {@code v}; otherwise it returns + * {@code null}. (There can be at most one such mapping.) + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped, or + * {@code null} if this map contains no mapping for the key + * @throws NullPointerException if the specified key is null + * @see #put(Object, Object) + */ + public synchronized V get(Object key) { + Entry tab[] = table; + int hash = key.hashCode(); + int index = (hash & 0x7FFFFFFF) % tab.length; + for (Entry e = tab[index] ; e != null ; e = e.next) { + if ((e.hash == hash) && e.key.equals(key)) { + return e.value; + } + } + return null; + } + + /** + * 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 and internally reorganizes this + * hashtable, in order to accommodate and access its entries more + * efficiently. This method is called automatically when the + * number of keys in the hashtable exceeds this hashtable's capacity + * and load factor. + */ + protected void rehash() { + int oldCapacity = table.length; + Entry[] oldMap = table; + + // overflow-conscious code + int newCapacity = (oldCapacity << 1) + 1; + if (newCapacity - MAX_ARRAY_SIZE > 0) { + if (oldCapacity == MAX_ARRAY_SIZE) + // Keep running with MAX_ARRAY_SIZE buckets + return; + newCapacity = MAX_ARRAY_SIZE; + } + Entry[] newMap = new Entry[newCapacity]; + + modCount++; + threshold = (int)(newCapacity * loadFactor); + table = newMap; + + for (int i = oldCapacity ; i-- > 0 ;) { + for (Entry old = oldMap[i] ; old != null ; ) { + Entry e = old; + old = old.next; + + int index = (e.hash & 0x7FFFFFFF) % newCapacity; + e.next = newMap[index]; + newMap[index] = e; + } + } + } + + /** + * Maps the specified key to the specified + * value in this hashtable. Neither the key nor the + * value can be null.

+ * + * The value can be retrieved by calling the get method + * with a key that is equal to the original key. + * + * @param key the hashtable key + * @param value the value + * @return the previous value of the specified key in this hashtable, + * or null if it did not have one + * @exception NullPointerException if the key or value is + * null + * @see Object#equals(Object) + * @see #get(Object) + */ + public synchronized V put(K key, V value) { + // Make sure the value is not null + if (value == null) { + throw new NullPointerException(); + } + + // Makes sure the key is not already in the hashtable. + Entry tab[] = table; + int hash = key.hashCode(); + int index = (hash & 0x7FFFFFFF) % tab.length; + for (Entry e = tab[index] ; e != null ; e = e.next) { + if ((e.hash == hash) && e.key.equals(key)) { + V old = e.value; + e.value = value; + return old; + } + } + + modCount++; + if (count >= threshold) { + // Rehash the table if the threshold is exceeded + rehash(); + + tab = table; + index = (hash & 0x7FFFFFFF) % tab.length; + } + + // Creates the new entry. + Entry e = tab[index]; + tab[index] = new Entry<>(hash, key, value, e); + count++; + return null; + } + + /** + * Removes the key (and its corresponding value) from this + * hashtable. This method does nothing if the key is not in the hashtable. + * + * @param key the key that needs to be removed + * @return the value to which the key had been mapped in this hashtable, + * or null if the key did not have a mapping + * @throws NullPointerException if the key is null + */ + public synchronized V remove(Object key) { + Entry tab[] = table; + int hash = key.hashCode(); + int index = (hash & 0x7FFFFFFF) % tab.length; + for (Entry e = tab[index], prev = null ; e != null ; prev = e, e = e.next) { + if ((e.hash == hash) && e.key.equals(key)) { + modCount++; + if (prev != null) { + prev.next = e.next; + } else { + tab[index] = e.next; + } + count--; + V oldValue = e.value; + e.value = null; + return oldValue; + } + } + return null; + } + + /** + * Copies all of the mappings from the specified map to this hashtable. + * These mappings will replace any mappings that this hashtable had for any + * of the keys currently in the specified map. + * + * @param t mappings to be stored in this map + * @throws NullPointerException if the specified map is null + * @since 1.2 + */ + public synchronized void putAll(Map t) { + for (Map.Entry e : t.entrySet()) + put(e.getKey(), e.getValue()); + } + + /** + * Clears this hashtable so that it contains no keys. + */ + public synchronized void clear() { + Entry tab[] = table; + modCount++; + for (int index = tab.length; --index >= 0; ) + tab[index] = null; + count = 0; + } + + /** + * Creates a shallow copy of this hashtable. All the structure of the + * hashtable itself is copied, but the keys and values are not cloned. + * This is a relatively expensive operation. + * + * @return a clone of the hashtable + */ + public synchronized Object clone() { + try { + Hashtable t = (Hashtable) super.clone(); + t.table = new Entry[table.length]; + for (int i = table.length ; i-- > 0 ; ) { + t.table[i] = (table[i] != null) + ? (Entry) table[i].clone() : null; + } + t.keySet = null; + t.entrySet = null; + t.values = null; + t.modCount = 0; + return t; + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + /** + * Returns a string representation of this Hashtable object + * in the form of a set of entries, enclosed in braces and separated + * by the ASCII characters "" (comma and space). Each + * entry is rendered as the key, an equals sign =, and the + * associated element, where the toString method is used to + * convert the key and element to strings. + * + * @return a string representation of this hashtable + */ + public synchronized String toString() { + int max = size() - 1; + if (max == -1) + return "{}"; + + StringBuilder sb = new StringBuilder(); + Iterator> it = entrySet().iterator(); + + sb.append('{'); + for (int i = 0; ; i++) { + Map.Entry e = it.next(); + K key = e.getKey(); + V value = e.getValue(); + sb.append(key == this ? "(this Map)" : key.toString()); + sb.append('='); + sb.append(value == this ? "(this Map)" : value.toString()); + + if (i == max) + return sb.append('}').toString(); + sb.append(", "); + } + } + + + private Enumeration getEnumeration(int type) { + if (count == 0) { + return Collections.emptyEnumeration(); + } else { + return new Enumerator<>(type, false); + } + } + + private Iterator getIterator(int type) { + if (count == 0) { + return Collections.emptyIterator(); + } else { + return new Enumerator<>(type, true); + } + } + + // 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. + */ + private transient volatile Set keySet = null; + private transient volatile Set> entrySet = null; + private transient volatile Collection values = null; + + /** + * 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 remove operation), the results of + * the iteration are undefined. The set supports element removal, + * which removes the corresponding mapping from the map, via the + * Iterator.remove, Set.remove, + * removeAll, retainAll, and clear + * operations. It does not support the add or addAll + * operations. + * + * @since 1.2 + */ + public Set keySet() { + if (keySet == null) + keySet = Collections.synchronizedSet(new KeySet(), this); + return keySet; + } + + private class KeySet extends AbstractSet { + public Iterator iterator() { + return getIterator(KEYS); + } + public int size() { + return count; + } + public boolean contains(Object o) { + return containsKey(o); + } + public boolean remove(Object o) { + return Hashtable.this.remove(o) != null; + } + public void clear() { + Hashtable.this.clear(); + } + } + + /** + * 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 remove operation, or through the + * 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 Iterator.remove, + * Set.remove, removeAll, retainAll and + * clear operations. It does not support the + * add or addAll operations. + * + * @since 1.2 + */ + public Set> entrySet() { + if (entrySet==null) + entrySet = Collections.synchronizedSet(new EntrySet(), this); + return entrySet; + } + + private class EntrySet extends AbstractSet> { + public Iterator> iterator() { + return getIterator(ENTRIES); + } + + public boolean add(Map.Entry o) { + return super.add(o); + } + + public boolean contains(Object o) { + if (!(o instanceof Map.Entry)) + return false; + Map.Entry entry = (Map.Entry)o; + Object key = entry.getKey(); + Entry[] tab = table; + int hash = key.hashCode(); + int index = (hash & 0x7FFFFFFF) % tab.length; + + for (Entry e = tab[index]; e != null; e = e.next) + if (e.hash==hash && e.equals(entry)) + return true; + return false; + } + + public boolean remove(Object o) { + if (!(o instanceof Map.Entry)) + return false; + Map.Entry entry = (Map.Entry) o; + K key = entry.getKey(); + Entry[] tab = table; + int hash = key.hashCode(); + int index = (hash & 0x7FFFFFFF) % tab.length; + + for (Entry e = tab[index], prev = null; e != null; + prev = e, e = e.next) { + if (e.hash==hash && e.equals(entry)) { + modCount++; + if (prev != null) + prev.next = e.next; + else + tab[index] = e.next; + + count--; + e.value = null; + return true; + } + } + return false; + } + + public int size() { + return count; + } + + public void clear() { + Hashtable.this.clear(); + } + } + + /** + * 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 remove operation), + * the results of the iteration are undefined. The collection + * supports element removal, which removes the corresponding + * mapping from the map, via the Iterator.remove, + * Collection.remove, removeAll, + * retainAll and clear operations. It does not + * support the add or addAll operations. + * + * @since 1.2 + */ + public Collection values() { + if (values==null) + values = Collections.synchronizedCollection(new ValueCollection(), + this); + return values; + } + + private class ValueCollection extends AbstractCollection { + public Iterator iterator() { + return getIterator(VALUES); + } + public int size() { + return count; + } + public boolean contains(Object o) { + return containsValue(o); + } + public void clear() { + Hashtable.this.clear(); + } + } + + // Comparison and hashing + + /** + * Compares the specified Object with this Map for equality, + * as per the definition in the Map interface. + * + * @param o object to be compared for equality with this hashtable + * @return true if the specified Object is equal to this Map + * @see Map#equals(Object) + * @since 1.2 + */ + public synchronized boolean equals(Object o) { + if (o == this) + return true; + + if (!(o instanceof Map)) + return false; + Map t = (Map) o; + if (t.size() != size()) + return false; + + try { + Iterator> i = entrySet().iterator(); + while (i.hasNext()) { + Map.Entry e = i.next(); + K key = e.getKey(); + V value = e.getValue(); + if (value == null) { + if (!(t.get(key)==null && t.containsKey(key))) + return false; + } else { + if (!value.equals(t.get(key))) + return false; + } + } + } catch (ClassCastException unused) { + return false; + } catch (NullPointerException unused) { + return false; + } + + return true; + } + + /** + * Returns the hash code value for this Map as per the definition in the + * Map interface. + * + * @see Map#hashCode() + * @since 1.2 + */ + public synchronized int hashCode() { + /* + * This code detects the recursion caused by computing the hash code + * of a self-referential hash table and prevents the stack overflow + * that would otherwise result. This allows certain 1.1-era + * applets with self-referential hash tables to work. This code + * abuses the loadFactor field to do double-duty as a hashCode + * in progress flag, so as not to worsen the space performance. + * A negative load factor indicates that hash code computation is + * in progress. + */ + int h = 0; + if (count == 0 || loadFactor < 0) + return h; // Returns zero + + loadFactor = -loadFactor; // Mark hashCode computation in progress + Entry[] tab = table; + for (int i = 0; i < tab.length; i++) + for (Entry e = tab[i]; e != null; e = e.next) + h += e.key.hashCode() ^ e.value.hashCode(); + loadFactor = -loadFactor; // Mark hashCode computation complete + + return h; + } + + /** + * Save the state of the Hashtable to a stream (i.e., serialize it). + * + * @serialData The capacity of the Hashtable (the length of the + * bucket array) is emitted (int), followed by the + * size of the Hashtable (the number of key-value + * mappings), followed by the key (Object) and value (Object) + * for each key-value mapping represented by the Hashtable + * The key-value mappings are emitted in no particular order. + */ + private void writeObject(java.io.ObjectOutputStream s) + throws IOException { + Entry entryStack = null; + + synchronized (this) { + // Write out the length, threshold, loadfactor + s.defaultWriteObject(); + + // Write out length, count of elements + s.writeInt(table.length); + s.writeInt(count); + + // Stack copies of the entries in the table + for (int index = 0; index < table.length; index++) { + Entry entry = table[index]; + + while (entry != null) { + entryStack = + new Entry<>(0, entry.key, entry.value, entryStack); + entry = entry.next; + } + } + } + + // Write out the key/value objects from the stacked entries + while (entryStack != null) { + s.writeObject(entryStack.key); + s.writeObject(entryStack.value); + entryStack = entryStack.next; + } + } + + /** + * Reconstitute the Hashtable from a stream (i.e., deserialize it). + */ + private void readObject(java.io.ObjectInputStream s) + throws IOException, ClassNotFoundException + { + // Read in the length, threshold, and loadfactor + s.defaultReadObject(); + + // Read the original length of the array and number of elements + int origlength = s.readInt(); + int elements = s.readInt(); + + // Compute new size with a bit of room 5% to grow but + // no larger than the original size. Make the length + // odd if it's large enough, this helps distribute the entries. + // Guard against the length ending up zero, that's not valid. + int length = (int)(elements * loadFactor) + (elements / 20) + 3; + if (length > elements && (length & 1) == 0) + length--; + if (origlength > 0 && length > origlength) + length = origlength; + + Entry[] table = new Entry[length]; + count = 0; + + // Read the number of elements and then all the key/value objects + for (; elements > 0; elements--) { + K key = (K)s.readObject(); + V value = (V)s.readObject(); + // synch could be eliminated for performance + reconstitutionPut(table, key, value); + } + this.table = table; + } + + /** + * The put method used by readObject. This is provided because put + * is overridable and should not be called in readObject since the + * subclass will not yet be initialized. + * + *

This differs from the regular put method in several ways. No + * checking for rehashing is necessary since the number of elements + * initially in the table is known. The modCount is not incremented + * because we are creating a new instance. Also, no return value + * is needed. + */ + private void reconstitutionPut(Entry[] tab, K key, V value) + throws StreamCorruptedException + { + if (value == null) { + throw new java.io.StreamCorruptedException(); + } + // Makes sure the key is not already in the hashtable. + // This should not happen in deserialized version. + int hash = key.hashCode(); + int index = (hash & 0x7FFFFFFF) % tab.length; + for (Entry e = tab[index] ; e != null ; e = e.next) { + if ((e.hash == hash) && e.key.equals(key)) { + throw new java.io.StreamCorruptedException(); + } + } + // Creates the new entry. + Entry e = tab[index]; + tab[index] = new Entry<>(hash, key, value, e); + count++; + } + + /** + * Hashtable collision list. + */ + private static class Entry implements Map.Entry { + int hash; + K key; + V value; + Entry next; + + protected Entry(int hash, K key, V value, Entry next) { + this.hash = hash; + this.key = key; + this.value = value; + this.next = next; + } + + protected Object clone() { + return new Entry<>(hash, key, value, + (next==null ? null : (Entry) next.clone())); + } + + // Map.Entry Ops + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V value) { + if (value == null) + throw new NullPointerException(); + + V oldValue = this.value; + this.value = value; + return oldValue; + } + + public boolean equals(Object o) { + if (!(o instanceof Map.Entry)) + return false; + Map.Entry e = (Map.Entry)o; + + return (key==null ? e.getKey()==null : key.equals(e.getKey())) && + (value==null ? e.getValue()==null : value.equals(e.getValue())); + } + + public int hashCode() { + return hash ^ (value==null ? 0 : value.hashCode()); + } + + public String toString() { + return key.toString()+"="+value.toString(); + } + } + + // Types of Enumerations/Iterations + private static final int KEYS = 0; + private static final int VALUES = 1; + private static final int ENTRIES = 2; + + /** + * A hashtable enumerator class. This class implements both the + * Enumeration and Iterator interfaces, but individual instances + * can be created with the Iterator methods disabled. This is necessary + * to avoid unintentionally increasing the capabilities granted a user + * by passing an Enumeration. + */ + private class Enumerator implements Enumeration, Iterator { + Entry[] table = Hashtable.this.table; + int index = table.length; + Entry entry = null; + Entry lastReturned = null; + int type; + + /** + * Indicates whether this Enumerator is serving as an Iterator + * or an Enumeration. (true -> Iterator). + */ + boolean iterator; + + /** + * The modCount value that the iterator believes that the backing + * Hashtable should have. If this expectation is violated, the iterator + * has detected concurrent modification. + */ + protected int expectedModCount = modCount; + + Enumerator(int type, boolean iterator) { + this.type = type; + this.iterator = iterator; + } + + public boolean hasMoreElements() { + Entry e = entry; + int i = index; + Entry[] t = table; + /* Use locals for faster loop iteration */ + while (e == null && i > 0) { + e = t[--i]; + } + entry = e; + index = i; + return e != null; + } + + public T nextElement() { + Entry et = entry; + int i = index; + Entry[] t = table; + /* Use locals for faster loop iteration */ + while (et == null && i > 0) { + et = t[--i]; + } + entry = et; + index = i; + if (et != null) { + Entry e = lastReturned = entry; + entry = e.next; + return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e); + } + throw new NoSuchElementException("Hashtable Enumerator"); + } + + // Iterator methods + public boolean hasNext() { + return hasMoreElements(); + } + + public T next() { + if (modCount != expectedModCount) + throw new ConcurrentModificationException(); + return nextElement(); + } + + public void remove() { + if (!iterator) + throw new UnsupportedOperationException(); + if (lastReturned == null) + throw new IllegalStateException("Hashtable Enumerator"); + if (modCount != expectedModCount) + throw new ConcurrentModificationException(); + + synchronized(Hashtable.this) { + Entry[] tab = Hashtable.this.table; + int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length; + + for (Entry e = tab[index], prev = null; e != null; + prev = e, e = e.next) { + if (e == lastReturned) { + modCount++; + expectedModCount++; + if (prev == null) + tab[index] = e.next; + else + prev.next = e.next; + count--; + lastReturned = null; + return; + } + } + throw new ConcurrentModificationException(); + } + } + } +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/LinkedList.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/LinkedList.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,1138 @@ +/* + * 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; + +/** + * Doubly-linked list implementation of the {@code List} and {@code Deque} + * interfaces. Implements all optional list operations, and permits all + * elements (including {@code null}). + * + *

All of the operations perform as could be expected for a doubly-linked + * list. Operations that index into the list will traverse the list from + * the beginning or the end, whichever is closer to the specified index. + * + *

Note that this implementation is not synchronized. + * If multiple threads access a linked list concurrently, and at least + * one of the threads modifies the list structurally, it must be + * synchronized externally. (A structural modification is any operation + * that adds or deletes one or more elements; merely setting the value of + * an element is not a structural modification.) This is typically + * accomplished by synchronizing on some object that naturally + * encapsulates the list. + * + * If no such object exists, the list should be "wrapped" using the + * {@link Collections#synchronizedList Collections.synchronizedList} + * method. This is best done at creation time, to prevent accidental + * unsynchronized access to the list:

+ *   List list = Collections.synchronizedList(new LinkedList(...));
+ * + *

The iterators returned by this class's {@code iterator} and + * {@code listIterator} methods are fail-fast: if the list is + * structurally modified at any time after the iterator is created, in + * any way except through the Iterator's own {@code remove} or + * {@code add} methods, 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. + * + *

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: the fail-fast behavior of iterators + * should be used only to detect bugs. + * + *

This class is a member of the + * + * Java Collections Framework. + * + * @author Josh Bloch + * @see List + * @see ArrayList + * @since 1.2 + * @param the type of elements held in this collection + */ + +public class LinkedList + extends AbstractSequentialList + implements List, Deque, Cloneable, java.io.Serializable +{ + transient int size = 0; + + /** + * Pointer to first node. + * Invariant: (first == null && last == null) || + * (first.prev == null && first.item != null) + */ + transient Node first; + + /** + * Pointer to last node. + * Invariant: (first == null && last == null) || + * (last.next == null && last.item != null) + */ + transient Node last; + + /** + * Constructs an empty list. + */ + public LinkedList() { + } + + /** + * Constructs a list containing the elements of the specified + * collection, in the order they are returned by the collection's + * iterator. + * + * @param c the collection whose elements are to be placed into this list + * @throws NullPointerException if the specified collection is null + */ + public LinkedList(Collection c) { + this(); + addAll(c); + } + + /** + * Links e as first element. + */ + private void linkFirst(E e) { + final Node f = first; + final Node newNode = new Node<>(null, e, f); + first = newNode; + if (f == null) + last = newNode; + else + f.prev = newNode; + size++; + modCount++; + } + + /** + * Links e as last element. + */ + void linkLast(E e) { + final Node l = last; + final Node newNode = new Node<>(l, e, null); + last = newNode; + if (l == null) + first = newNode; + else + l.next = newNode; + size++; + modCount++; + } + + /** + * Inserts element e before non-null Node succ. + */ + void linkBefore(E e, Node succ) { + // assert succ != null; + final Node pred = succ.prev; + final Node newNode = new Node<>(pred, e, succ); + succ.prev = newNode; + if (pred == null) + first = newNode; + else + pred.next = newNode; + size++; + modCount++; + } + + /** + * Unlinks non-null first node f. + */ + private E unlinkFirst(Node f) { + // assert f == first && f != null; + final E element = f.item; + final Node next = f.next; + f.item = null; + f.next = null; // help GC + first = next; + if (next == null) + last = null; + else + next.prev = null; + size--; + modCount++; + return element; + } + + /** + * Unlinks non-null last node l. + */ + private E unlinkLast(Node l) { + // assert l == last && l != null; + final E element = l.item; + final Node prev = l.prev; + l.item = null; + l.prev = null; // help GC + last = prev; + if (prev == null) + first = null; + else + prev.next = null; + size--; + modCount++; + return element; + } + + /** + * Unlinks non-null node x. + */ + E unlink(Node x) { + // assert x != null; + final E element = x.item; + final Node next = x.next; + final Node prev = x.prev; + + if (prev == null) { + first = next; + } else { + prev.next = next; + x.prev = null; + } + + if (next == null) { + last = prev; + } else { + next.prev = prev; + x.next = null; + } + + x.item = null; + size--; + modCount++; + return element; + } + + /** + * Returns the first element in this list. + * + * @return the first element in this list + * @throws NoSuchElementException if this list is empty + */ + public E getFirst() { + final Node f = first; + if (f == null) + throw new NoSuchElementException(); + return f.item; + } + + /** + * Returns the last element in this list. + * + * @return the last element in this list + * @throws NoSuchElementException if this list is empty + */ + public E getLast() { + final Node l = last; + if (l == null) + throw new NoSuchElementException(); + return l.item; + } + + /** + * Removes and returns the first element from this list. + * + * @return the first element from this list + * @throws NoSuchElementException if this list is empty + */ + public E removeFirst() { + final Node f = first; + if (f == null) + throw new NoSuchElementException(); + return unlinkFirst(f); + } + + /** + * Removes and returns the last element from this list. + * + * @return the last element from this list + * @throws NoSuchElementException if this list is empty + */ + public E removeLast() { + final Node l = last; + if (l == null) + throw new NoSuchElementException(); + return unlinkLast(l); + } + + /** + * Inserts the specified element at the beginning of this list. + * + * @param e the element to add + */ + public void addFirst(E e) { + linkFirst(e); + } + + /** + * Appends the specified element to the end of this list. + * + *

This method is equivalent to {@link #add}. + * + * @param e the element to add + */ + public void addLast(E e) { + linkLast(e); + } + + /** + * Returns {@code true} if this list contains the specified element. + * More formally, returns {@code true} if and only if this list contains + * at least one element {@code e} such that + * (o==null ? e==null : o.equals(e)). + * + * @param o element whose presence in this list is to be tested + * @return {@code true} if this list contains the specified element + */ + public boolean contains(Object o) { + return indexOf(o) != -1; + } + + /** + * Returns the number of elements in this list. + * + * @return the number of elements in this list + */ + public int size() { + return size; + } + + /** + * Appends the specified element to the end of this list. + * + *

This method is equivalent to {@link #addLast}. + * + * @param e element to be appended to this list + * @return {@code true} (as specified by {@link Collection#add}) + */ + public boolean add(E e) { + linkLast(e); + return true; + } + + /** + * Removes the first occurrence of the specified element from this list, + * if it is present. If this list does not contain the element, it is + * unchanged. More formally, removes the element with the lowest index + * {@code i} such that + * (o==null ? get(i)==null : o.equals(get(i))) + * (if such an element exists). Returns {@code true} 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 {@code true} if this list contained the specified element + */ + public boolean remove(Object o) { + if (o == null) { + for (Node x = first; x != null; x = x.next) { + if (x.item == null) { + unlink(x); + return true; + } + } + } else { + for (Node x = first; x != null; x = x.next) { + if (o.equals(x.item)) { + unlink(x); + return true; + } + } + } + return false; + } + + /** + * 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. 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 {@code true} if this list changed as a result of the call + * @throws NullPointerException if the specified collection is null + */ + public boolean addAll(Collection c) { + return addAll(size, c); + } + + /** + * Inserts all of the elements in the specified collection into this + * list, starting at the specified position. 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 the list in the order that they are returned by the + * specified collection's iterator. + * + * @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 {@code true} if this list changed as a result of the call + * @throws IndexOutOfBoundsException {@inheritDoc} + * @throws NullPointerException if the specified collection is null + */ + public boolean addAll(int index, Collection c) { + checkPositionIndex(index); + + Object[] a = c.toArray(); + int numNew = a.length; + if (numNew == 0) + return false; + + Node pred, succ; + if (index == size) { + succ = null; + pred = last; + } else { + succ = node(index); + pred = succ.prev; + } + + for (Object o : a) { + @SuppressWarnings("unchecked") E e = (E) o; + Node newNode = new Node<>(pred, e, null); + if (pred == null) + first = newNode; + else + pred.next = newNode; + pred = newNode; + } + + if (succ == null) { + last = pred; + } else { + pred.next = succ; + succ.prev = pred; + } + + size += numNew; + modCount++; + return true; + } + + /** + * Removes all of the elements from this list. + * The list will be empty after this call returns. + */ + public void clear() { + // Clearing all of the links between nodes is "unnecessary", but: + // - helps a generational GC if the discarded nodes inhabit + // more than one generation + // - is sure to free memory even if there is a reachable Iterator + for (Node x = first; x != null; ) { + Node next = x.next; + x.item = null; + x.next = null; + x.prev = null; + x = next; + } + first = last = null; + size = 0; + modCount++; + } + + + // 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 {@inheritDoc} + */ + public E get(int index) { + checkElementIndex(index); + return node(index).item; + } + + /** + * Replaces the element at the specified position in this list with the + * specified element. + * + * @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 IndexOutOfBoundsException {@inheritDoc} + */ + public E set(int index, E element) { + checkElementIndex(index); + Node x = node(index); + E oldVal = x.item; + x.item = element; + return oldVal; + } + + /** + * Inserts the specified element at the specified position in this list. + * 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 IndexOutOfBoundsException {@inheritDoc} + */ + public void add(int index, E element) { + checkPositionIndex(index); + + if (index == size) + linkLast(element); + else + linkBefore(element, node(index)); + } + + /** + * Removes the element at the specified position in this list. 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 IndexOutOfBoundsException {@inheritDoc} + */ + public E remove(int index) { + checkElementIndex(index); + return unlink(node(index)); + } + + /** + * Tells if the argument is the index of an existing element. + */ + private boolean isElementIndex(int index) { + return index >= 0 && index < size; + } + + /** + * Tells if the argument is the index of a valid position for an + * iterator or an add operation. + */ + private boolean isPositionIndex(int index) { + return index >= 0 && index <= size; + } + + /** + * Constructs an IndexOutOfBoundsException detail message. + * Of the many possible refactorings of the error handling code, + * this "outlining" performs best with both server and client VMs. + */ + private String outOfBoundsMsg(int index) { + return "Index: "+index+", Size: "+size; + } + + private void checkElementIndex(int index) { + if (!isElementIndex(index)) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private void checkPositionIndex(int index) { + if (!isPositionIndex(index)) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + /** + * Returns the (non-null) Node at the specified element index. + */ + Node node(int index) { + // assert isElementIndex(index); + + if (index < (size >> 1)) { + Node x = first; + for (int i = 0; i < index; i++) + x = x.next; + return x; + } else { + Node x = last; + for (int i = size - 1; i > index; i--) + x = x.prev; + return x; + } + } + + // 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 {@code i} such that + * (o==null ? get(i)==null : o.equals(get(i))), + * 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 + */ + public int indexOf(Object o) { + int index = 0; + if (o == null) { + for (Node x = first; x != null; x = x.next) { + if (x.item == null) + return index; + index++; + } + } else { + for (Node x = first; x != null; x = x.next) { + if (o.equals(x.item)) + return index; + index++; + } + } + return -1; + } + + /** + * 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 {@code i} such that + * (o==null ? get(i)==null : o.equals(get(i))), + * 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 + */ + public int lastIndexOf(Object o) { + int index = size; + if (o == null) { + for (Node x = last; x != null; x = x.prev) { + index--; + if (x.item == null) + return index; + } + } else { + for (Node x = last; x != null; x = x.prev) { + index--; + if (o.equals(x.item)) + return index; + } + } + return -1; + } + + // Queue operations. + + /** + * Retrieves, but does not remove, the head (first element) of this list. + * + * @return the head of this list, or {@code null} if this list is empty + * @since 1.5 + */ + public E peek() { + final Node f = first; + return (f == null) ? null : f.item; + } + + /** + * Retrieves, but does not remove, the head (first element) of this list. + * + * @return the head of this list + * @throws NoSuchElementException if this list is empty + * @since 1.5 + */ + public E element() { + return getFirst(); + } + + /** + * Retrieves and removes the head (first element) of this list. + * + * @return the head of this list, or {@code null} if this list is empty + * @since 1.5 + */ + public E poll() { + final Node f = first; + return (f == null) ? null : unlinkFirst(f); + } + + /** + * Retrieves and removes the head (first element) of this list. + * + * @return the head of this list + * @throws NoSuchElementException if this list is empty + * @since 1.5 + */ + public E remove() { + return removeFirst(); + } + + /** + * Adds the specified element as the tail (last element) of this list. + * + * @param e the element to add + * @return {@code true} (as specified by {@link Queue#offer}) + * @since 1.5 + */ + public boolean offer(E e) { + return add(e); + } + + // Deque operations + /** + * Inserts the specified element at the front of this list. + * + * @param e the element to insert + * @return {@code true} (as specified by {@link Deque#offerFirst}) + * @since 1.6 + */ + public boolean offerFirst(E e) { + addFirst(e); + return true; + } + + /** + * Inserts the specified element at the end of this list. + * + * @param e the element to insert + * @return {@code true} (as specified by {@link Deque#offerLast}) + * @since 1.6 + */ + public boolean offerLast(E e) { + addLast(e); + return true; + } + + /** + * Retrieves, but does not remove, the first element of this list, + * or returns {@code null} if this list is empty. + * + * @return the first element of this list, or {@code null} + * if this list is empty + * @since 1.6 + */ + public E peekFirst() { + final Node f = first; + return (f == null) ? null : f.item; + } + + /** + * Retrieves, but does not remove, the last element of this list, + * or returns {@code null} if this list is empty. + * + * @return the last element of this list, or {@code null} + * if this list is empty + * @since 1.6 + */ + public E peekLast() { + final Node l = last; + return (l == null) ? null : l.item; + } + + /** + * Retrieves and removes the first element of this list, + * or returns {@code null} if this list is empty. + * + * @return the first element of this list, or {@code null} if + * this list is empty + * @since 1.6 + */ + public E pollFirst() { + final Node f = first; + return (f == null) ? null : unlinkFirst(f); + } + + /** + * Retrieves and removes the last element of this list, + * or returns {@code null} if this list is empty. + * + * @return the last element of this list, or {@code null} if + * this list is empty + * @since 1.6 + */ + public E pollLast() { + final Node l = last; + return (l == null) ? null : unlinkLast(l); + } + + /** + * Pushes an element onto the stack represented by this list. In other + * words, inserts the element at the front of this list. + * + *

This method is equivalent to {@link #addFirst}. + * + * @param e the element to push + * @since 1.6 + */ + public void push(E e) { + addFirst(e); + } + + /** + * Pops an element from the stack represented by this list. In other + * words, removes and returns the first element of this list. + * + *

This method is equivalent to {@link #removeFirst()}. + * + * @return the element at the front of this list (which is the top + * of the stack represented by this list) + * @throws NoSuchElementException if this list is empty + * @since 1.6 + */ + public E pop() { + return removeFirst(); + } + + /** + * Removes the first occurrence of the specified element in this + * list (when traversing the list from head to tail). If the list + * does not contain the element, it is unchanged. + * + * @param o element to be removed from this list, if present + * @return {@code true} if the list contained the specified element + * @since 1.6 + */ + public boolean removeFirstOccurrence(Object o) { + return remove(o); + } + + /** + * Removes the last occurrence of the specified element in this + * list (when traversing the list from head to tail). If the list + * does not contain the element, it is unchanged. + * + * @param o element to be removed from this list, if present + * @return {@code true} if the list contained the specified element + * @since 1.6 + */ + public boolean removeLastOccurrence(Object o) { + if (o == null) { + for (Node x = last; x != null; x = x.prev) { + if (x.item == null) { + unlink(x); + return true; + } + } + } else { + for (Node x = last; x != null; x = x.prev) { + if (o.equals(x.item)) { + unlink(x); + return true; + } + } + } + return false; + } + + /** + * Returns a list-iterator of the elements in this list (in proper + * sequence), starting at the specified position in the list. + * Obeys the general contract of {@code List.listIterator(int)}.

+ * + * The list-iterator is fail-fast: if the list is structurally + * modified at any time after the Iterator is created, in any way except + * through the list-iterator's own {@code remove} or {@code add} + * methods, the list-iterator will throw a + * {@code 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. + * + * @param index index of the first element to be returned from the + * list-iterator (by a call to {@code next}) + * @return a ListIterator of the elements in this list (in proper + * sequence), starting at the specified position in the list + * @throws IndexOutOfBoundsException {@inheritDoc} + * @see List#listIterator(int) + */ + public ListIterator listIterator(int index) { + checkPositionIndex(index); + return new ListItr(index); + } + + private class ListItr implements ListIterator { + private Node lastReturned = null; + private Node next; + private int nextIndex; + private int expectedModCount = modCount; + + ListItr(int index) { + // assert isPositionIndex(index); + next = (index == size) ? null : node(index); + nextIndex = index; + } + + public boolean hasNext() { + return nextIndex < size; + } + + public E next() { + checkForComodification(); + if (!hasNext()) + throw new NoSuchElementException(); + + lastReturned = next; + next = next.next; + nextIndex++; + return lastReturned.item; + } + + public boolean hasPrevious() { + return nextIndex > 0; + } + + public E previous() { + checkForComodification(); + if (!hasPrevious()) + throw new NoSuchElementException(); + + lastReturned = next = (next == null) ? last : next.prev; + nextIndex--; + return lastReturned.item; + } + + public int nextIndex() { + return nextIndex; + } + + public int previousIndex() { + return nextIndex - 1; + } + + public void remove() { + checkForComodification(); + if (lastReturned == null) + throw new IllegalStateException(); + + Node lastNext = lastReturned.next; + unlink(lastReturned); + if (next == lastReturned) + next = lastNext; + else + nextIndex--; + lastReturned = null; + expectedModCount++; + } + + public void set(E e) { + if (lastReturned == null) + throw new IllegalStateException(); + checkForComodification(); + lastReturned.item = e; + } + + public void add(E e) { + checkForComodification(); + lastReturned = null; + if (next == null) + linkLast(e); + else + linkBefore(e, next); + nextIndex++; + expectedModCount++; + } + + final void checkForComodification() { + if (modCount != expectedModCount) + throw new ConcurrentModificationException(); + } + } + + private static class Node { + E item; + Node next; + Node prev; + + Node(Node prev, E element, Node next) { + this.item = element; + this.next = next; + this.prev = prev; + } + } + + /** + * @since 1.6 + */ + public Iterator descendingIterator() { + return new DescendingIterator(); + } + + /** + * Adapter to provide descending iterators via ListItr.previous + */ + private class DescendingIterator implements Iterator { + private final ListItr itr = new ListItr(size()); + public boolean hasNext() { + return itr.hasPrevious(); + } + public E next() { + return itr.previous(); + } + public void remove() { + itr.remove(); + } + } + + @SuppressWarnings("unchecked") + private LinkedList superClone() { + try { + return (LinkedList) super.clone(); + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } + + /** + * Returns a shallow copy of this {@code LinkedList}. (The elements + * themselves are not cloned.) + * + * @return a shallow copy of this {@code LinkedList} instance + */ + public Object clone() { + LinkedList clone = superClone(); + + // Put clone into "virgin" state + clone.first = clone.last = null; + clone.size = 0; + clone.modCount = 0; + + // Initialize clone with our elements + for (Node x = first; x != null; x = x.next) + clone.add(x.item); + + return clone; + } + + /** + * Returns an array containing all of the elements in this list + * in proper sequence (from first to last element). + * + *

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). The caller is thus free to modify the returned array. + * + *

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 + */ + public Object[] toArray() { + Object[] result = new Object[size]; + int i = 0; + for (Node x = first; x != null; x = x.next) + result[i++] = x.item; + return result; + } + + /** + * 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. + * + *

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 {@code null}. + * (This is useful in determining the length of the list only if + * the caller knows that the list does not contain any null elements.) + * + *

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. + * + *

Suppose {@code x} is a list known to contain only strings. + * The following code can be used to dump the list into a newly + * allocated array of {@code String}: + * + *

+     *     String[] y = x.toArray(new String[0]);
+ * + * Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. + * + * @param a the array into which the elements of the 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 the 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 + */ + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + if (a.length < size) + a = (T[])java.lang.reflect.Array.newInstance( + a.getClass().getComponentType(), size); + int i = 0; + Object[] result = a; + for (Node x = first; x != null; x = x.next) + result[i++] = x.item; + + if (a.length > size) + a[size] = null; + + return a; + } + + private static final long serialVersionUID = 876323262645176354L; + + /** + * Saves the state of this {@code LinkedList} instance to a stream + * (that is, serializes it). + * + * @serialData The size of the list (the number of elements it + * contains) is emitted (int), followed by all of its + * elements (each an Object) in the proper order. + */ + private void writeObject(java.io.ObjectOutputStream s) + throws java.io.IOException { + // Write out any hidden serialization magic + s.defaultWriteObject(); + + // Write out size + s.writeInt(size); + + // Write out all elements in the proper order. + for (Node x = first; x != null; x = x.next) + s.writeObject(x.item); + } + + /** + * Reconstitutes this {@code LinkedList} instance from a stream + * (that is, deserializes it). + */ + @SuppressWarnings("unchecked") + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + // Read in any hidden serialization magic + s.defaultReadObject(); + + // Read in size + int size = s.readInt(); + + // Read in all elements in the proper order. + for (int i = 0; i < size; i++) + linkLast((E)s.readObject()); + } +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/Queue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/Queue.java Mon Jan 28 13:30:53 2013 +0100 @@ -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 null or false, depending on the + * operation). The latter form of the insert operation is designed + * specifically for use with capacity-restricted Queue + * implementations; in most implementations, insert operations cannot + * fail. + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Throws exceptionReturns special value
Insert{@link #add add(e)}{@link #offer offer(e)}
Remove{@link #remove remove()}{@link #poll poll()}
Examine{@link #element element()}{@link #peek peek()}
+ * + *

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 head 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 tail of the queue. Other kinds of queues may use + * different placement rules. Every Queue implementation + * must specify its ordering properties. + * + *

The {@link #offer offer} method inserts an element if possible, + * otherwise returning 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 + * offer method is designed for use when failure is a normal, + * rather than exceptional occurrence, for example, in fixed-capacity + * (or "bounded") queues. + * + *

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 remove() and + * poll() methods differ only in their behavior when the + * queue is empty: the remove() method throws an exception, + * while the poll() method returns null. + * + *

The {@link #element()} and {@link #peek()} methods return, but do + * not remove, the head of the queue. + * + *

The Queue interface does not define the blocking queue + * methods, 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. + * + *

Queue implementations generally do not allow insertion + * of null elements, although some implementations, such as + * {@link LinkedList}, do not prohibit insertion of null. + * Even in the implementations that permit it, null should + * not be inserted into a Queue, as null is also + * used as a special return value by the poll method to + * indicate that the queue contains no elements. + * + *

Queue implementations generally do not define + * element-based versions of methods equals and + * hashCode but instead inherit the identity based versions + * from class Object, because element-based equality is not + * always well-defined for queues with the same elements but different + * ordering properties. + * + * + *

This interface is a member of the + * + * Java Collections Framework. + * + * @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 the type of elements held in this collection + */ +public interface Queue extends Collection { + /** + * Inserts the specified element into this queue if it is possible to do so + * immediately without violating capacity restrictions, returning + * true upon success and throwing an IllegalStateException + * if no space is currently available. + * + * @param e the element to add + * @return 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 true if the element was added to this queue, else + * 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 null if this queue is empty. + * + * @return the head of this queue, or 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 null if this queue is empty. + * + * @return the head of this queue, or null if this queue is empty + */ + E peek(); +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/Random.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/Random.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,575 @@ +/* + * Copyright (c) 1995, 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; +import java.io.*; +import java.util.concurrent.atomic.AtomicLong; +import sun.misc.Unsafe; + +/** + * An instance of this class is used to generate a stream of + * pseudorandom numbers. The class uses a 48-bit seed, which is + * modified using a linear congruential formula. (See Donald Knuth, + * The Art of Computer Programming, Volume 2, Section 3.2.1.) + *

+ * If two instances of {@code Random} are created with the same + * seed, and the same sequence of method calls is made for each, they + * will generate and return identical sequences of numbers. In order to + * guarantee this property, particular algorithms are specified for the + * class {@code Random}. Java implementations must use all the algorithms + * shown here for the class {@code Random}, for the sake of absolute + * portability of Java code. However, subclasses of class {@code Random} + * are permitted to use other algorithms, so long as they adhere to the + * general contracts for all the methods. + *

+ * The algorithms implemented by class {@code Random} use a + * {@code protected} utility method that on each invocation can supply + * up to 32 pseudorandomly generated bits. + *

+ * Many applications will find the method {@link Math#random} simpler to use. + * + *

Instances of {@code java.util.Random} are threadsafe. + * However, the concurrent use of the same {@code java.util.Random} + * instance across threads may encounter contention and consequent + * poor performance. Consider instead using + * {@link java.util.concurrent.ThreadLocalRandom} in multithreaded + * designs. + * + *

Instances of {@code java.util.Random} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} to + * get a cryptographically secure pseudo-random number generator for use + * by security-sensitive applications. + * + * @author Frank Yellin + * @since 1.0 + */ +public +class Random implements java.io.Serializable { + /** use serialVersionUID from JDK 1.1 for interoperability */ + static final long serialVersionUID = 3905348978240129619L; + + /** + * The internal state associated with this pseudorandom number generator. + * (The specs for the methods in this class describe the ongoing + * computation of this value.) + */ + private final AtomicLong seed; + + private static final long multiplier = 0x5DEECE66DL; + private static final long addend = 0xBL; + private static final long mask = (1L << 48) - 1; + + /** + * Creates a new random number generator. This constructor sets + * the seed of the random number generator to a value very likely + * to be distinct from any other invocation of this constructor. + */ + public Random() { + this(seedUniquifier() ^ System.nanoTime()); + } + + private static long seedUniquifier() { + // L'Ecuyer, "Tables of Linear Congruential Generators of + // Different Sizes and Good Lattice Structure", 1999 + for (;;) { + long current = seedUniquifier.get(); + long next = current * 181783497276652981L; + if (seedUniquifier.compareAndSet(current, next)) + return next; + } + } + + private static final AtomicLong seedUniquifier + = new AtomicLong(8682522807148012L); + + /** + * Creates a new random number generator using a single {@code long} seed. + * The seed is the initial value of the internal state of the pseudorandom + * number generator which is maintained by method {@link #next}. + * + *

The invocation {@code new Random(seed)} is equivalent to: + *

 {@code
+     * Random rnd = new Random();
+     * rnd.setSeed(seed);}
+ * + * @param seed the initial seed + * @see #setSeed(long) + */ + public Random(long seed) { + this.seed = new AtomicLong(initialScramble(seed)); + } + + private static long initialScramble(long seed) { + return (seed ^ multiplier) & mask; + } + + /** + * Sets the seed of this random number generator using a single + * {@code long} seed. The general contract of {@code setSeed} is + * that it alters the state of this random number generator object + * so as to be in exactly the same state as if it had just been + * created with the argument {@code seed} as a seed. The method + * {@code setSeed} is implemented by class {@code Random} by + * atomically updating the seed to + *
{@code (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1)}
+ * and clearing the {@code haveNextNextGaussian} flag used by {@link + * #nextGaussian}. + * + *

The implementation of {@code setSeed} by class {@code Random} + * happens to use only 48 bits of the given seed. In general, however, + * an overriding method may use all 64 bits of the {@code long} + * argument as a seed value. + * + * @param seed the initial seed + */ + synchronized public void setSeed(long seed) { + this.seed.set(initialScramble(seed)); + haveNextNextGaussian = false; + } + + /** + * Generates the next pseudorandom number. Subclasses should + * override this, as this is used by all other methods. + * + *

The general contract of {@code next} is that it returns an + * {@code int} value and if the argument {@code bits} is between + * {@code 1} and {@code 32} (inclusive), then that many low-order + * bits of the returned value will be (approximately) independently + * chosen bit values, each of which is (approximately) equally + * likely to be {@code 0} or {@code 1}. The method {@code next} is + * implemented by class {@code Random} by atomically updating the seed to + *

{@code (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)}
+ * and returning + *
{@code (int)(seed >>> (48 - bits))}.
+ * + * This is a linear congruential pseudorandom number generator, as + * defined by D. H. Lehmer and described by Donald E. Knuth in + * The Art of Computer Programming, Volume 3: + * Seminumerical Algorithms, section 3.2.1. + * + * @param bits random bits + * @return the next pseudorandom value from this random number + * generator's sequence + * @since 1.1 + */ + protected int next(int bits) { + long oldseed, nextseed; + AtomicLong seed = this.seed; + do { + oldseed = seed.get(); + nextseed = (oldseed * multiplier + addend) & mask; + } while (!seed.compareAndSet(oldseed, nextseed)); + return (int)(nextseed >>> (48 - bits)); + } + + /** + * Generates random bytes and places them into a user-supplied + * byte array. The number of random bytes produced is equal to + * the length of the byte array. + * + *

The method {@code nextBytes} is implemented by class {@code Random} + * as if by: + *

 {@code
+     * public void nextBytes(byte[] bytes) {
+     *   for (int i = 0; i < bytes.length; )
+     *     for (int rnd = nextInt(), n = Math.min(bytes.length - i, 4);
+     *          n-- > 0; rnd >>= 8)
+     *       bytes[i++] = (byte)rnd;
+     * }}
+ * + * @param bytes the byte array to fill with random bytes + * @throws NullPointerException if the byte array is null + * @since 1.1 + */ + public void nextBytes(byte[] bytes) { + for (int i = 0, len = bytes.length; i < len; ) + for (int rnd = nextInt(), + n = Math.min(len - i, Integer.SIZE/Byte.SIZE); + n-- > 0; rnd >>= Byte.SIZE) + bytes[i++] = (byte)rnd; + } + + /** + * Returns the next pseudorandom, uniformly distributed {@code int} + * value from this random number generator's sequence. The general + * contract of {@code nextInt} is that one {@code int} value is + * pseudorandomly generated and returned. All 232 + * possible {@code int} values are produced with + * (approximately) equal probability. + * + *

The method {@code nextInt} is implemented by class {@code Random} + * as if by: + *

 {@code
+     * public int nextInt() {
+     *   return next(32);
+     * }}
+ * + * @return the next pseudorandom, uniformly distributed {@code int} + * value from this random number generator's sequence + */ + public int nextInt() { + return next(32); + } + + /** + * Returns a pseudorandom, uniformly distributed {@code int} value + * between 0 (inclusive) and the specified value (exclusive), drawn from + * this random number generator's sequence. The general contract of + * {@code nextInt} is that one {@code int} value in the specified range + * is pseudorandomly generated and returned. All {@code n} possible + * {@code int} values are produced with (approximately) equal + * probability. The method {@code nextInt(int n)} is implemented by + * class {@code Random} as if by: + *
 {@code
+     * public int nextInt(int n) {
+     *   if (n <= 0)
+     *     throw new IllegalArgumentException("n must be positive");
+     *
+     *   if ((n & -n) == n)  // i.e., n is a power of 2
+     *     return (int)((n * (long)next(31)) >> 31);
+     *
+     *   int bits, val;
+     *   do {
+     *       bits = next(31);
+     *       val = bits % n;
+     *   } while (bits - val + (n-1) < 0);
+     *   return val;
+     * }}
+ * + *

The hedge "approximately" is used in the foregoing description only + * because the next method is only approximately an unbiased source of + * independently chosen bits. If it were a perfect source of randomly + * chosen bits, then the algorithm shown would choose {@code int} + * values from the stated range with perfect uniformity. + *

+ * The algorithm is slightly tricky. It rejects values that would result + * in an uneven distribution (due to the fact that 2^31 is not divisible + * by n). The probability of a value being rejected depends on n. The + * worst case is n=2^30+1, for which the probability of a reject is 1/2, + * and the expected number of iterations before the loop terminates is 2. + *

+ * The algorithm treats the case where n is a power of two specially: it + * returns the correct number of high-order bits from the underlying + * pseudo-random number generator. In the absence of special treatment, + * the correct number of low-order bits would be returned. Linear + * congruential pseudo-random number generators such as the one + * implemented by this class are known to have short periods in the + * sequence of values of their low-order bits. Thus, this special case + * greatly increases the length of the sequence of values returned by + * successive calls to this method if n is a small power of two. + * + * @param n the bound on the random number to be returned. Must be + * positive. + * @return the next pseudorandom, uniformly distributed {@code int} + * value between {@code 0} (inclusive) and {@code n} (exclusive) + * from this random number generator's sequence + * @throws IllegalArgumentException if n is not positive + * @since 1.2 + */ + + public int nextInt(int n) { + if (n <= 0) + throw new IllegalArgumentException("n must be positive"); + + if ((n & -n) == n) // i.e., n is a power of 2 + return (int)((n * (long)next(31)) >> 31); + + int bits, val; + do { + bits = next(31); + val = bits % n; + } while (bits - val + (n-1) < 0); + return val; + } + + /** + * Returns the next pseudorandom, uniformly distributed {@code long} + * value from this random number generator's sequence. The general + * contract of {@code nextLong} is that one {@code long} value is + * pseudorandomly generated and returned. + * + *

The method {@code nextLong} is implemented by class {@code Random} + * as if by: + *

 {@code
+     * public long nextLong() {
+     *   return ((long)next(32) << 32) + next(32);
+     * }}
+ * + * Because class {@code Random} uses a seed with only 48 bits, + * this algorithm will not return all possible {@code long} values. + * + * @return the next pseudorandom, uniformly distributed {@code long} + * value from this random number generator's sequence + */ + public long nextLong() { + // it's okay that the bottom word remains signed. + return ((long)(next(32)) << 32) + next(32); + } + + /** + * Returns the next pseudorandom, uniformly distributed + * {@code boolean} value from this random number generator's + * sequence. The general contract of {@code nextBoolean} is that one + * {@code boolean} value is pseudorandomly generated and returned. The + * values {@code true} and {@code false} are produced with + * (approximately) equal probability. + * + *

The method {@code nextBoolean} is implemented by class {@code Random} + * as if by: + *

 {@code
+     * public boolean nextBoolean() {
+     *   return next(1) != 0;
+     * }}
+ * + * @return the next pseudorandom, uniformly distributed + * {@code boolean} value from this random number generator's + * sequence + * @since 1.2 + */ + public boolean nextBoolean() { + return next(1) != 0; + } + + /** + * Returns the next pseudorandom, uniformly distributed {@code float} + * value between {@code 0.0} and {@code 1.0} from this random + * number generator's sequence. + * + *

The general contract of {@code nextFloat} is that one + * {@code float} value, chosen (approximately) uniformly from the + * range {@code 0.0f} (inclusive) to {@code 1.0f} (exclusive), is + * pseudorandomly generated and returned. All 224 possible {@code float} values + * of the form m x 2-24, where m is a positive + * integer less than 224 , are + * produced with (approximately) equal probability. + * + *

The method {@code nextFloat} is implemented by class {@code Random} + * as if by: + *

 {@code
+     * public float nextFloat() {
+     *   return next(24) / ((float)(1 << 24));
+     * }}
+ * + *

The hedge "approximately" is used in the foregoing description only + * because the next method is only approximately an unbiased source of + * independently chosen bits. If it were a perfect source of randomly + * chosen bits, then the algorithm shown would choose {@code float} + * values from the stated range with perfect uniformity.

+ * [In early versions of Java, the result was incorrectly calculated as: + *

 {@code
+     *   return next(30) / ((float)(1 << 30));}
+ * This might seem to be equivalent, if not better, but in fact it + * introduced a slight nonuniformity because of the bias in the rounding + * of floating-point numbers: it was slightly more likely that the + * low-order bit of the significand would be 0 than that it would be 1.] + * + * @return the next pseudorandom, uniformly distributed {@code float} + * value between {@code 0.0} and {@code 1.0} from this + * random number generator's sequence + */ + public float nextFloat() { + return next(24) / ((float)(1 << 24)); + } + + /** + * Returns the next pseudorandom, uniformly distributed + * {@code double} value between {@code 0.0} and + * {@code 1.0} from this random number generator's sequence. + * + *

The general contract of {@code nextDouble} is that one + * {@code double} value, chosen (approximately) uniformly from the + * range {@code 0.0d} (inclusive) to {@code 1.0d} (exclusive), is + * pseudorandomly generated and returned. + * + *

The method {@code nextDouble} is implemented by class {@code Random} + * as if by: + *

 {@code
+     * public double nextDouble() {
+     *   return (((long)next(26) << 27) + next(27))
+     *     / (double)(1L << 53);
+     * }}
+ * + *

The hedge "approximately" is used in the foregoing description only + * because the {@code next} method is only approximately an unbiased + * source of independently chosen bits. If it were a perfect source of + * randomly chosen bits, then the algorithm shown would choose + * {@code double} values from the stated range with perfect uniformity. + *

[In early versions of Java, the result was incorrectly calculated as: + *

 {@code
+     *   return (((long)next(27) << 27) + next(27))
+     *     / (double)(1L << 54);}
+ * This might seem to be equivalent, if not better, but in fact it + * introduced a large nonuniformity because of the bias in the rounding + * of floating-point numbers: it was three times as likely that the + * low-order bit of the significand would be 0 than that it would be 1! + * This nonuniformity probably doesn't matter much in practice, but we + * strive for perfection.] + * + * @return the next pseudorandom, uniformly distributed {@code double} + * value between {@code 0.0} and {@code 1.0} from this + * random number generator's sequence + * @see Math#random + */ + public double nextDouble() { + return (((long)(next(26)) << 27) + next(27)) + / (double)(1L << 53); + } + + private double nextNextGaussian; + private boolean haveNextNextGaussian = false; + + /** + * Returns the next pseudorandom, Gaussian ("normally") distributed + * {@code double} value with mean {@code 0.0} and standard + * deviation {@code 1.0} from this random number generator's sequence. + *

+ * The general contract of {@code nextGaussian} is that one + * {@code double} value, chosen from (approximately) the usual + * normal distribution with mean {@code 0.0} and standard deviation + * {@code 1.0}, is pseudorandomly generated and returned. + * + *

The method {@code nextGaussian} is implemented by class + * {@code Random} as if by a threadsafe version of the following: + *

 {@code
+     * private double nextNextGaussian;
+     * private boolean haveNextNextGaussian = false;
+     *
+     * public double nextGaussian() {
+     *   if (haveNextNextGaussian) {
+     *     haveNextNextGaussian = false;
+     *     return nextNextGaussian;
+     *   } else {
+     *     double v1, v2, s;
+     *     do {
+     *       v1 = 2 * nextDouble() - 1;   // between -1.0 and 1.0
+     *       v2 = 2 * nextDouble() - 1;   // between -1.0 and 1.0
+     *       s = v1 * v1 + v2 * v2;
+     *     } while (s >= 1 || s == 0);
+     *     double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
+     *     nextNextGaussian = v2 * multiplier;
+     *     haveNextNextGaussian = true;
+     *     return v1 * multiplier;
+     *   }
+     * }}
+ * This uses the polar method of G. E. P. Box, M. E. Muller, and + * G. Marsaglia, as described by Donald E. Knuth in The Art of + * Computer Programming, Volume 3: Seminumerical Algorithms, + * section 3.4.1, subsection C, algorithm P. Note that it generates two + * independent values at the cost of only one call to {@code StrictMath.log} + * and one call to {@code StrictMath.sqrt}. + * + * @return the next pseudorandom, Gaussian ("normally") distributed + * {@code double} value with mean {@code 0.0} and + * standard deviation {@code 1.0} from this random number + * generator's sequence + */ + synchronized public double nextGaussian() { + // See Knuth, ACP, Section 3.4.1 Algorithm C. + if (haveNextNextGaussian) { + haveNextNextGaussian = false; + return nextNextGaussian; + } else { + double v1, v2, s; + do { + v1 = 2 * nextDouble() - 1; // between -1 and 1 + v2 = 2 * nextDouble() - 1; // between -1 and 1 + s = v1 * v1 + v2 * v2; + } while (s >= 1 || s == 0); + double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s); + nextNextGaussian = v2 * multiplier; + haveNextNextGaussian = true; + return v1 * multiplier; + } + } + + /** + * Serializable fields for Random. + * + * @serialField seed long + * seed for random computations + * @serialField nextNextGaussian double + * next Gaussian to be returned + * @serialField haveNextNextGaussian boolean + * nextNextGaussian is valid + */ + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("seed", Long.TYPE), + new ObjectStreamField("nextNextGaussian", Double.TYPE), + new ObjectStreamField("haveNextNextGaussian", Boolean.TYPE) + }; + + /** + * Reconstitute the {@code Random} instance from a stream (that is, + * deserialize it). + */ + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + + ObjectInputStream.GetField fields = s.readFields(); + + // The seed is read in as {@code long} for + // historical reasons, but it is converted to an AtomicLong. + long seedVal = fields.get("seed", -1L); + if (seedVal < 0) + throw new java.io.StreamCorruptedException( + "Random: invalid seed"); + resetSeed(seedVal); + nextNextGaussian = fields.get("nextNextGaussian", 0.0); + haveNextNextGaussian = fields.get("haveNextNextGaussian", false); + } + + /** + * Save the {@code Random} instance to a stream. + */ + synchronized private void writeObject(ObjectOutputStream s) + throws IOException { + + // set the values of the Serializable fields + ObjectOutputStream.PutField fields = s.putFields(); + + // The seed is serialized as a long for historical reasons. + fields.put("seed", seed.get()); + fields.put("nextNextGaussian", nextNextGaussian); + fields.put("haveNextNextGaussian", haveNextNextGaussian); + + // save them + s.writeFields(); + } + + // Support for resetting seed while deserializing + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final long seedOffset; + static { + try { + seedOffset = unsafe.objectFieldOffset + (Random.class.getDeclaredField("seed")); + } catch (Exception ex) { throw new Error(ex); } + } + private void resetSeed(long seedVal) { + unsafe.putObjectVolatile(this, seedOffset, new AtomicLong(seedVal)); + } +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/SortedMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/SortedMap.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,284 @@ +/* + * Copyright (c) 1998, 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; + +/** + * A {@link Map} that further provides a total ordering 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}.) + * + *

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 mutually comparable: {@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}. + * + *

Note that the ordering maintained by a sorted map (whether or not an + * explicit comparator is provided) must be consistent with equals 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 consistent with equals.) 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 is well-defined even if its + * ordering is inconsistent with equals; it just fails to obey the general + * contract of the {@code Map} interface. + * + *

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: + *

    + *
  1. A void (no arguments) constructor, which creates an empty sorted map + * sorted according to the natural ordering of its keys.
  2. + *
  3. A constructor with a single argument of type {@code Comparator}, which + * creates an empty sorted map sorted according to the specified comparator.
  4. + *
  5. 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.
  6. + *
  7. 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.
  8. + *
+ * + *

Note: several methods return submaps with restricted key + * ranges. Such ranges are half-open, that is, they include their low + * endpoint but not their high endpoint (where applicable). If you need a + * closed range (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:

+ *   SortedMap<String, V> sub = m.subMap(low, high+"\0");
+ * + * A similar technique can be used to generate an open range + * (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:
+ *   SortedMap<String, V> sub = m.subMap(low+"\0", high);
+ * + *

This interface is a member of the + * + * Java Collections Framework. + * + * @param the type of keys maintained by this map + * @param 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 extends Map { + /** + * 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 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. + * + *

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 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. + * + *

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 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. + * + *

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 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 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 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> entrySet(); +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/SortedSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/SortedSet.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,222 @@ +/* + * Copyright (c) 1998, 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; + +/** + * A {@link Set} that further provides a total ordering 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}.) + * + *

All elements inserted into a sorted set must implement the Comparable + * interface (or be accepted by the specified comparator). Furthermore, all + * such elements must be mutually comparable: e1.compareTo(e2) + * (or comparator.compare(e1, e2)) must not throw a + * ClassCastException for any elements e1 and e2 in + * the sorted set. Attempts to violate this restriction will cause the + * offending method or constructor invocation to throw a + * ClassCastException. + * + *

Note that the ordering maintained by a sorted set (whether or not an + * explicit comparator is provided) must be consistent with equals if + * the sorted set is to correctly implement the Set interface. (See + * the Comparable interface or Comparator interface for a + * precise definition of consistent with equals.) This is so because + * the Set interface is defined in terms of the equals + * operation, but a sorted set performs all element comparisons using its + * compareTo (or compare) method, so two elements that are + * deemed equal by this method are, from the standpoint of the sorted set, + * equal. The behavior of a sorted set is well-defined even if its + * ordering is inconsistent with equals; it just fails to obey the general + * contract of the Set interface. + * + *

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 Comparator, which creates an empty + * sorted set sorted according to the specified comparator. 3) A + * constructor with a single argument of type Collection, + * which creates a new sorted set with the same elements as its + * argument, sorted according to the natural ordering of the elements. + * 4) A constructor with a single argument of type SortedSet, + * which creates a new sorted set with the same elements and the same + * ordering as the input sorted set. There is no way to enforce this + * recommendation, as interfaces cannot contain constructors. + * + *

Note: several methods return subsets with restricted ranges. + * Such ranges are half-open, that is, they include their low + * endpoint but not their high endpoint (where applicable). + * If you need a closed range (which includes both endpoints), and + * the element type allows for calculation of the successor of a given + * value, merely request the subrange from lowEndpoint to + * successor(highEndpoint). For example, suppose that s + * is a sorted set of strings. The following idiom obtains a view + * containing all of the strings in s from low to + * high, inclusive:

+ *   SortedSet<String> sub = s.subSet(low, high+"\0");
+ * + * A similar technique can be used to generate an open range (which + * contains neither endpoint). The following idiom obtains a view + * containing all of the Strings in s from low to + * high, exclusive:
+ *   SortedSet<String> sub = s.subSet(low+"\0", high);
+ * + *

This interface is a member of the + * + * Java Collections Framework. + * + * @param 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 extends Set { + /** + * Returns the comparator used to order the elements in this set, + * or null if this set uses the {@linkplain Comparable + * natural ordering} of its elements. + * + * @return the comparator used to order the elements in this set, + * or null if this set uses the natural ordering + * of its elements + */ + Comparator comparator(); + + /** + * Returns a view of the portion of this set whose elements range + * from fromElement, inclusive, to toElement, + * exclusive. (If fromElement and toElement are + * equal, the returned set is empty.) The returned set is backed + * by this set, so changes in the returned set are reflected in + * this set, and vice-versa. The returned set supports all + * optional set operations that this set supports. + * + *

The returned set will throw an IllegalArgumentException + * on an attempt to insert an element outside its range. + * + * @param fromElement low endpoint (inclusive) of the returned set + * @param toElement high endpoint (exclusive) of the returned set + * @return a view of the portion of this set whose elements range from + * fromElement, inclusive, to toElement, exclusive + * @throws ClassCastException if fromElement and + * 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 fromElement or + * toElement cannot be compared to elements currently in + * the set. + * @throws NullPointerException if fromElement or + * toElement is null and this set does not permit null + * elements + * @throws IllegalArgumentException if fromElement is + * greater than toElement; or if this set itself + * has a restricted range, and fromElement or + * toElement lies outside the bounds of the range + */ + SortedSet subSet(E fromElement, E toElement); + + /** + * Returns a view of the portion of this set whose elements are + * strictly less than 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. + * + *

The returned set will throw an IllegalArgumentException + * on an attempt to insert an element outside its range. + * + * @param toElement high endpoint (exclusive) of the returned set + * @return a view of the portion of this set whose elements are strictly + * less than toElement + * @throws ClassCastException if toElement is not compatible + * with this set's comparator (or, if the set has no comparator, + * if toElement does not implement {@link Comparable}). + * Implementations may, but are not required to, throw this + * exception if toElement cannot be compared to elements + * currently in the set. + * @throws NullPointerException if toElement is null and + * this set does not permit null elements + * @throws IllegalArgumentException if this set itself has a + * restricted range, and toElement lies outside the + * bounds of the range + */ + SortedSet headSet(E toElement); + + /** + * Returns a view of the portion of this set whose elements are + * greater than or equal to 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. + * + *

The returned set will throw an IllegalArgumentException + * on an attempt to insert an element outside its range. + * + * @param fromElement low endpoint (inclusive) of the returned set + * @return a view of the portion of this set whose elements are greater + * than or equal to fromElement + * @throws ClassCastException if fromElement is not compatible + * with this set's comparator (or, if the set has no comparator, + * if fromElement does not implement {@link Comparable}). + * Implementations may, but are not required to, throw this + * exception if fromElement cannot be compared to elements + * currently in the set. + * @throws NullPointerException if fromElement is null + * and this set does not permit null elements + * @throws IllegalArgumentException if this set itself has a + * restricted range, and fromElement lies outside the + * bounds of the range + */ + SortedSet 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(); +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/Stack.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/Stack.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1994, 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; + +/** + * The Stack class represents a last-in-first-out + * (LIFO) stack of objects. It extends class Vector with five + * operations that allow a vector to be treated as a stack. The usual + * push and pop operations are provided, as well as a + * method to peek at the top item on the stack, a method to test + * for whether the stack is empty, and a method to search + * the stack for an item and discover how far it is from the top. + *

+ * When a stack is first created, it contains no items. + * + *

A more complete and consistent set of LIFO stack operations is + * provided by the {@link Deque} interface and its implementations, which + * should be used in preference to this class. For example: + *

   {@code
+ *   Deque stack = new ArrayDeque();}
+ * + * @author Jonathan Payne + * @since JDK1.0 + */ +public +class Stack extends Vector { + /** + * Creates an empty Stack. + */ + public Stack() { + } + + /** + * Pushes an item onto the top of this stack. This has exactly + * the same effect as: + *
+     * addElement(item)
+ * + * @param item the item to be pushed onto this stack. + * @return the item argument. + * @see java.util.Vector#addElement + */ + public E push(E item) { + addElement(item); + + return item; + } + + /** + * Removes the object at the top of this stack and returns that + * object as the value of this function. + * + * @return The object at the top of this stack (the last item + * of the Vector object). + * @throws EmptyStackException if this stack is empty. + */ + public synchronized E pop() { + E obj; + int len = size(); + + obj = peek(); + removeElementAt(len - 1); + + return obj; + } + + /** + * Looks at the object at the top of this stack without removing it + * from the stack. + * + * @return the object at the top of this stack (the last item + * of the Vector object). + * @throws EmptyStackException if this stack is empty. + */ + public synchronized E peek() { + int len = size(); + + if (len == 0) + throw new EmptyStackException(); + return elementAt(len - 1); + } + + /** + * Tests if this stack is empty. + * + * @return true if and only if this stack contains + * no items; false otherwise. + */ + public boolean empty() { + return size() == 0; + } + + /** + * Returns the 1-based position where an object is on this stack. + * If the object o occurs as an item in this stack, this + * method returns the distance from the top of the stack of the + * occurrence nearest the top of the stack; the topmost item on the + * stack is considered to be at distance 1. The equals + * method is used to compare o to the + * items in this stack. + * + * @param o the desired object. + * @return the 1-based position from the top of the stack where + * the object is located; the return value -1 + * indicates that the object is not on the stack. + */ + public synchronized int search(Object o) { + int i = lastIndexOf(o); + + if (i >= 0) { + return size() - i; + } + return -1; + } + + /** use serialVersionUID from JDK 1.0.2 for interoperability */ + private static final long serialVersionUID = 1224463164541339165L; +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/StringTokenizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/StringTokenizer.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,431 @@ +/* + * Copyright (c) 1994, 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; + +import java.lang.*; + +/** + * The string tokenizer class allows an application to break a + * string into tokens. The tokenization method is much simpler than + * the one used by the StreamTokenizer class. The + * StringTokenizer methods do not distinguish among + * identifiers, numbers, and quoted strings, nor do they recognize + * and skip comments. + *

+ * The set of delimiters (the characters that separate tokens) may + * be specified either at creation time or on a per-token basis. + *

+ * An instance of StringTokenizer behaves in one of two + * ways, depending on whether it was created with the + * returnDelims flag having the value true + * or false: + *

    + *
  • If the flag is false, delimiter characters serve to + * separate tokens. A token is a maximal sequence of consecutive + * characters that are not delimiters. + *
  • If the flag is true, delimiter characters are themselves + * considered to be tokens. A token is thus either one delimiter + * character, or a maximal sequence of consecutive characters that are + * not delimiters. + *

+ * A StringTokenizer object internally maintains a current + * position within the string to be tokenized. Some operations advance this + * current position past the characters processed.

+ * A token is returned by taking a substring of the string that was used to + * create the StringTokenizer object. + *

+ * The following is one example of the use of the tokenizer. The code: + *

+ *     StringTokenizer st = new StringTokenizer("this is a test");
+ *     while (st.hasMoreTokens()) {
+ *         System.out.println(st.nextToken());
+ *     }
+ * 
+ *

+ * prints the following output: + *

+ *     this
+ *     is
+ *     a
+ *     test
+ * 
+ * + *

+ * StringTokenizer is a legacy class that is retained for + * compatibility reasons although its use is discouraged in new code. It is + * recommended that anyone seeking this functionality use the split + * method of String or the java.util.regex package instead. + *

+ * The following example illustrates how the String.split + * method can be used to break up a string into its basic tokens: + *

+ *     String[] result = "this is a test".split("\\s");
+ *     for (int x=0; x<result.length; x++)
+ *         System.out.println(result[x]);
+ * 
+ *

+ * prints the following output: + *

+ *     this
+ *     is
+ *     a
+ *     test
+ * 
+ * + * @author unascribed + * @see java.io.StreamTokenizer + * @since JDK1.0 + */ +public +class StringTokenizer implements Enumeration { + private int currentPosition; + private int newPosition; + private int maxPosition; + private String str; + private String delimiters; + private boolean retDelims; + private boolean delimsChanged; + + /** + * maxDelimCodePoint stores the value of the delimiter character with the + * highest value. It is used to optimize the detection of delimiter + * characters. + * + * It is unlikely to provide any optimization benefit in the + * hasSurrogates case because most string characters will be + * smaller than the limit, but we keep it so that the two code + * paths remain similar. + */ + private int maxDelimCodePoint; + + /** + * If delimiters include any surrogates (including surrogate + * pairs), hasSurrogates is true and the tokenizer uses the + * different code path. This is because String.indexOf(int) + * doesn't handle unpaired surrogates as a single character. + */ + private boolean hasSurrogates = false; + + /** + * When hasSurrogates is true, delimiters are converted to code + * points and isDelimiter(int) is used to determine if the given + * codepoint is a delimiter. + */ + private int[] delimiterCodePoints; + + /** + * Set maxDelimCodePoint to the highest char in the delimiter set. + */ + private void setMaxDelimCodePoint() { + if (delimiters == null) { + maxDelimCodePoint = 0; + return; + } + + int m = 0; + int c; + int count = 0; + for (int i = 0; i < delimiters.length(); i += Character.charCount(c)) { + c = delimiters.charAt(i); + if (c >= Character.MIN_HIGH_SURROGATE && c <= Character.MAX_LOW_SURROGATE) { + c = delimiters.codePointAt(i); + hasSurrogates = true; + } + if (m < c) + m = c; + count++; + } + maxDelimCodePoint = m; + + if (hasSurrogates) { + delimiterCodePoints = new int[count]; + for (int i = 0, j = 0; i < count; i++, j += Character.charCount(c)) { + c = delimiters.codePointAt(j); + delimiterCodePoints[i] = c; + } + } + } + + /** + * Constructs a string tokenizer for the specified string. All + * characters in the delim argument are the delimiters + * for separating tokens. + *

+ * If the returnDelims flag is true, then + * the delimiter characters are also returned as tokens. Each + * delimiter is returned as a string of length one. If the flag is + * false, the delimiter characters are skipped and only + * serve as separators between tokens. + *

+ * Note that if delim is null, this constructor does + * not throw an exception. However, trying to invoke other methods on the + * resulting StringTokenizer may result in a + * NullPointerException. + * + * @param str a string to be parsed. + * @param delim the delimiters. + * @param returnDelims flag indicating whether to return the delimiters + * as tokens. + * @exception NullPointerException if str is null + */ + public StringTokenizer(String str, String delim, boolean returnDelims) { + currentPosition = 0; + newPosition = -1; + delimsChanged = false; + this.str = str; + maxPosition = str.length(); + delimiters = delim; + retDelims = returnDelims; + setMaxDelimCodePoint(); + } + + /** + * Constructs a string tokenizer for the specified string. The + * characters in the delim argument are the delimiters + * for separating tokens. Delimiter characters themselves will not + * be treated as tokens. + *

+ * Note that if delim is null, this constructor does + * not throw an exception. However, trying to invoke other methods on the + * resulting StringTokenizer may result in a + * NullPointerException. + * + * @param str a string to be parsed. + * @param delim the delimiters. + * @exception NullPointerException if str is null + */ + public StringTokenizer(String str, String delim) { + this(str, delim, false); + } + + /** + * Constructs a string tokenizer for the specified string. The + * tokenizer uses the default delimiter set, which is + * " \t\n\r\f": the space character, + * the tab character, the newline character, the carriage-return character, + * and the form-feed character. Delimiter characters themselves will + * not be treated as tokens. + * + * @param str a string to be parsed. + * @exception NullPointerException if str is null + */ + public StringTokenizer(String str) { + this(str, " \t\n\r\f", false); + } + + /** + * Skips delimiters starting from the specified position. If retDelims + * is false, returns the index of the first non-delimiter character at or + * after startPos. If retDelims is true, startPos is returned. + */ + private int skipDelimiters(int startPos) { + if (delimiters == null) + throw new NullPointerException(); + + int position = startPos; + while (!retDelims && position < maxPosition) { + if (!hasSurrogates) { + char c = str.charAt(position); + if ((c > maxDelimCodePoint) || (delimiters.indexOf(c) < 0)) + break; + position++; + } else { + int c = str.codePointAt(position); + if ((c > maxDelimCodePoint) || !isDelimiter(c)) { + break; + } + position += Character.charCount(c); + } + } + return position; + } + + /** + * Skips ahead from startPos and returns the index of the next delimiter + * character encountered, or maxPosition if no such delimiter is found. + */ + private int scanToken(int startPos) { + int position = startPos; + while (position < maxPosition) { + if (!hasSurrogates) { + char c = str.charAt(position); + if ((c <= maxDelimCodePoint) && (delimiters.indexOf(c) >= 0)) + break; + position++; + } else { + int c = str.codePointAt(position); + if ((c <= maxDelimCodePoint) && isDelimiter(c)) + break; + position += Character.charCount(c); + } + } + if (retDelims && (startPos == position)) { + if (!hasSurrogates) { + char c = str.charAt(position); + if ((c <= maxDelimCodePoint) && (delimiters.indexOf(c) >= 0)) + position++; + } else { + int c = str.codePointAt(position); + if ((c <= maxDelimCodePoint) && isDelimiter(c)) + position += Character.charCount(c); + } + } + return position; + } + + private boolean isDelimiter(int codePoint) { + for (int i = 0; i < delimiterCodePoints.length; i++) { + if (delimiterCodePoints[i] == codePoint) { + return true; + } + } + return false; + } + + /** + * Tests if there are more tokens available from this tokenizer's string. + * If this method returns true, then a subsequent call to + * nextToken with no argument will successfully return a token. + * + * @return true if and only if there is at least one token + * in the string after the current position; false + * otherwise. + */ + public boolean hasMoreTokens() { + /* + * Temporarily store this position and use it in the following + * nextToken() method only if the delimiters haven't been changed in + * that nextToken() invocation. + */ + newPosition = skipDelimiters(currentPosition); + return (newPosition < maxPosition); + } + + /** + * Returns the next token from this string tokenizer. + * + * @return the next token from this string tokenizer. + * @exception NoSuchElementException if there are no more tokens in this + * tokenizer's string. + */ + public String nextToken() { + /* + * If next position already computed in hasMoreElements() and + * delimiters have changed between the computation and this invocation, + * then use the computed value. + */ + + currentPosition = (newPosition >= 0 && !delimsChanged) ? + newPosition : skipDelimiters(currentPosition); + + /* Reset these anyway */ + delimsChanged = false; + newPosition = -1; + + if (currentPosition >= maxPosition) + throw new NoSuchElementException(); + int start = currentPosition; + currentPosition = scanToken(currentPosition); + return str.substring(start, currentPosition); + } + + /** + * Returns the next token in this string tokenizer's string. First, + * the set of characters considered to be delimiters by this + * StringTokenizer object is changed to be the characters in + * the string delim. Then the next token in the string + * after the current position is returned. The current position is + * advanced beyond the recognized token. The new delimiter set + * remains the default after this call. + * + * @param delim the new delimiters. + * @return the next token, after switching to the new delimiter set. + * @exception NoSuchElementException if there are no more tokens in this + * tokenizer's string. + * @exception NullPointerException if delim is null + */ + public String nextToken(String delim) { + delimiters = delim; + + /* delimiter string specified, so set the appropriate flag. */ + delimsChanged = true; + + setMaxDelimCodePoint(); + return nextToken(); + } + + /** + * Returns the same value as the hasMoreTokens + * method. It exists so that this class can implement the + * Enumeration interface. + * + * @return true if there are more tokens; + * false otherwise. + * @see java.util.Enumeration + * @see java.util.StringTokenizer#hasMoreTokens() + */ + public boolean hasMoreElements() { + return hasMoreTokens(); + } + + /** + * Returns the same value as the nextToken method, + * except that its declared return value is Object rather than + * String. It exists so that this class can implement the + * Enumeration interface. + * + * @return the next token in the string. + * @exception NoSuchElementException if there are no more tokens in this + * tokenizer's string. + * @see java.util.Enumeration + * @see java.util.StringTokenizer#nextToken() + */ + public Object nextElement() { + return nextToken(); + } + + /** + * Calculates the number of times that this tokenizer's + * nextToken method can be called before it generates an + * exception. The current position is not advanced. + * + * @return the number of tokens remaining in the string using the current + * delimiter set. + * @see java.util.StringTokenizer#nextToken() + */ + public int countTokens() { + int count = 0; + int currpos = currentPosition; + while (currpos < maxPosition) { + currpos = skipDelimiters(currpos); + if (currpos >= maxPosition) + break; + currpos = scanToken(currpos); + count++; + } + return count; + } +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/compact/src/main/java/java/util/Vector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/Vector.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,1212 @@ +/* + * Copyright (c) 1994, 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; + +/** + * The {@code Vector} class implements a growable array of + * objects. Like an array, it contains components that can be + * accessed using an integer index. However, the size of a + * {@code Vector} can grow or shrink as needed to accommodate + * adding and removing items after the {@code Vector} has been created. + * + *

Each vector tries to optimize storage management by maintaining a + * {@code capacity} and a {@code capacityIncrement}. The + * {@code capacity} is always at least as large as the vector + * size; it is usually larger because as components are added to the + * vector, the vector's storage increases in chunks the size of + * {@code capacityIncrement}. An application can increase the + * capacity of a vector before inserting a large number of + * components; this reduces the amount of incremental reallocation. + * + *

+ * The iterators returned by this class's {@link #iterator() iterator} and + * {@link #listIterator(int) listIterator} methods are fail-fast: + * if the vector is structurally modified at any time after the iterator is + * created, in any way except through the iterator's own + * {@link ListIterator#remove() remove} or + * {@link ListIterator#add(Object) add} methods, 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. The {@link Enumeration Enumerations} returned by + * the {@link #elements() elements} method are not fail-fast. + * + *

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: the fail-fast behavior of iterators + * should be used only to detect bugs. + * + *

As of the Java 2 platform v1.2, this class was retrofitted to + * implement the {@link List} interface, making it a member of the + * + * Java Collections Framework. Unlike the new collection + * implementations, {@code Vector} is synchronized. If a thread-safe + * implementation is not needed, it is recommended to use {@link + * ArrayList} in place of {@code Vector}. + * + * @author Lee Boynton + * @author Jonathan Payne + * @see Collection + * @see LinkedList + * @since JDK1.0 + */ +public class Vector + extends AbstractList + implements List, RandomAccess, Cloneable, java.io.Serializable +{ + /** + * The array buffer into which the components of the vector are + * stored. The capacity of the vector is the length of this array buffer, + * and is at least large enough to contain all the vector's elements. + * + *

Any array elements following the last element in the Vector are null. + * + * @serial + */ + protected Object[] elementData; + + /** + * The number of valid components in this {@code Vector} object. + * Components {@code elementData[0]} through + * {@code elementData[elementCount-1]} are the actual items. + * + * @serial + */ + protected int elementCount; + + /** + * The amount by which the capacity of the vector is automatically + * incremented when its size becomes greater than its capacity. If + * the capacity increment is less than or equal to zero, the capacity + * of the vector is doubled each time it needs to grow. + * + * @serial + */ + protected int capacityIncrement; + + /** use serialVersionUID from JDK 1.0.2 for interoperability */ + private static final long serialVersionUID = -2767605614048989439L; + + /** + * Constructs an empty vector with the specified initial capacity and + * capacity increment. + * + * @param initialCapacity the initial capacity of the vector + * @param capacityIncrement the amount by which the capacity is + * increased when the vector overflows + * @throws IllegalArgumentException if the specified initial capacity + * is negative + */ + public Vector(int initialCapacity, int capacityIncrement) { + super(); + if (initialCapacity < 0) + throw new IllegalArgumentException("Illegal Capacity: "+ + initialCapacity); + this.elementData = new Object[initialCapacity]; + this.capacityIncrement = capacityIncrement; + } + + /** + * Constructs an empty vector with the specified initial capacity and + * with its capacity increment equal to zero. + * + * @param initialCapacity the initial capacity of the vector + * @throws IllegalArgumentException if the specified initial capacity + * is negative + */ + public Vector(int initialCapacity) { + this(initialCapacity, 0); + } + + /** + * Constructs an empty vector so that its internal data array + * has size {@code 10} and its standard capacity increment is + * zero. + */ + public Vector() { + this(10); + } + + /** + * Constructs a vector containing the elements of the specified + * collection, in the order they are returned by the collection's + * iterator. + * + * @param c the collection whose elements are to be placed into this + * vector + * @throws NullPointerException if the specified collection is null + * @since 1.2 + */ + public Vector(Collection c) { + elementData = c.toArray(); + elementCount = elementData.length; + // c.toArray might (incorrectly) not return Object[] (see 6260652) + if (elementData.getClass() != Object[].class) + elementData = Arrays.copyOf(elementData, elementCount, Object[].class); + } + + /** + * Copies the components of this vector into the specified array. + * The item at index {@code k} in this vector is copied into + * component {@code k} of {@code anArray}. + * + * @param anArray the array into which the components get copied + * @throws NullPointerException if the given array is null + * @throws IndexOutOfBoundsException if the specified array is not + * large enough to hold all the components of this vector + * @throws ArrayStoreException if a component of this vector is not of + * a runtime type that can be stored in the specified array + * @see #toArray(Object[]) + */ + public synchronized void copyInto(Object[] anArray) { + System.arraycopy(elementData, 0, anArray, 0, elementCount); + } + + /** + * Trims the capacity of this vector to be the vector's current + * size. If the capacity of this vector is larger than its current + * size, then the capacity is changed to equal the size by replacing + * its internal data array, kept in the field {@code elementData}, + * with a smaller one. An application can use this operation to + * minimize the storage of a vector. + */ + public synchronized void trimToSize() { + modCount++; + int oldCapacity = elementData.length; + if (elementCount < oldCapacity) { + elementData = Arrays.copyOf(elementData, elementCount); + } + } + + /** + * Increases the capacity of this vector, if necessary, to ensure + * that it can hold at least the number of components specified by + * the minimum capacity argument. + * + *

If the current capacity of this vector is less than + * {@code minCapacity}, then its capacity is increased by replacing its + * internal data array, kept in the field {@code elementData}, with a + * larger one. The size of the new data array will be the old size plus + * {@code capacityIncrement}, unless the value of + * {@code capacityIncrement} is less than or equal to zero, in which case + * the new capacity will be twice the old capacity; but if this new size + * is still smaller than {@code minCapacity}, then the new capacity will + * be {@code minCapacity}. + * + * @param minCapacity the desired minimum capacity + */ + public synchronized void ensureCapacity(int minCapacity) { + if (minCapacity > 0) { + modCount++; + ensureCapacityHelper(minCapacity); + } + } + + /** + * This implements the unsynchronized semantics of ensureCapacity. + * Synchronized methods in this class can internally call this + * method for ensuring capacity without incurring the cost of an + * extra synchronization. + * + * @see #ensureCapacity(int) + */ + private void ensureCapacityHelper(int minCapacity) { + // overflow-conscious code + if (minCapacity - elementData.length > 0) + grow(minCapacity); + } + + /** + * 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; + + private void grow(int minCapacity) { + // overflow-conscious code + int oldCapacity = elementData.length; + int newCapacity = oldCapacity + ((capacityIncrement > 0) ? + capacityIncrement : oldCapacity); + if (newCapacity - minCapacity < 0) + newCapacity = minCapacity; + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); + elementData = Arrays.copyOf(elementData, 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; + } + + /** + * Sets the size of this vector. If the new size is greater than the + * current size, new {@code null} items are added to the end of + * the vector. If the new size is less than the current size, all + * components at index {@code newSize} and greater are discarded. + * + * @param newSize the new size of this vector + * @throws ArrayIndexOutOfBoundsException if the new size is negative + */ + public synchronized void setSize(int newSize) { + modCount++; + if (newSize > elementCount) { + ensureCapacityHelper(newSize); + } else { + for (int i = newSize ; i < elementCount ; i++) { + elementData[i] = null; + } + } + elementCount = newSize; + } + + /** + * Returns the current capacity of this vector. + * + * @return the current capacity (the length of its internal + * data array, kept in the field {@code elementData} + * of this vector) + */ + public synchronized int capacity() { + return elementData.length; + } + + /** + * Returns the number of components in this vector. + * + * @return the number of components in this vector + */ + public synchronized int size() { + return elementCount; + } + + /** + * Tests if this vector has no components. + * + * @return {@code true} if and only if this vector has + * no components, that is, its size is zero; + * {@code false} otherwise. + */ + public synchronized boolean isEmpty() { + return elementCount == 0; + } + + /** + * Returns an enumeration of the components of this vector. The + * returned {@code Enumeration} object will generate all items in + * this vector. The first item generated is the item at index {@code 0}, + * then the item at index {@code 1}, and so on. + * + * @return an enumeration of the components of this vector + * @see Iterator + */ + public Enumeration elements() { + return new Enumeration() { + int count = 0; + + public boolean hasMoreElements() { + return count < elementCount; + } + + public E nextElement() { + synchronized (Vector.this) { + if (count < elementCount) { + return elementData(count++); + } + } + throw new NoSuchElementException("Vector Enumeration"); + } + }; + } + + /** + * Returns {@code true} if this vector contains the specified element. + * More formally, returns {@code true} if and only if this vector + * contains at least one element {@code e} such that + * (o==null ? e==null : o.equals(e)). + * + * @param o element whose presence in this vector is to be tested + * @return {@code true} if this vector contains the specified element + */ + public boolean contains(Object o) { + return indexOf(o, 0) >= 0; + } + + /** + * Returns the index of the first occurrence of the specified element + * in this vector, or -1 if this vector does not contain the element. + * More formally, returns the lowest index {@code i} such that + * (o==null ? get(i)==null : o.equals(get(i))), + * 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 vector, or -1 if this vector does not contain the element + */ + public int indexOf(Object o) { + return indexOf(o, 0); + } + + /** + * Returns the index of the first occurrence of the specified element in + * this vector, searching forwards from {@code index}, or returns -1 if + * the element is not found. + * More formally, returns the lowest index {@code i} such that + * (i >= index && (o==null ? get(i)==null : o.equals(get(i)))), + * or -1 if there is no such index. + * + * @param o element to search for + * @param index index to start searching from + * @return the index of the first occurrence of the element in + * this vector at position {@code index} or later in the vector; + * {@code -1} if the element is not found. + * @throws IndexOutOfBoundsException if the specified index is negative + * @see Object#equals(Object) + */ + public synchronized int indexOf(Object o, int index) { + if (o == null) { + for (int i = index ; i < elementCount ; i++) + if (elementData[i]==null) + return i; + } else { + for (int i = index ; i < elementCount ; i++) + if (o.equals(elementData[i])) + return i; + } + return -1; + } + + /** + * Returns the index of the last occurrence of the specified element + * in this vector, or -1 if this vector does not contain the element. + * More formally, returns the highest index {@code i} such that + * (o==null ? get(i)==null : o.equals(get(i))), + * 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 vector, or -1 if this vector does not contain the element + */ + public synchronized int lastIndexOf(Object o) { + return lastIndexOf(o, elementCount-1); + } + + /** + * Returns the index of the last occurrence of the specified element in + * this vector, searching backwards from {@code index}, or returns -1 if + * the element is not found. + * More formally, returns the highest index {@code i} such that + * (i <= index && (o==null ? get(i)==null : o.equals(get(i)))), + * or -1 if there is no such index. + * + * @param o element to search for + * @param index index to start searching backwards from + * @return the index of the last occurrence of the element at position + * less than or equal to {@code index} in this vector; + * -1 if the element is not found. + * @throws IndexOutOfBoundsException if the specified index is greater + * than or equal to the current size of this vector + */ + public synchronized int lastIndexOf(Object o, int index) { + if (index >= elementCount) + throw new IndexOutOfBoundsException(index + " >= "+ elementCount); + + if (o == null) { + for (int i = index; i >= 0; i--) + if (elementData[i]==null) + return i; + } else { + for (int i = index; i >= 0; i--) + if (o.equals(elementData[i])) + return i; + } + return -1; + } + + /** + * Returns the component at the specified index. + * + *

This method is identical in functionality to the {@link #get(int)} + * method (which is part of the {@link List} interface). + * + * @param index an index into this vector + * @return the component at the specified index + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + */ + public synchronized E elementAt(int index) { + if (index >= elementCount) { + throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); + } + + return elementData(index); + } + + /** + * Returns the first component (the item at index {@code 0}) of + * this vector. + * + * @return the first component of this vector + * @throws NoSuchElementException if this vector has no components + */ + public synchronized E firstElement() { + if (elementCount == 0) { + throw new NoSuchElementException(); + } + return elementData(0); + } + + /** + * Returns the last component of the vector. + * + * @return the last component of the vector, i.e., the component at index + * size() - 1. + * @throws NoSuchElementException if this vector is empty + */ + public synchronized E lastElement() { + if (elementCount == 0) { + throw new NoSuchElementException(); + } + return elementData(elementCount - 1); + } + + /** + * Sets the component at the specified {@code index} of this + * vector to be the specified object. The previous component at that + * position is discarded. + * + *

The index must be a value greater than or equal to {@code 0} + * and less than the current size of the vector. + * + *

This method is identical in functionality to the + * {@link #set(int, Object) set(int, E)} + * method (which is part of the {@link List} interface). Note that the + * {@code set} method reverses the order of the parameters, to more closely + * match array usage. Note also that the {@code set} method returns the + * old value that was stored at the specified position. + * + * @param obj what the component is to be set to + * @param index the specified index + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + */ + public synchronized void setElementAt(E obj, int index) { + if (index >= elementCount) { + throw new ArrayIndexOutOfBoundsException(index + " >= " + + elementCount); + } + elementData[index] = obj; + } + + /** + * Deletes the component at the specified index. Each component in + * this vector with an index greater or equal to the specified + * {@code index} is shifted downward to have an index one + * smaller than the value it had previously. The size of this vector + * is decreased by {@code 1}. + * + *

The index must be a value greater than or equal to {@code 0} + * and less than the current size of the vector. + * + *

This method is identical in functionality to the {@link #remove(int)} + * method (which is part of the {@link List} interface). Note that the + * {@code remove} method returns the old value that was stored at the + * specified position. + * + * @param index the index of the object to remove + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + */ + public synchronized void removeElementAt(int index) { + modCount++; + if (index >= elementCount) { + throw new ArrayIndexOutOfBoundsException(index + " >= " + + elementCount); + } + else if (index < 0) { + throw new ArrayIndexOutOfBoundsException(index); + } + int j = elementCount - index - 1; + if (j > 0) { + System.arraycopy(elementData, index + 1, elementData, index, j); + } + elementCount--; + elementData[elementCount] = null; /* to let gc do its work */ + } + + /** + * Inserts the specified object as a component in this vector at the + * specified {@code index}. Each component in this vector with + * an index greater or equal to the specified {@code index} is + * shifted upward to have an index one greater than the value it had + * previously. + * + *

The index must be a value greater than or equal to {@code 0} + * and less than or equal to the current size of the vector. (If the + * index is equal to the current size of the vector, the new element + * is appended to the Vector.) + * + *

This method is identical in functionality to the + * {@link #add(int, Object) add(int, E)} + * method (which is part of the {@link List} interface). Note that the + * {@code add} method reverses the order of the parameters, to more closely + * match array usage. + * + * @param obj the component to insert + * @param index where to insert the new component + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index > size()}) + */ + public synchronized void insertElementAt(E obj, int index) { + modCount++; + if (index > elementCount) { + throw new ArrayIndexOutOfBoundsException(index + + " > " + elementCount); + } + ensureCapacityHelper(elementCount + 1); + System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); + elementData[index] = obj; + elementCount++; + } + + /** + * Adds the specified component to the end of this vector, + * increasing its size by one. The capacity of this vector is + * increased if its size becomes greater than its capacity. + * + *

This method is identical in functionality to the + * {@link #add(Object) add(E)} + * method (which is part of the {@link List} interface). + * + * @param obj the component to be added + */ + public synchronized void addElement(E obj) { + modCount++; + ensureCapacityHelper(elementCount + 1); + elementData[elementCount++] = obj; + } + + /** + * Removes the first (lowest-indexed) occurrence of the argument + * from this vector. If the object is found in this vector, each + * component in the vector with an index greater or equal to the + * object's index is shifted downward to have an index one smaller + * than the value it had previously. + * + *

This method is identical in functionality to the + * {@link #remove(Object)} method (which is part of the + * {@link List} interface). + * + * @param obj the component to be removed + * @return {@code true} if the argument was a component of this + * vector; {@code false} otherwise. + */ + public synchronized boolean removeElement(Object obj) { + modCount++; + int i = indexOf(obj); + if (i >= 0) { + removeElementAt(i); + return true; + } + return false; + } + + /** + * Removes all components from this vector and sets its size to zero. + * + *

This method is identical in functionality to the {@link #clear} + * method (which is part of the {@link List} interface). + */ + public synchronized void removeAllElements() { + modCount++; + // Let gc do its work + for (int i = 0; i < elementCount; i++) + elementData[i] = null; + + elementCount = 0; + } + + /** + * Returns a clone of this vector. The copy will contain a + * reference to a clone of the internal data array, not a reference + * to the original internal data array of this {@code Vector} object. + * + * @return a clone of this vector + */ + public synchronized Object clone() { + try { + @SuppressWarnings("unchecked") + Vector v = (Vector) super.clone(); + v.elementData = Arrays.copyOf(elementData, elementCount); + v.modCount = 0; + return v; + } catch (CloneNotSupportedException e) { + // this shouldn't happen, since we are Cloneable + throw new InternalError(); + } + } + + /** + * Returns an array containing all of the elements in this Vector + * in the correct order. + * + * @since 1.2 + */ + public synchronized Object[] toArray() { + return Arrays.copyOf(elementData, elementCount); + } + + /** + * Returns an array containing all of the elements in this Vector in the + * correct order; the runtime type of the returned array is that of the + * specified array. If the Vector 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 Vector. + * + *

If the Vector fits in the specified array with room to spare + * (i.e., the array has more elements than the Vector), + * the element in the array immediately following the end of the + * Vector is set to null. (This is useful in determining the length + * of the Vector only if the caller knows that the Vector + * does not contain any null elements.) + * + * @param a the array into which the elements of the Vector 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 the Vector + * @throws ArrayStoreException if the runtime type of a is not a supertype + * of the runtime type of every element in this Vector + * @throws NullPointerException if the given array is null + * @since 1.2 + */ + @SuppressWarnings("unchecked") + public synchronized T[] toArray(T[] a) { + if (a.length < elementCount) + return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass()); + + System.arraycopy(elementData, 0, a, 0, elementCount); + + if (a.length > elementCount) + a[elementCount] = null; + + return a; + } + + // Positional Access Operations + + @SuppressWarnings("unchecked") + E elementData(int index) { + return (E) elementData[index]; + } + + /** + * Returns the element at the specified position in this Vector. + * + * @param index index of the element to return + * @return object at the specified index + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + * @since 1.2 + */ + public synchronized E get(int index) { + if (index >= elementCount) + throw new ArrayIndexOutOfBoundsException(index); + + return elementData(index); + } + + /** + * Replaces the element at the specified position in this Vector with the + * specified element. + * + * @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 ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + * @since 1.2 + */ + public synchronized E set(int index, E element) { + if (index >= elementCount) + throw new ArrayIndexOutOfBoundsException(index); + + E oldValue = elementData(index); + elementData[index] = element; + return oldValue; + } + + /** + * Appends the specified element to the end of this Vector. + * + * @param e element to be appended to this Vector + * @return {@code true} (as specified by {@link Collection#add}) + * @since 1.2 + */ + public synchronized boolean add(E e) { + modCount++; + ensureCapacityHelper(elementCount + 1); + elementData[elementCount++] = e; + return true; + } + + /** + * Removes the first occurrence of the specified element in this Vector + * If the Vector does not contain the element, it is unchanged. More + * formally, removes the element with the lowest index i such that + * {@code (o==null ? get(i)==null : o.equals(get(i)))} (if such + * an element exists). + * + * @param o element to be removed from this Vector, if present + * @return true if the Vector contained the specified element + * @since 1.2 + */ + public boolean remove(Object o) { + return removeElement(o); + } + + /** + * Inserts the specified element at the specified position in this Vector. + * 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 ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index > size()}) + * @since 1.2 + */ + public void add(int index, E element) { + insertElementAt(element, index); + } + + /** + * Removes the element at the specified position in this Vector. + * Shifts any subsequent elements to the left (subtracts one from their + * indices). Returns the element that was removed from the Vector. + * + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + * @param index the index of the element to be removed + * @return element that was removed + * @since 1.2 + */ + public synchronized E remove(int index) { + modCount++; + if (index >= elementCount) + throw new ArrayIndexOutOfBoundsException(index); + E oldValue = elementData(index); + + int numMoved = elementCount - index - 1; + if (numMoved > 0) + System.arraycopy(elementData, index+1, elementData, index, + numMoved); + elementData[--elementCount] = null; // Let gc do its work + + return oldValue; + } + + /** + * Removes all of the elements from this Vector. The Vector will + * be empty after this call returns (unless it throws an exception). + * + * @since 1.2 + */ + public void clear() { + removeAllElements(); + } + + // Bulk Operations + + /** + * Returns true if this Vector contains all of the elements in the + * specified Collection. + * + * @param c a collection whose elements will be tested for containment + * in this Vector + * @return true if this Vector contains all of the elements in the + * specified collection + * @throws NullPointerException if the specified collection is null + */ + public synchronized boolean containsAll(Collection c) { + return super.containsAll(c); + } + + /** + * Appends all of the elements in the specified Collection to the end of + * this Vector, 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. + * (This implies that the behavior of this call is undefined if the + * specified Collection is this Vector, and this Vector is nonempty.) + * + * @param c elements to be inserted into this Vector + * @return {@code true} if this Vector changed as a result of the call + * @throws NullPointerException if the specified collection is null + * @since 1.2 + */ + public synchronized boolean addAll(Collection c) { + modCount++; + Object[] a = c.toArray(); + int numNew = a.length; + ensureCapacityHelper(elementCount + numNew); + System.arraycopy(a, 0, elementData, elementCount, numNew); + elementCount += numNew; + return numNew != 0; + } + + /** + * Removes from this Vector all of its elements that are contained in the + * specified Collection. + * + * @param c a collection of elements to be removed from the Vector + * @return true if this Vector changed as a result of the call + * @throws ClassCastException if the types of one or more elements + * in this vector are incompatible with the specified + * collection + * (optional) + * @throws NullPointerException if this vector contains one or more null + * elements and the specified collection does not support null + * elements + * (optional), + * or if the specified collection is null + * @since 1.2 + */ + public synchronized boolean removeAll(Collection c) { + return super.removeAll(c); + } + + /** + * Retains only the elements in this Vector that are contained in the + * specified Collection. In other words, removes from this Vector all + * of its elements that are not contained in the specified Collection. + * + * @param c a collection of elements to be retained in this Vector + * (all other elements are removed) + * @return true if this Vector changed as a result of the call + * @throws ClassCastException if the types of one or more elements + * in this vector are incompatible with the specified + * collection + * (optional) + * @throws NullPointerException if this vector contains one or more null + * elements and the specified collection does not support null + * elements + * (optional), + * or if the specified collection is null + * @since 1.2 + */ + public synchronized boolean retainAll(Collection c) { + return super.retainAll(c); + } + + /** + * Inserts all of the elements in the specified Collection into this + * Vector at the specified position. 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 the Vector + * in the order that they are returned by the specified Collection's + * iterator. + * + * @param index index at which to insert the first element from the + * specified collection + * @param c elements to be inserted into this Vector + * @return {@code true} if this Vector changed as a result of the call + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index > size()}) + * @throws NullPointerException if the specified collection is null + * @since 1.2 + */ + public synchronized boolean addAll(int index, Collection c) { + modCount++; + if (index < 0 || index > elementCount) + throw new ArrayIndexOutOfBoundsException(index); + + Object[] a = c.toArray(); + int numNew = a.length; + ensureCapacityHelper(elementCount + numNew); + + int numMoved = elementCount - index; + if (numMoved > 0) + System.arraycopy(elementData, index, elementData, index + numNew, + numMoved); + + System.arraycopy(a, 0, elementData, index, numNew); + elementCount += numNew; + return numNew != 0; + } + + /** + * Compares the specified Object with this Vector for equality. Returns + * 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 equal. (Two elements {@code e1} and + * {@code e2} are equal 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. + * + * @param o the Object to be compared for equality with this Vector + * @return true if the specified Object is equal to this Vector + */ + public synchronized boolean equals(Object o) { + return super.equals(o); + } + + /** + * Returns the hash code value for this Vector. + */ + public synchronized int hashCode() { + return super.hashCode(); + } + + /** + * Returns a string representation of this Vector, containing + * the String representation of each element. + */ + public synchronized String toString() { + return super.toString(); + } + + /** + * Returns a view of the portion of this List between fromIndex, + * inclusive, and toIndex, exclusive. (If fromIndex and toIndex are + * equal, the returned List is empty.) The returned List is backed by this + * List, so 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. + * + *

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 operating on a subList view + * instead of a whole List. For example, the following idiom + * removes a range of elements from a List: + *

+     *      list.subList(from, to).clear();
+     * 
+ * Similar idioms may be constructed for indexOf and lastIndexOf, + * and all of the algorithms in the Collections class can be applied to + * a subList. + * + *

The semantics of the List returned by this method become undefined if + * the backing list (i.e., this List) is structurally modified in + * any way other than via the returned List. (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.) + * + * @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 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 synchronized List subList(int fromIndex, int toIndex) { + return Collections.synchronizedList(super.subList(fromIndex, toIndex), + this); + } + + /** + * 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.) + */ + protected synchronized void removeRange(int fromIndex, int toIndex) { + modCount++; + int numMoved = elementCount - toIndex; + System.arraycopy(elementData, toIndex, elementData, fromIndex, + numMoved); + + // Let gc do its work + int newElementCount = elementCount - (toIndex-fromIndex); + while (elementCount != newElementCount) + elementData[--elementCount] = null; + } + + /** + * Save the state of the {@code Vector} instance to a stream (that + * is, serialize it). + * This method performs synchronization to ensure the consistency + * of the serialized data. + */ + private void writeObject(java.io.ObjectOutputStream s) + throws java.io.IOException { + final java.io.ObjectOutputStream.PutField fields = s.putFields(); + final Object[] data; + synchronized (this) { + fields.put("capacityIncrement", capacityIncrement); + fields.put("elementCount", elementCount); + data = elementData.clone(); + } + fields.put("elementData", data); + s.writeFields(); + } + + /** + * 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. + * + *

The returned list iterator is fail-fast. + * + * @throws IndexOutOfBoundsException {@inheritDoc} + */ + public synchronized ListIterator listIterator(int index) { + if (index < 0 || index > elementCount) + throw new IndexOutOfBoundsException("Index: "+index); + return new ListItr(index); + } + + /** + * Returns a list iterator over the elements in this list (in proper + * sequence). + * + *

The returned list iterator is fail-fast. + * + * @see #listIterator(int) + */ + public synchronized ListIterator listIterator() { + return new ListItr(0); + } + + /** + * Returns an iterator over the elements in this list in proper sequence. + * + *

The returned iterator is fail-fast. + * + * @return an iterator over the elements in this list in proper sequence + */ + public synchronized Iterator iterator() { + return new Itr(); + } + + /** + * An optimized version of AbstractList.Itr + */ + private class Itr implements Iterator { + int cursor; // index of next element to return + int lastRet = -1; // index of last element returned; -1 if no such + int expectedModCount = modCount; + + public boolean hasNext() { + // Racy but within spec, since modifications are checked + // within or after synchronization in next/previous + return cursor != elementCount; + } + + public E next() { + synchronized (Vector.this) { + checkForComodification(); + int i = cursor; + if (i >= elementCount) + throw new NoSuchElementException(); + cursor = i + 1; + return elementData(lastRet = i); + } + } + + public void remove() { + if (lastRet == -1) + throw new IllegalStateException(); + synchronized (Vector.this) { + checkForComodification(); + Vector.this.remove(lastRet); + expectedModCount = modCount; + } + cursor = lastRet; + lastRet = -1; + } + + final void checkForComodification() { + if (modCount != expectedModCount) + throw new ConcurrentModificationException(); + } + } + + /** + * An optimized version of AbstractList.ListItr + */ + final class ListItr extends Itr implements ListIterator { + ListItr(int index) { + super(); + cursor = index; + } + + public boolean hasPrevious() { + return cursor != 0; + } + + public int nextIndex() { + return cursor; + } + + public int previousIndex() { + return cursor - 1; + } + + public E previous() { + synchronized (Vector.this) { + checkForComodification(); + int i = cursor - 1; + if (i < 0) + throw new NoSuchElementException(); + cursor = i; + return elementData(lastRet = i); + } + } + + public void set(E e) { + if (lastRet == -1) + throw new IllegalStateException(); + synchronized (Vector.this) { + checkForComodification(); + Vector.this.set(lastRet, e); + } + } + + public void add(E e) { + int i = cursor; + synchronized (Vector.this) { + checkForComodification(); + Vector.this.add(i, e); + expectedModCount = modCount; + } + cursor = i + 1; + lastRet = -1; + } + } +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/mini/src/main/java/java/lang/ArrayStoreException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/lang/ArrayStoreException.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1995, 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.lang; + +/** + * Thrown to indicate that an attempt has been made to store the + * wrong type of object into an array of objects. For example, the + * following code generates an ArrayStoreException: + *

+ *     Object x[] = new String[3];
+ *     x[0] = new Integer(0);
+ * 
+ * + * @author unascribed + * @since JDK1.0 + */ +public +class ArrayStoreException extends RuntimeException { + private static final long serialVersionUID = -4522193890499838241L; + + /** + * Constructs an ArrayStoreException with no detail message. + */ + public ArrayStoreException() { + super(); + } + + /** + * Constructs an ArrayStoreException with the specified + * detail message. + * + * @param s the detail message. + */ + public ArrayStoreException(String s) { + super(s); + } +} diff -r 784aaf9ee179 -r 41b8defdf158 emul/mini/src/main/java/java/lang/Override.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/lang/Override.java Mon Jan 28 13:30:53 2013 +0100 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2003, 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.lang; + +import java.lang.annotation.*; + +/** + * Indicates that a method declaration is intended to override a + * method declaration in a supertype. If a method is annotated with + * this annotation type compilers are required to generate an error + * message unless at least one of the following conditions hold: + * + *
  • + * The method does override or implement a method declared in a + * supertype. + *
  • + * The method has a signature that is override-equivalent to that of + * any public method declared in {@linkplain Object}. + *
+ * + * @author Peter von der Ahé + * @author Joshua Bloch + * @jls 9.6.1.4 Override + * @since 1.5 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.SOURCE) +public @interface Override { +}