diff --git a/notes/src/ArrayList.java b/notes/src/ArrayList.java deleted file mode 100644 index 17179aea..00000000 --- a/notes/src/ArrayList.java +++ /dev/null @@ -1,1034 +0,0 @@ -package java.util; - - -public class ArrayList<E> extends AbstractList<E> - implements List<E>, RandomAccess, Cloneable, java.io.Serializable -{ - private static final long serialVersionUID = 8683452581122892189L; - - /** - * The array buffer into which the elements of the ArrayList are stored. - * The capacity of the ArrayList is the length of this array buffer. - */ - private transient Object[] elementData; - - /** - * The size of the ArrayList (the number of elements it contains). - * - * @serial - */ - private int size; - - /** - * Constructs an empty list with the specified initial capacity. - * - * @param initialCapacity the initial capacity of the list - * @throws IllegalArgumentException if the specified initial capacity - * is negative - */ - public ArrayList(int initialCapacity) { - super(); - if (initialCapacity < 0) - throw new IllegalArgumentException("Illegal Capacity: "+ - initialCapacity); - this.elementData = new Object[initialCapacity]; - } - - /** - * Constructs an empty list with an initial capacity of ten. - */ - public ArrayList() { - this(10); - } - - /** - * 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 ArrayList(Collection<? extends E> c) { - elementData = c.toArray(); - size = elementData.length; - // c.toArray might (incorrectly) not return Object[] (see 6260652) - if (elementData.getClass() != Object[].class) - elementData = Arrays.copyOf(elementData, size, Object[].class); - } - - /** - * Trims the capacity of this <tt>ArrayList</tt> instance to be the - * list's current size. An application can use this operation to minimize - * the storage of an <tt>ArrayList</tt> instance. - */ - public void trimToSize() { - modCount++; - int oldCapacity = elementData.length; - if (size < oldCapacity) { - elementData = Arrays.copyOf(elementData, size); - } - } - - /** - * Increases the capacity of this <tt>ArrayList</tt> instance, if - * necessary, to ensure that it can hold at least the number of elements - * specified by the minimum capacity argument. - * - * @param minCapacity the desired minimum capacity - */ - public void ensureCapacity(int minCapacity) { - if (minCapacity > 0) - ensureCapacityInternal(minCapacity); - } - - private void ensureCapacityInternal(int minCapacity) { - modCount++; - // 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; - - /** - * Increases the capacity to ensure that it can hold at least the - * number of elements specified by the minimum capacity argument. - * - * @param minCapacity the desired minimum capacity - */ - private void grow(int minCapacity) { - // overflow-conscious code - int oldCapacity = elementData.length; - int newCapacity = oldCapacity + (oldCapacity >> 1); - if (newCapacity - minCapacity < 0) - newCapacity = minCapacity; - if (newCapacity - MAX_ARRAY_SIZE > 0) - newCapacity = hugeCapacity(minCapacity); - // minCapacity is usually close to size, so this is a win: - 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; - } - - /** - * Returns the number of elements in this list. - * - * @return the number of elements in this list - */ - public int size() { - return size; - } - - /** - * Returns <tt>true</tt> if this list contains no elements. - * - * @return <tt>true</tt> if this list contains no elements - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns <tt>true</tt> if this list contains the specified element. - * More formally, returns <tt>true</tt> if and only if this list contains - * at least one element <tt>e</tt> such that - * <tt>(o==null ? e==null : o.equals(e))</tt>. - * - * @param o element whose presence in this list is to be tested - * @return <tt>true</tt> if this list contains the specified element - */ - public boolean contains(Object o) { - return indexOf(o) >= 0; - } - - /** - * Returns the index of the first occurrence of the specified element - * in this list, or -1 if this list does not contain the element. - * More formally, returns the lowest index <tt>i</tt> such that - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, - * or -1 if there is no such index. - */ - public int indexOf(Object o) { - if (o == null) { - for (int i = 0; i < size; i++) - if (elementData[i]==null) - return i; - } else { - for (int i = 0; i < size; i++) - if (o.equals(elementData[i])) - return i; - } - 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 <tt>i</tt> such that - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, - * or -1 if there is no such index. - */ - public int lastIndexOf(Object o) { - if (o == null) { - for (int i = size-1; i >= 0; i--) - if (elementData[i]==null) - return i; - } else { - for (int i = size-1; i >= 0; i--) - if (o.equals(elementData[i])) - return i; - } - return -1; - } - - /** - * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The - * elements themselves are not copied.) - * - * @return a clone of this <tt>ArrayList</tt> instance - */ - public Object clone() { - try { - @SuppressWarnings("unchecked") - ArrayList<E> v = (ArrayList<E>) super.clone(); - v.elementData = Arrays.copyOf(elementData, size); - 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 list - * in proper sequence (from first to last element). - * - * <p>The returned array will be "safe" in that no references to it are - * maintained by this list. (In other words, this method must allocate - * a new array). The caller is thus free to modify the returned array. - * - * <p>This method acts as bridge between array-based and collection-based - * APIs. - * - * @return an array containing all of the elements in this list in - * proper sequence - */ - public Object[] toArray() { - return Arrays.copyOf(elementData, size); - } - - /** - * Returns an array containing all of the elements in this list in proper - * sequence (from first to last element); the runtime type of the returned - * array is that of the specified array. If the list fits in the - * specified array, it is returned therein. Otherwise, a new array is - * allocated with the runtime type of the specified array and the size of - * this list. - * - * <p>If the list fits in the specified array with room to spare - * (i.e., the array has more elements than the list), the element in - * the array immediately following the end of the collection is set to - * <tt>null</tt>. (This is useful in determining the length of the - * list <i>only</i> if the caller knows that the list does not contain - * any null elements.) - * - * @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> T[] toArray(T[] a) { - if (a.length < size) - // Make a new array of a's runtime type, but my contents: - return (T[]) Arrays.copyOf(elementData, size, a.getClass()); - System.arraycopy(elementData, 0, a, 0, size); - if (a.length > size) - a[size] = 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 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) { - rangeCheck(index); - - return elementData(index); - } - - /** - * 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) { - rangeCheck(index); - - E oldValue = elementData(index); - elementData[index] = element; - return oldValue; - } - - /** - * Appends the specified element to the end of this list. - * - * @param e element to be appended to this list - * @return <tt>true</tt> (as specified by {@link Collection#add}) - */ - public boolean add(E e) { - ensureCapacityInternal(size + 1); // Increments modCount!! - elementData[size++] = e; - return true; - } - - /** - * 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) { - rangeCheckForAdd(index); - - ensureCapacityInternal(size + 1); // Increments modCount!! - System.arraycopy(elementData, index, elementData, index + 1, - size - index); - elementData[index] = element; - size++; - } - - /** - * Removes the element at the specified position in this list. - * Shifts any subsequent elements to the left (subtracts one from their - * indices). - * - * @param index the index of the element to be removed - * @return the element that was removed from the list - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public E remove(int index) { - rangeCheck(index); - - modCount++; - E oldValue = elementData(index); - - int numMoved = size - index - 1; - if (numMoved > 0) - System.arraycopy(elementData, index+1, elementData, index, - numMoved); - elementData[--size] = null; // Let gc do its work - - return oldValue; - } - - /** - * Removes the first occurrence of the specified element from this list, - * if it is present. If the list does not contain the element, it is - * unchanged. More formally, removes the element with the lowest index - * <tt>i</tt> such that - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> - * (if such an element exists). Returns <tt>true</tt> if this list - * contained the specified element (or equivalently, if this list - * changed as a result of the call). - * - * @param o element to be removed from this list, if present - * @return <tt>true</tt> if this list contained the specified element - */ - public boolean remove(Object o) { - if (o == null) { - for (int index = 0; index < size; index++) - if (elementData[index] == null) { - fastRemove(index); - return true; - } - } else { - for (int index = 0; index < size; index++) - if (o.equals(elementData[index])) { - fastRemove(index); - return true; - } - } - return false; - } - - /* - * Private remove method that skips bounds checking and does not - * return the value removed. - */ - private void fastRemove(int index) { - modCount++; - int numMoved = size - index - 1; - if (numMoved > 0) - System.arraycopy(elementData, index+1, elementData, index, - numMoved); - elementData[--size] = null; // Let gc do its work - } - - /** - * Removes all of the elements from this list. The list will - * be empty after this call returns. - */ - public void clear() { - modCount++; - - // Let gc do its work - for (int i = 0; i < size; i++) - elementData[i] = null; - - size = 0; - } - - /** - * 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. (This implies that the behavior of this call is - * undefined if the specified collection is this list, and this - * list is nonempty.) - * - * @param c collection containing elements to be added to this list - * @return <tt>true</tt> if this list changed as a result of the call - * @throws NullPointerException if the specified collection is null - */ - public boolean addAll(Collection<? extends E> c) { - Object[] a = c.toArray(); - int numNew = a.length; - ensureCapacityInternal(size + numNew); // Increments modCount - System.arraycopy(a, 0, elementData, size, numNew); - size += numNew; - return numNew != 0; - } - - /** - * 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 <tt>true</tt> 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<? extends E> c) { - rangeCheckForAdd(index); - - Object[] a = c.toArray(); - int numNew = a.length; - ensureCapacityInternal(size + numNew); // Increments modCount - - int numMoved = size - index; - if (numMoved > 0) - System.arraycopy(elementData, index, elementData, index + numNew, - numMoved); - - System.arraycopy(a, 0, elementData, index, numNew); - size += numNew; - return numNew != 0; - } - - /** - * 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.) - * - * @throws IndexOutOfBoundsException if {@code fromIndex} or - * {@code toIndex} is out of range - * ({@code fromIndex < 0 || - * fromIndex >= size() || - * toIndex > size() || - * toIndex < fromIndex}) - */ - protected void removeRange(int fromIndex, int toIndex) { - modCount++; - int numMoved = size - toIndex; - System.arraycopy(elementData, toIndex, elementData, fromIndex, - numMoved); - - // Let gc do its work - int newSize = size - (toIndex-fromIndex); - while (size != newSize) - elementData[--size] = null; - } - - /** - * Checks if the given index is in range. If not, throws an appropriate - * runtime exception. This method does *not* check if the index is - * negative: It is always used immediately prior to an array access, - * which throws an ArrayIndexOutOfBoundsException if index is negative. - */ - private void rangeCheck(int index) { - if (index >= size) - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - - /** - * A version of rangeCheck used by add and addAll. - */ - private void rangeCheckForAdd(int index) { - if (index > size || index < 0) - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - - /** - * 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; - } - - /** - * Removes from this list all of its elements that are contained in the - * specified collection. - * - * @param c collection containing elements to be removed from this list - * @return {@code true} if this list changed as a result of the call - * @throws ClassCastException if the class of an element of this list - * is incompatible with the specified collection - * (<a href="Collection.html#optional-restrictions">optional</a>) - * @throws NullPointerException if this list contains a null element and the - * specified collection does not permit null elements - * (<a href="Collection.html#optional-restrictions">optional</a>), - * or if the specified collection is null - * @see Collection#contains(Object) - */ - public boolean removeAll(Collection<?> c) { - return batchRemove(c, false); - } - - /** - * Retains only the elements in this list that are contained in the - * specified collection. In other words, removes from this list all - * of its elements that are not contained in the specified collection. - * - * @param c collection containing elements to be retained in this list - * @return {@code true} if this list changed as a result of the call - * @throws ClassCastException if the class of an element of this list - * is incompatible with the specified collection - * (<a href="Collection.html#optional-restrictions">optional</a>) - * @throws NullPointerException if this list contains a null element and the - * specified collection does not permit null elements - * (<a href="Collection.html#optional-restrictions">optional</a>), - * or if the specified collection is null - * @see Collection#contains(Object) - */ - public boolean retainAll(Collection<?> c) { - return batchRemove(c, true); - } - - private boolean batchRemove(Collection<?> c, boolean complement) { - final Object[] elementData = this.elementData; - int r = 0, w = 0; - boolean modified = false; - try { - for (; r < size; r++) - if (c.contains(elementData[r]) == complement) - elementData[w++] = elementData[r]; - } finally { - // Preserve behavioral compatibility with AbstractCollection, - // even if c.contains() throws. - if (r != size) { - System.arraycopy(elementData, r, - elementData, w, - size - r); - w += size - r; - } - if (w != size) { - for (int i = w; i < size; i++) - elementData[i] = null; - modCount += size - w; - size = w; - modified = true; - } - } - return modified; - } - - /** - * Save the state of the <tt>ArrayList</tt> instance to a stream (that - * is, serialize it). - * - * @serialData The length of the array backing the <tt>ArrayList</tt> - * instance is emitted (int), followed by all of its elements - * (each an <tt>Object</tt>) in the proper order. - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException{ - // Write out element count, and any hidden stuff - int expectedModCount = modCount; - s.defaultWriteObject(); - - // Write out array length - s.writeInt(elementData.length); - - // Write out all elements in the proper order. - for (int i=0; i<size; i++) - s.writeObject(elementData[i]); - - if (modCount != expectedModCount) { - throw new ConcurrentModificationException(); - } - - } - - /** - * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is, - * deserialize it). - */ - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - // Read in size, and any hidden stuff - s.defaultReadObject(); - - // Read in array length and allocate array - int arrayLength = s.readInt(); - Object[] a = elementData = new Object[arrayLength]; - - // Read in all elements in the proper order. - for (int i=0; i<size; i++) - a[i] = s.readObject(); - } - - /** - * 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. - * - * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>. - * - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public ListIterator<E> listIterator(int index) { - if (index < 0 || index > size) - throw new IndexOutOfBoundsException("Index: "+index); - return new ListItr(index); - } - - /** - * Returns a list iterator over the elements in this list (in proper - * sequence). - * - * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>. - * - * @see #listIterator(int) - */ - public ListIterator<E> listIterator() { - return new ListItr(0); - } - - /** - * Returns an iterator over the elements in this list in proper sequence. - * - * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>. - * - * @return an iterator over the elements in this list in proper sequence - */ - public Iterator<E> iterator() { - return new Itr(); - } - - /** - * An optimized version of AbstractList.Itr - */ - private class Itr implements Iterator<E> { - 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() { - return cursor != size; - } - - @SuppressWarnings("unchecked") - public E next() { - checkForComodification(); - int i = cursor; - if (i >= size) - throw new NoSuchElementException(); - Object[] elementData = ArrayList.this.elementData; - if (i >= elementData.length) - throw new ConcurrentModificationException(); - cursor = i + 1; - return (E) elementData[lastRet = i]; - } - - public void remove() { - if (lastRet < 0) - throw new IllegalStateException(); - checkForComodification(); - - try { - ArrayList.this.remove(lastRet); - cursor = lastRet; - lastRet = -1; - expectedModCount = modCount; - } catch (IndexOutOfBoundsException ex) { - throw new ConcurrentModificationException(); - } - } - - final void checkForComodification() { - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - } - } - - /** - * An optimized version of AbstractList.ListItr - */ - private class ListItr extends Itr implements ListIterator<E> { - ListItr(int index) { - super(); - cursor = index; - } - - public boolean hasPrevious() { - return cursor != 0; - } - - public int nextIndex() { - return cursor; - } - - public int previousIndex() { - return cursor - 1; - } - - @SuppressWarnings("unchecked") - public E previous() { - checkForComodification(); - int i = cursor - 1; - if (i < 0) - throw new NoSuchElementException(); - Object[] elementData = ArrayList.this.elementData; - if (i >= elementData.length) - throw new ConcurrentModificationException(); - cursor = i; - return (E) elementData[lastRet = i]; - } - - public void set(E e) { - if (lastRet < 0) - throw new IllegalStateException(); - checkForComodification(); - - try { - ArrayList.this.set(lastRet, e); - } catch (IndexOutOfBoundsException ex) { - throw new ConcurrentModificationException(); - } - } - - public void add(E e) { - checkForComodification(); - - try { - int i = cursor; - ArrayList.this.add(i, e); - cursor = i + 1; - lastRet = -1; - expectedModCount = modCount; - } catch (IndexOutOfBoundsException ex) { - throw new ConcurrentModificationException(); - } - } - } - - /** - * Returns a view of the portion of this list between the specified - * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. (If - * {@code fromIndex} and {@code toIndex} are equal, the returned list is - * empty.) The returned list is backed by this list, so non-structural - * changes in the returned list are reflected in this list, and vice-versa. - * The returned list supports all of the optional list operations. - * - * <p>This method eliminates the need for explicit range operations (of - * the sort that commonly exist for arrays). Any operation that expects - * a list can be used as a range operation by passing a subList view - * instead of a whole list. For example, the following idiom - * removes a range of elements from a list: - * <pre> - * list.subList(from, to).clear(); - * </pre> - * Similar idioms may be constructed for {@link #indexOf(Object)} and - * {@link #lastIndexOf(Object)}, and all of the algorithms in the - * {@link Collections} class can be applied to a subList. - * - * <p>The semantics of the list returned by this method become undefined if - * the backing list (i.e., this list) is <i>structurally modified</i> in - * any way other than via the returned list. (Structural modifications are - * those that change the size of this list, or otherwise perturb it in such - * a fashion that iterations in progress may yield incorrect results.) - * - * @throws IndexOutOfBoundsException {@inheritDoc} - * @throws IllegalArgumentException {@inheritDoc} - */ - public List<E> subList(int fromIndex, int toIndex) { - subListRangeCheck(fromIndex, toIndex, size); - return new SubList(this, 0, fromIndex, toIndex); - } - - static void subListRangeCheck(int fromIndex, int toIndex, int size) { - if (fromIndex < 0) - throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); - if (toIndex > size) - throw new IndexOutOfBoundsException("toIndex = " + toIndex); - if (fromIndex > toIndex) - throw new IllegalArgumentException("fromIndex(" + fromIndex + - ") > toIndex(" + toIndex + ")"); - } - - private class SubList extends AbstractList<E> implements RandomAccess { - private final AbstractList<E> parent; - private final int parentOffset; - private final int offset; - int size; - - SubList(AbstractList<E> parent, - int offset, int fromIndex, int toIndex) { - this.parent = parent; - this.parentOffset = fromIndex; - this.offset = offset + fromIndex; - this.size = toIndex - fromIndex; - this.modCount = ArrayList.this.modCount; - } - - public E set(int index, E e) { - rangeCheck(index); - checkForComodification(); - E oldValue = ArrayList.this.elementData(offset + index); - ArrayList.this.elementData[offset + index] = e; - return oldValue; - } - - public E get(int index) { - rangeCheck(index); - checkForComodification(); - return ArrayList.this.elementData(offset + index); - } - - public int size() { - checkForComodification(); - return this.size; - } - - public void add(int index, E e) { - rangeCheckForAdd(index); - checkForComodification(); - parent.add(parentOffset + index, e); - this.modCount = parent.modCount; - this.size++; - } - - public E remove(int index) { - rangeCheck(index); - checkForComodification(); - E result = parent.remove(parentOffset + index); - this.modCount = parent.modCount; - this.size--; - return result; - } - - protected void removeRange(int fromIndex, int toIndex) { - checkForComodification(); - parent.removeRange(parentOffset + fromIndex, - parentOffset + toIndex); - this.modCount = parent.modCount; - this.size -= toIndex - fromIndex; - } - - public boolean addAll(Collection<? extends E> c) { - return addAll(this.size, c); - } - - public boolean addAll(int index, Collection<? extends E> c) { - rangeCheckForAdd(index); - int cSize = c.size(); - if (cSize==0) - return false; - - checkForComodification(); - parent.addAll(parentOffset + index, c); - this.modCount = parent.modCount; - this.size += cSize; - return true; - } - - public Iterator<E> iterator() { - return listIterator(); - } - - public ListIterator<E> listIterator(final int index) { - checkForComodification(); - rangeCheckForAdd(index); - final int offset = this.offset; - - return new ListIterator<E>() { - int cursor = index; - int lastRet = -1; - int expectedModCount = ArrayList.this.modCount; - - public boolean hasNext() { - return cursor != SubList.this.size; - } - - @SuppressWarnings("unchecked") - public E next() { - checkForComodification(); - int i = cursor; - if (i >= SubList.this.size) - throw new NoSuchElementException(); - Object[] elementData = ArrayList.this.elementData; - if (offset + i >= elementData.length) - throw new ConcurrentModificationException(); - cursor = i + 1; - return (E) elementData[offset + (lastRet = i)]; - } - - public boolean hasPrevious() { - return cursor != 0; - } - - @SuppressWarnings("unchecked") - public E previous() { - checkForComodification(); - int i = cursor - 1; - if (i < 0) - throw new NoSuchElementException(); - Object[] elementData = ArrayList.this.elementData; - if (offset + i >= elementData.length) - throw new ConcurrentModificationException(); - cursor = i; - return (E) elementData[offset + (lastRet = i)]; - } - - public int nextIndex() { - return cursor; - } - - public int previousIndex() { - return cursor - 1; - } - - public void remove() { - if (lastRet < 0) - throw new IllegalStateException(); - checkForComodification(); - - try { - SubList.this.remove(lastRet); - cursor = lastRet; - lastRet = -1; - expectedModCount = ArrayList.this.modCount; - } catch (IndexOutOfBoundsException ex) { - throw new ConcurrentModificationException(); - } - } - - public void set(E e) { - if (lastRet < 0) - throw new IllegalStateException(); - checkForComodification(); - - try { - ArrayList.this.set(offset + lastRet, e); - } catch (IndexOutOfBoundsException ex) { - throw new ConcurrentModificationException(); - } - } - - public void add(E e) { - checkForComodification(); - - try { - int i = cursor; - SubList.this.add(i, e); - cursor = i + 1; - lastRet = -1; - expectedModCount = ArrayList.this.modCount; - } catch (IndexOutOfBoundsException ex) { - throw new ConcurrentModificationException(); - } - } - - final void checkForComodification() { - if (expectedModCount != ArrayList.this.modCount) - throw new ConcurrentModificationException(); - } - }; - } - - public List<E> subList(int fromIndex, int toIndex) { - subListRangeCheck(fromIndex, toIndex, size); - return new SubList(this, offset, fromIndex, toIndex); - } - - private void rangeCheck(int index) { - if (index < 0 || index >= this.size) - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - - private void rangeCheckForAdd(int index) { - if (index < 0 || index > this.size) - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - - private String outOfBoundsMsg(int index) { - return "Index: "+index+", Size: "+this.size; - } - - private void checkForComodification() { - if (ArrayList.this.modCount != this.modCount) - throw new ConcurrentModificationException(); - } - } -} diff --git a/notes/src/ConcurrentHashMap.java b/notes/src/ConcurrentHashMap.java deleted file mode 100644 index 338f7d65..00000000 --- a/notes/src/ConcurrentHashMap.java +++ /dev/null @@ -1,1430 +0,0 @@ - -package java.util.concurrent; -import java.util.concurrent.locks.*; -import java.util.*; -import java.io.Serializable; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> - implements ConcurrentMap<K, V>, Serializable { - private static final long serialVersionUID = 7249069246763182397L; - - /* - * The basic strategy is to subdivide the table among Segments, - * each of which itself is a concurrently readable hash table. To - * reduce footprint, all but one segments are constructed only - * when first needed (see ensureSegment). To maintain visibility - * in the presence of lazy construction, accesses to segments as - * well as elements of segment's table must use volatile access, - * which is done via Unsafe within methods segmentAt etc - * below. These provide the functionality of AtomicReferenceArrays - * but reduce the levels of indirection. Additionally, - * volatile-writes of table elements and entry "next" fields - * within locked operations use the cheaper "lazySet" forms of - * writes (via putOrderedObject) because these writes are always - * followed by lock releases that maintain sequential consistency - * of table updates. - * - * Historical note: The previous version of this class relied - * heavily on "final" fields, which avoided some volatile reads at - * the expense of a large initial footprint. Some remnants of - * that design (including forced construction of segment 0) exist - * to ensure serialization compatibility. - */ - - /* ---------------- Constants -------------- */ - - /** - * The default initial capacity for this table, - * used when not otherwise specified in a constructor. - */ - static final int DEFAULT_INITIAL_CAPACITY = 16; - - /** - * The default load factor for this table, used when not - * otherwise specified in a constructor. - */ - static final float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * The default concurrency level for this table, used when not - * otherwise specified in a constructor. - */ - static final int DEFAULT_CONCURRENCY_LEVEL = 16; - - /** - * The maximum capacity, used if a higher value is implicitly - * specified by either of the constructors with arguments. MUST - * be a power of two <= 1<<30 to ensure that entries are indexable - * using ints. - */ - static final int MAXIMUM_CAPACITY = 1 << 30; - - /** - * The minimum capacity for per-segment tables. Must be a power - * of two, at least two to avoid immediate resizing on next use - * after lazy construction. - */ - static final int MIN_SEGMENT_TABLE_CAPACITY = 2; - - /** - * The maximum number of segments to allow; used to bound - * constructor arguments. Must be power of two less than 1 << 24. - */ - static final int MAX_SEGMENTS = 1 << 16; // slightly conservative - - /** - * Number of unsynchronized retries in size and containsValue - * methods before resorting to locking. This is used to avoid - * unbounded retries if tables undergo continuous modification - * which would make it impossible to obtain an accurate result. - */ - static final int RETRIES_BEFORE_LOCK = 2; - - /* ---------------- Fields -------------- */ - - /** - * Mask value for indexing into segments. The upper bits of a - * key's hash code are used to choose the segment. - */ - final int segmentMask; - - /** - * Shift value for indexing within segments. - */ - final int segmentShift; - - /** - * The segments, each of which is a specialized hash table. - */ - final Segment<K,V>[] segments; - - transient Set<K> keySet; - transient Set<Map.Entry<K,V>> entrySet; - transient Collection<V> values; - - /** - * ConcurrentHashMap list entry. Note that this is never exported - * out as a user-visible Map.Entry. - */ - static final class HashEntry<K,V> { - final int hash; - final K key; - volatile V value; - volatile HashEntry<K,V> next; - - HashEntry(int hash, K key, V value, HashEntry<K,V> next) { - this.hash = hash; - this.key = key; - this.value = value; - this.next = next; - } - - /** - * Sets next field with volatile write semantics. (See above - * about use of putOrderedObject.) - */ - final void setNext(HashEntry<K,V> n) { - UNSAFE.putOrderedObject(this, nextOffset, n); - } - - // Unsafe mechanics - static final sun.misc.Unsafe UNSAFE; - static final long nextOffset; - static { - try { - UNSAFE = sun.misc.Unsafe.getUnsafe(); - Class k = HashEntry.class; - nextOffset = UNSAFE.objectFieldOffset - (k.getDeclaredField("next")); - } catch (Exception e) { - throw new Error(e); - } - } - } - - /** - * Gets the ith element of given table (if nonnull) with volatile - * read semantics. Note: This is manually integrated into a few - * performance-sensitive methods to reduce call overhead. - */ - @SuppressWarnings("unchecked") - static final <K,V> HashEntry<K,V> entryAt(HashEntry<K,V>[] tab, int i) { - return (tab == null) ? null : - (HashEntry<K,V>) UNSAFE.getObjectVolatile - (tab, ((long)i << TSHIFT) + TBASE); - } - - /** - * Sets the ith element of given table, with volatile write - * semantics. (See above about use of putOrderedObject.) - */ - static final <K,V> void setEntryAt(HashEntry<K,V>[] tab, int i, - HashEntry<K,V> e) { - UNSAFE.putOrderedObject(tab, ((long)i << TSHIFT) + TBASE, e); - } - - /** - * Applies a supplemental hash function to a given hashCode, which - * defends against poor quality hash functions. This is critical - * because ConcurrentHashMap uses power-of-two length hash tables, - * that otherwise encounter collisions for hashCodes that do not - * differ in lower or upper bits. - */ - private static int hash(int h) { - // Spread bits to regularize both segment and index locations, - // using variant of single-word Wang/Jenkins hash. - h += (h << 15) ^ 0xffffcd7d; - h ^= (h >>> 10); - h += (h << 3); - h ^= (h >>> 6); - h += (h << 2) + (h << 14); - return h ^ (h >>> 16); - } - - /** - * Segments are specialized versions of hash tables. This - * subclasses from ReentrantLock opportunistically, just to - * simplify some locking and avoid separate construction. - */ - static final class Segment<K,V> extends ReentrantLock implements Serializable { - /* - * Segments maintain a table of entry lists that are always - * kept in a consistent state, so can be read (via volatile - * reads of segments and tables) without locking. This - * requires replicating nodes when necessary during table - * resizing, so the old lists can be traversed by readers - * still using old version of table. - * - * This class defines only mutative methods requiring locking. - * Except as noted, the methods of this class perform the - * per-segment versions of ConcurrentHashMap methods. (Other - * methods are integrated directly into ConcurrentHashMap - * methods.) These mutative methods use a form of controlled - * spinning on contention via methods scanAndLock and - * scanAndLockForPut. These intersperse tryLocks with - * traversals to locate nodes. The main benefit is to absorb - * cache misses (which are very common for hash tables) while - * obtaining locks so that traversal is faster once - * acquired. We do not actually use the found nodes since they - * must be re-acquired under lock anyway to ensure sequential - * consistency of updates (and in any case may be undetectably - * stale), but they will normally be much faster to re-locate. - * Also, scanAndLockForPut speculatively creates a fresh node - * to use in put if no node is found. - */ - - private static final long serialVersionUID = 2249069246763182397L; - - /** - * The maximum number of times to tryLock in a prescan before - * possibly blocking on acquire in preparation for a locked - * segment operation. On multiprocessors, using a bounded - * number of retries maintains cache acquired while locating - * nodes. - */ - static final int MAX_SCAN_RETRIES = - Runtime.getRuntime().availableProcessors() > 1 ? 64 : 1; - - /** - * The per-segment table. Elements are accessed via - * entryAt/setEntryAt providing volatile semantics. - */ - transient volatile HashEntry<K,V>[] table; - - /** - * The number of elements. Accessed only either within locks - * or among other volatile reads that maintain visibility. - */ - transient int count; - - /** - * The total number of mutative operations in this segment. - * Even though this may overflows 32 bits, it provides - * sufficient accuracy for stability checks in CHM isEmpty() - * and size() methods. Accessed only either within locks or - * among other volatile reads that maintain visibility. - */ - transient int modCount; - - /** - * The table is rehashed when its size exceeds this threshold. - * (The value of this field is always <tt>(int)(capacity * - * loadFactor)</tt>.) - */ - transient int threshold; - - /** - * The load factor for the hash table. Even though this value - * is same for all segments, it is replicated to avoid needing - * links to outer object. - * @serial - */ - final float loadFactor; - - Segment(float lf, int threshold, HashEntry<K,V>[] tab) { - this.loadFactor = lf; - this.threshold = threshold; - this.table = tab; - } - - final V put(K key, int hash, V value, boolean onlyIfAbsent) { - HashEntry<K,V> node = tryLock() ? null : - scanAndLockForPut(key, hash, value); - V oldValue; - try { - HashEntry<K,V>[] tab = table; - int index = (tab.length - 1) & hash; - HashEntry<K,V> first = entryAt(tab, index); - for (HashEntry<K,V> e = first;;) { - if (e != null) { - K k; - if ((k = e.key) == key || - (e.hash == hash && key.equals(k))) { - oldValue = e.value; - if (!onlyIfAbsent) { - e.value = value; - ++modCount; - } - break; - } - e = e.next; - } - else { - if (node != null) - node.setNext(first); - else - node = new HashEntry<K,V>(hash, key, value, first); - int c = count + 1; - if (c > threshold && tab.length < MAXIMUM_CAPACITY) - rehash(node); - else - setEntryAt(tab, index, node); - ++modCount; - count = c; - oldValue = null; - break; - } - } - } finally { - unlock(); - } - return oldValue; - } - - /** - * Doubles size of table and repacks entries, also adding the - * given node to new table - */ - @SuppressWarnings("unchecked") - private void rehash(HashEntry<K,V> node) { - /* - * Reclassify nodes in each list to new table. Because we - * are using power-of-two expansion, the elements from - * each bin must either stay at same index, or move with a - * power of two offset. We eliminate unnecessary node - * creation by catching cases where old nodes can be - * reused because their next fields won't change. - * Statistically, at the default threshold, only about - * one-sixth of them need cloning when a table - * doubles. The nodes they replace will be garbage - * collectable as soon as they are no longer referenced by - * any reader thread that may be in the midst of - * concurrently traversing table. Entry accesses use plain - * array indexing because they are followed by volatile - * table write. - */ - HashEntry<K,V>[] oldTable = table; - int oldCapacity = oldTable.length; - int newCapacity = oldCapacity << 1; - threshold = (int)(newCapacity * loadFactor); - HashEntry<K,V>[] newTable = - (HashEntry<K,V>[]) new HashEntry[newCapacity]; - int sizeMask = newCapacity - 1; - for (int i = 0; i < oldCapacity ; i++) { - HashEntry<K,V> e = oldTable[i]; - if (e != null) { - HashEntry<K,V> next = e.next; - int idx = e.hash & sizeMask; - if (next == null) // Single node on list - newTable[idx] = e; - else { // Reuse consecutive sequence at same slot - HashEntry<K,V> lastRun = e; - int lastIdx = idx; - for (HashEntry<K,V> last = next; - last != null; - last = last.next) { - int k = last.hash & sizeMask; - if (k != lastIdx) { - lastIdx = k; - lastRun = last; - } - } - newTable[lastIdx] = lastRun; - // Clone remaining nodes - for (HashEntry<K,V> p = e; p != lastRun; p = p.next) { - V v = p.value; - int h = p.hash; - int k = h & sizeMask; - HashEntry<K,V> n = newTable[k]; - newTable[k] = new HashEntry<K,V>(h, p.key, v, n); - } - } - } - } - int nodeIndex = node.hash & sizeMask; // add the new node - node.setNext(newTable[nodeIndex]); - newTable[nodeIndex] = node; - table = newTable; - } - - /** - * Scans for a node containing given key while trying to - * acquire lock, creating and returning one if not found. Upon - * return, guarantees that lock is held. UNlike in most - * methods, calls to method equals are not screened: Since - * traversal speed doesn't matter, we might as well help warm - * up the associated code and accesses as well. - * - * @return a new node if key not found, else null - */ - private HashEntry<K,V> scanAndLockForPut(K key, int hash, V value) { - HashEntry<K,V> first = entryForHash(this, hash); - HashEntry<K,V> e = first; - HashEntry<K,V> node = null; - int retries = -1; // negative while locating node - while (!tryLock()) { - HashEntry<K,V> f; // to recheck first below - if (retries < 0) { - if (e == null) { - if (node == null) // speculatively create node - node = new HashEntry<K,V>(hash, key, value, null); - retries = 0; - } - else if (key.equals(e.key)) - retries = 0; - else - e = e.next; - } - else if (++retries > MAX_SCAN_RETRIES) { - lock(); - break; - } - else if ((retries & 1) == 0 && - (f = entryForHash(this, hash)) != first) { - e = first = f; // re-traverse if entry changed - retries = -1; - } - } - return node; - } - - /** - * Scans for a node containing the given key while trying to - * acquire lock for a remove or replace operation. Upon - * return, guarantees that lock is held. Note that we must - * lock even if the key is not found, to ensure sequential - * consistency of updates. - */ - private void scanAndLock(Object key, int hash) { - // similar to but simpler than scanAndLockForPut - HashEntry<K,V> first = entryForHash(this, hash); - HashEntry<K,V> e = first; - int retries = -1; - while (!tryLock()) { - HashEntry<K,V> f; - if (retries < 0) { - if (e == null || key.equals(e.key)) - retries = 0; - else - e = e.next; - } - else if (++retries > MAX_SCAN_RETRIES) { - lock(); - break; - } - else if ((retries & 1) == 0 && - (f = entryForHash(this, hash)) != first) { - e = first = f; - retries = -1; - } - } - } - - /** - * Remove; match on key only if value null, else match both. - */ - final V remove(Object key, int hash, Object value) { - if (!tryLock()) - scanAndLock(key, hash); - V oldValue = null; - try { - HashEntry<K,V>[] tab = table; - int index = (tab.length - 1) & hash; - HashEntry<K,V> e = entryAt(tab, index); - HashEntry<K,V> pred = null; - while (e != null) { - K k; - HashEntry<K,V> next = e.next; - if ((k = e.key) == key || - (e.hash == hash && key.equals(k))) { - V v = e.value; - if (value == null || value == v || value.equals(v)) { - if (pred == null) - setEntryAt(tab, index, next); - else - pred.setNext(next); - ++modCount; - --count; - oldValue = v; - } - break; - } - pred = e; - e = next; - } - } finally { - unlock(); - } - return oldValue; - } - - final boolean replace(K key, int hash, V oldValue, V newValue) { - if (!tryLock()) - scanAndLock(key, hash); - boolean replaced = false; - try { - HashEntry<K,V> e; - for (e = entryForHash(this, hash); e != null; e = e.next) { - K k; - if ((k = e.key) == key || - (e.hash == hash && key.equals(k))) { - if (oldValue.equals(e.value)) { - e.value = newValue; - ++modCount; - replaced = true; - } - break; - } - } - } finally { - unlock(); - } - return replaced; - } - - final V replace(K key, int hash, V value) { - if (!tryLock()) - scanAndLock(key, hash); - V oldValue = null; - try { - HashEntry<K,V> e; - for (e = entryForHash(this, hash); e != null; e = e.next) { - K k; - if ((k = e.key) == key || - (e.hash == hash && key.equals(k))) { - oldValue = e.value; - e.value = value; - ++modCount; - break; - } - } - } finally { - unlock(); - } - return oldValue; - } - - final void clear() { - lock(); - try { - HashEntry<K,V>[] tab = table; - for (int i = 0; i < tab.length ; i++) - setEntryAt(tab, i, null); - ++modCount; - count = 0; - } finally { - unlock(); - } - } - } - - // Accessing segments - - /** - * Gets the jth element of given segment array (if nonnull) with - * volatile element access semantics via Unsafe. (The null check - * can trigger harmlessly only during deserialization.) Note: - * because each element of segments array is set only once (using - * fully ordered writes), some performance-sensitive methods rely - * on this method only as a recheck upon null reads. - */ - @SuppressWarnings("unchecked") - static final <K,V> Segment<K,V> segmentAt(Segment<K,V>[] ss, int j) { - long u = (j << SSHIFT) + SBASE; - return ss == null ? null : - (Segment<K,V>) UNSAFE.getObjectVolatile(ss, u); - } - - /** - * Returns the segment for the given index, creating it and - * recording in segment table (via CAS) if not already present. - * - * @param k the index - * @return the segment - */ - @SuppressWarnings("unchecked") - private Segment<K,V> ensureSegment(int k) { - final Segment<K,V>[] ss = this.segments; - long u = (k << SSHIFT) + SBASE; // raw offset - Segment<K,V> seg; - if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u)) == null) { - Segment<K,V> proto = ss[0]; // use segment 0 as prototype - int cap = proto.table.length; - float lf = proto.loadFactor; - int threshold = (int)(cap * lf); - HashEntry<K,V>[] tab = (HashEntry<K,V>[])new HashEntry[cap]; - if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u)) - == null) { // recheck - Segment<K,V> s = new Segment<K,V>(lf, threshold, tab); - while ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u)) - == null) { - if (UNSAFE.compareAndSwapObject(ss, u, null, seg = s)) - break; - } - } - } - return seg; - } - - // Hash-based segment and entry accesses - - /** - * Get the segment for the given hash - */ - @SuppressWarnings("unchecked") - private Segment<K,V> segmentForHash(int h) { - long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE; - return (Segment<K,V>) UNSAFE.getObjectVolatile(segments, u); - } - - /** - * Gets the table entry for the given segment and hash - */ - @SuppressWarnings("unchecked") - static final <K,V> HashEntry<K,V> entryForHash(Segment<K,V> seg, int h) { - HashEntry<K,V>[] tab; - return (seg == null || (tab = seg.table) == null) ? null : - (HashEntry<K,V>) UNSAFE.getObjectVolatile - (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE); - } - - /* ---------------- Public operations -------------- */ - - /** - * Creates a new, empty map with the specified initial - * capacity, load factor and concurrency level. - * - * @param initialCapacity the initial capacity. The implementation - * performs internal sizing to accommodate this many elements. - * @param loadFactor the load factor threshold, used to control resizing. - * Resizing may be performed when the average number of elements per - * bin exceeds this threshold. - * @param concurrencyLevel the estimated number of concurrently - * updating threads. The implementation performs internal sizing - * to try to accommodate this many threads. - * @throws IllegalArgumentException if the initial capacity is - * negative or the load factor or concurrencyLevel are - * nonpositive. - */ - @SuppressWarnings("unchecked") - public ConcurrentHashMap(int initialCapacity, - float loadFactor, int concurrencyLevel) { - if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) - throw new IllegalArgumentException(); - if (concurrencyLevel > MAX_SEGMENTS) - concurrencyLevel = MAX_SEGMENTS; - // Find power-of-two sizes best matching arguments - int sshift = 0; - int ssize = 1; - while (ssize < concurrencyLevel) { - ++sshift; - ssize <<= 1; - } - this.segmentShift = 32 - sshift; - this.segmentMask = ssize - 1; - if (initialCapacity > MAXIMUM_CAPACITY) - initialCapacity = MAXIMUM_CAPACITY; - int c = initialCapacity / ssize; - if (c * ssize < initialCapacity) - ++c; - int cap = MIN_SEGMENT_TABLE_CAPACITY; - while (cap < c) - cap <<= 1; - // create segments and segments[0] - Segment<K,V> s0 = - new Segment<K,V>(loadFactor, (int)(cap * loadFactor), - (HashEntry<K,V>[])new HashEntry[cap]); - Segment<K,V>[] ss = (Segment<K,V>[])new Segment[ssize]; - UNSAFE.putOrderedObject(ss, SBASE, s0); // ordered write of segments[0] - this.segments = ss; - } - - /** - * Creates a new, empty map with the specified initial capacity - * and load factor and with the default concurrencyLevel (16). - * - * @param initialCapacity The implementation performs internal - * sizing to accommodate this many elements. - * @param loadFactor the load factor threshold, used to control resizing. - * Resizing may be performed when the average number of elements per - * bin exceeds this threshold. - * @throws IllegalArgumentException if the initial capacity of - * elements is negative or the load factor is nonpositive - * - * @since 1.6 - */ - public ConcurrentHashMap(int initialCapacity, float loadFactor) { - this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL); - } - - /** - * Creates a new, empty map with the specified initial capacity, - * and with default load factor (0.75) and concurrencyLevel (16). - * - * @param initialCapacity the initial capacity. The implementation - * performs internal sizing to accommodate this many elements. - * @throws IllegalArgumentException if the initial capacity of - * elements is negative. - */ - public ConcurrentHashMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL); - } - - /** - * Creates a new, empty map with a default initial capacity (16), - * load factor (0.75) and concurrencyLevel (16). - */ - public ConcurrentHashMap() { - this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL); - } - - /** - * Creates a new map with the same mappings as the given map. - * The map is created with a capacity of 1.5 times the number - * of mappings in the given map or 16 (whichever is greater), - * and a default load factor (0.75) and concurrencyLevel (16). - * - * @param m the map - */ - public ConcurrentHashMap(Map<? extends K, ? extends V> m) { - this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, - DEFAULT_INITIAL_CAPACITY), - DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL); - putAll(m); - } - - /** - * Returns <tt>true</tt> if this map contains no key-value mappings. - * - * @return <tt>true</tt> if this map contains no key-value mappings - */ - public boolean isEmpty() { - /* - * Sum per-segment modCounts to avoid mis-reporting when - * elements are concurrently added and removed in one segment - * while checking another, in which case the table was never - * actually empty at any point. (The sum ensures accuracy up - * through at least 1<<31 per-segment modifications before - * recheck.) Methods size() and containsValue() use similar - * constructions for stability checks. - */ - long sum = 0L; - final Segment<K,V>[] segments = this.segments; - for (int j = 0; j < segments.length; ++j) { - Segment<K,V> seg = segmentAt(segments, j); - if (seg != null) { - if (seg.count != 0) - return false; - sum += seg.modCount; - } - } - if (sum != 0L) { // recheck unless no modifications - for (int j = 0; j < segments.length; ++j) { - Segment<K,V> seg = segmentAt(segments, j); - if (seg != null) { - if (seg.count != 0) - return false; - sum -= seg.modCount; - } - } - if (sum != 0L) - return false; - } - return true; - } - - /** - * Returns the number of key-value mappings in this map. If the - * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns - * <tt>Integer.MAX_VALUE</tt>. - * - * @return the number of key-value mappings in this map - */ - public int size() { - // Try a few times to get accurate count. On failure due to - // continuous async changes in table, resort to locking. - final Segment<K,V>[] segments = this.segments; - int size; - boolean overflow; // true if size overflows 32 bits - long sum; // sum of modCounts - long last = 0L; // previous sum - int retries = -1; // first iteration isn't retry - try { - for (;;) { - if (retries++ == RETRIES_BEFORE_LOCK) { - for (int j = 0; j < segments.length; ++j) - ensureSegment(j).lock(); // force creation - } - sum = 0L; - size = 0; - overflow = false; - for (int j = 0; j < segments.length; ++j) { - Segment<K,V> seg = segmentAt(segments, j); - if (seg != null) { - sum += seg.modCount; - int c = seg.count; - if (c < 0 || (size += c) < 0) - overflow = true; - } - } - if (sum == last) - break; - last = sum; - } - } finally { - if (retries > RETRIES_BEFORE_LOCK) { - for (int j = 0; j < segments.length; ++j) - segmentAt(segments, j).unlock(); - } - } - return overflow ? Integer.MAX_VALUE : size; - } - - /** - * Returns the value to which the specified key is mapped, - * or {@code null} if this map contains no mapping for the key. - * - * <p>More formally, if this map contains a mapping from a key - * {@code k} to a value {@code v} such that {@code key.equals(k)}, - * then this method returns {@code v}; otherwise it returns - * {@code null}. (There can be at most one such mapping.) - * - * @throws NullPointerException if the specified key is null - */ - public V get(Object key) { - Segment<K,V> s; // manually integrate access methods to reduce overhead - HashEntry<K,V>[] tab; - int h = hash(key.hashCode()); - long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE; - if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null && - (tab = s.table) != null) { - for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile - (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE); - e != null; e = e.next) { - K k; - if ((k = e.key) == key || (e.hash == h && key.equals(k))) - return e.value; - } - } - return null; - } - - /** - * Tests if the specified object is a key in this table. - * - * @param key possible key - * @return <tt>true</tt> if and only if the specified object - * is a key in this table, as determined by the - * <tt>equals</tt> method; <tt>false</tt> otherwise. - * @throws NullPointerException if the specified key is null - */ - @SuppressWarnings("unchecked") - public boolean containsKey(Object key) { - Segment<K,V> s; // same as get() except no need for volatile value read - HashEntry<K,V>[] tab; - int h = hash(key.hashCode()); - long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE; - if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null && - (tab = s.table) != null) { - for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile - (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE); - e != null; e = e.next) { - K k; - if ((k = e.key) == key || (e.hash == h && key.equals(k))) - return true; - } - } - return false; - } - - /** - * Returns <tt>true</tt> if this map maps one or more keys to the - * specified value. Note: This method requires a full internal - * traversal of the hash table, and so is much slower than - * method <tt>containsKey</tt>. - * - * @param value value whose presence in this map is to be tested - * @return <tt>true</tt> if this map maps one or more keys to the - * specified value - * @throws NullPointerException if the specified value is null - */ - public boolean containsValue(Object value) { - // Same idea as size() - if (value == null) - throw new NullPointerException(); - final Segment<K,V>[] segments = this.segments; - boolean found = false; - long last = 0; - int retries = -1; - try { - outer: for (;;) { - if (retries++ == RETRIES_BEFORE_LOCK) { - for (int j = 0; j < segments.length; ++j) - ensureSegment(j).lock(); // force creation - } - long hashSum = 0L; - int sum = 0; - for (int j = 0; j < segments.length; ++j) { - HashEntry<K,V>[] tab; - Segment<K,V> seg = segmentAt(segments, j); - if (seg != null && (tab = seg.table) != null) { - for (int i = 0 ; i < tab.length; i++) { - HashEntry<K,V> e; - for (e = entryAt(tab, i); e != null; e = e.next) { - V v = e.value; - if (v != null && value.equals(v)) { - found = true; - break outer; - } - } - } - sum += seg.modCount; - } - } - if (retries > 0 && sum == last) - break; - last = sum; - } - } finally { - if (retries > RETRIES_BEFORE_LOCK) { - for (int j = 0; j < segments.length; ++j) - segmentAt(segments, j).unlock(); - } - } - return found; - } - - /** - * Legacy method testing if some key maps into the specified value - * in this table. This method is identical in functionality to - * {@link #containsValue}, and exists solely to ensure - * full compatibility with class {@link java.util.Hashtable}, - * which supported this method prior to introduction of the - * Java Collections framework. - - * @param value a value to search for - * @return <tt>true</tt> if and only if some key maps to the - * <tt>value</tt> argument in this table as - * determined by the <tt>equals</tt> method; - * <tt>false</tt> otherwise - * @throws NullPointerException if the specified value is null - */ - public boolean contains(Object value) { - return containsValue(value); - } - - /** - * Maps the specified key to the specified value in this table. - * Neither the key nor the value can be null. - * - * <p> The value can be retrieved by calling the <tt>get</tt> method - * with a key that is equal to the original key. - * - * @param key key with which the specified value is to be associated - * @param value value to be associated with the specified key - * @return the previous value associated with <tt>key</tt>, or - * <tt>null</tt> if there was no mapping for <tt>key</tt> - * @throws NullPointerException if the specified key or value is null - */ - @SuppressWarnings("unchecked") - public V put(K key, V value) { - Segment<K,V> s; - if (value == null) - throw new NullPointerException(); - int hash = hash(key.hashCode()); - int j = (hash >>> segmentShift) & segmentMask; - if ((s = (Segment<K,V>)UNSAFE.getObject // nonvolatile; recheck - (segments, (j << SSHIFT) + SBASE)) == null) // in ensureSegment - s = ensureSegment(j); - return s.put(key, hash, value, false); - } - - /** - * {@inheritDoc} - * - * @return the previous value associated with the specified key, - * or <tt>null</tt> if there was no mapping for the key - * @throws NullPointerException if the specified key or value is null - */ - @SuppressWarnings("unchecked") - public V putIfAbsent(K key, V value) { - Segment<K,V> s; - if (value == null) - throw new NullPointerException(); - int hash = hash(key.hashCode()); - int j = (hash >>> segmentShift) & segmentMask; - if ((s = (Segment<K,V>)UNSAFE.getObject - (segments, (j << SSHIFT) + SBASE)) == null) - s = ensureSegment(j); - return s.put(key, hash, value, true); - } - - /** - * Copies all of the mappings from the specified map to this one. - * These mappings replace any mappings that this map had for any of the - * keys currently in the specified map. - * - * @param m mappings to be stored in this map - */ - public void putAll(Map<? extends K, ? extends V> m) { - for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) - put(e.getKey(), e.getValue()); - } - - /** - * Removes the key (and its corresponding value) from this map. - * This method does nothing if the key is not in the map. - * - * @param key the key that needs to be removed - * @return the previous value associated with <tt>key</tt>, or - * <tt>null</tt> if there was no mapping for <tt>key</tt> - * @throws NullPointerException if the specified key is null - */ - public V remove(Object key) { - int hash = hash(key.hashCode()); - Segment<K,V> s = segmentForHash(hash); - return s == null ? null : s.remove(key, hash, null); - } - - /** - * {@inheritDoc} - * - * @throws NullPointerException if the specified key is null - */ - public boolean remove(Object key, Object value) { - int hash = hash(key.hashCode()); - Segment<K,V> s; - return value != null && (s = segmentForHash(hash)) != null && - s.remove(key, hash, value) != null; - } - - /** - * {@inheritDoc} - * - * @throws NullPointerException if any of the arguments are null - */ - public boolean replace(K key, V oldValue, V newValue) { - int hash = hash(key.hashCode()); - if (oldValue == null || newValue == null) - throw new NullPointerException(); - Segment<K,V> s = segmentForHash(hash); - return s != null && s.replace(key, hash, oldValue, newValue); - } - - /** - * {@inheritDoc} - * - * @return the previous value associated with the specified key, - * or <tt>null</tt> if there was no mapping for the key - * @throws NullPointerException if the specified key or value is null - */ - public V replace(K key, V value) { - int hash = hash(key.hashCode()); - if (value == null) - throw new NullPointerException(); - Segment<K,V> s = segmentForHash(hash); - return s == null ? null : s.replace(key, hash, value); - } - - /** - * Removes all of the mappings from this map. - */ - public void clear() { - final Segment<K,V>[] segments = this.segments; - for (int j = 0; j < segments.length; ++j) { - Segment<K,V> s = segmentAt(segments, j); - if (s != null) - s.clear(); - } - } - - /** - * 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. The set supports element - * removal, which removes the corresponding mapping from this map, - * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, - * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> - * operations. It does not support the <tt>add</tt> or - * <tt>addAll</tt> operations. - * - * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator - * that will never throw {@link ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. - */ - public Set<K> keySet() { - Set<K> ks = keySet; - return (ks != null) ? ks : (keySet = new KeySet()); - } - - /** - * 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. The collection - * supports element removal, which removes the corresponding - * mapping from this map, via the <tt>Iterator.remove</tt>, - * <tt>Collection.remove</tt>, <tt>removeAll</tt>, - * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not - * support the <tt>add</tt> or <tt>addAll</tt> operations. - * - * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator - * that will never throw {@link ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. - */ - public Collection<V> values() { - Collection<V> vs = values; - return (vs != null) ? vs : (values = new Values()); - } - - /** - * 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. The set supports element - * removal, which removes the corresponding mapping from the map, - * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, - * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> - * operations. It does not support the <tt>add</tt> or - * <tt>addAll</tt> operations. - * - * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator - * that will never throw {@link ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. - */ - public Set<Map.Entry<K,V>> entrySet() { - Set<Map.Entry<K,V>> es = entrySet; - return (es != null) ? es : (entrySet = new EntrySet()); - } - - /** - * Returns an enumeration of the keys in this table. - * - * @return an enumeration of the keys in this table - * @see #keySet() - */ - public Enumeration<K> keys() { - return new KeyIterator(); - } - - /** - * Returns an enumeration of the values in this table. - * - * @return an enumeration of the values in this table - * @see #values() - */ - public Enumeration<V> elements() { - return new ValueIterator(); - } - - /* ---------------- Iterator Support -------------- */ - - abstract class HashIterator { - int nextSegmentIndex; - int nextTableIndex; - HashEntry<K,V>[] currentTable; - HashEntry<K, V> nextEntry; - HashEntry<K, V> lastReturned; - - HashIterator() { - nextSegmentIndex = segments.length - 1; - nextTableIndex = -1; - advance(); - } - - /** - * Set nextEntry to first node of next non-empty table - * (in backwards order, to simplify checks). - */ - final void advance() { - for (;;) { - if (nextTableIndex >= 0) { - if ((nextEntry = entryAt(currentTable, - nextTableIndex--)) != null) - break; - } - else if (nextSegmentIndex >= 0) { - Segment<K,V> seg = segmentAt(segments, nextSegmentIndex--); - if (seg != null && (currentTable = seg.table) != null) - nextTableIndex = currentTable.length - 1; - } - else - break; - } - } - - final HashEntry<K,V> nextEntry() { - HashEntry<K,V> e = nextEntry; - if (e == null) - throw new NoSuchElementException(); - lastReturned = e; // cannot assign until after null check - if ((nextEntry = e.next) == null) - advance(); - return e; - } - - public final boolean hasNext() { return nextEntry != null; } - public final boolean hasMoreElements() { return nextEntry != null; } - - public final void remove() { - if (lastReturned == null) - throw new IllegalStateException(); - ConcurrentHashMap.this.remove(lastReturned.key); - lastReturned = null; - } - } - - final class KeyIterator - extends HashIterator - implements Iterator<K>, Enumeration<K> - { - public final K next() { return super.nextEntry().key; } - public final K nextElement() { return super.nextEntry().key; } - } - - final class ValueIterator - extends HashIterator - implements Iterator<V>, Enumeration<V> - { - public final V next() { return super.nextEntry().value; } - public final V nextElement() { return super.nextEntry().value; } - } - - /** - * Custom Entry class used by EntryIterator.next(), that relays - * setValue changes to the underlying map. - */ - final class WriteThroughEntry - extends AbstractMap.SimpleEntry<K,V> - { - WriteThroughEntry(K k, V v) { - super(k,v); - } - - /** - * Set our entry's value and write through to the map. The - * value to return is somewhat arbitrary here. Since a - * WriteThroughEntry does not necessarily track asynchronous - * changes, the most recent "previous" value could be - * different from what we return (or could even have been - * removed in which case the put will re-establish). We do not - * and cannot guarantee more. - */ - public V setValue(V value) { - if (value == null) throw new NullPointerException(); - V v = super.setValue(value); - ConcurrentHashMap.this.put(getKey(), value); - return v; - } - } - - final class EntryIterator - extends HashIterator - implements Iterator<Entry<K,V>> - { - public Map.Entry<K,V> next() { - HashEntry<K,V> e = super.nextEntry(); - return new WriteThroughEntry(e.key, e.value); - } - } - - final class KeySet extends AbstractSet<K> { - public Iterator<K> iterator() { - return new KeyIterator(); - } - public int size() { - return ConcurrentHashMap.this.size(); - } - public boolean isEmpty() { - return ConcurrentHashMap.this.isEmpty(); - } - public boolean contains(Object o) { - return ConcurrentHashMap.this.containsKey(o); - } - public boolean remove(Object o) { - return ConcurrentHashMap.this.remove(o) != null; - } - public void clear() { - ConcurrentHashMap.this.clear(); - } - } - - final class Values extends AbstractCollection<V> { - public Iterator<V> iterator() { - return new ValueIterator(); - } - public int size() { - return ConcurrentHashMap.this.size(); - } - public boolean isEmpty() { - return ConcurrentHashMap.this.isEmpty(); - } - public boolean contains(Object o) { - return ConcurrentHashMap.this.containsValue(o); - } - public void clear() { - ConcurrentHashMap.this.clear(); - } - } - - final class EntrySet extends AbstractSet<Map.Entry<K,V>> { - public Iterator<Map.Entry<K,V>> iterator() { - return new EntryIterator(); - } - public boolean contains(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry<?,?> e = (Map.Entry<?,?>)o; - V v = ConcurrentHashMap.this.get(e.getKey()); - return v != null && v.equals(e.getValue()); - } - public boolean remove(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry<?,?> e = (Map.Entry<?,?>)o; - return ConcurrentHashMap.this.remove(e.getKey(), e.getValue()); - } - public int size() { - return ConcurrentHashMap.this.size(); - } - public boolean isEmpty() { - return ConcurrentHashMap.this.isEmpty(); - } - public void clear() { - ConcurrentHashMap.this.clear(); - } - } - - /* ---------------- Serialization Support -------------- */ - - /** - * Save the state of the <tt>ConcurrentHashMap</tt> instance to a - * stream (i.e., serialize it). - * @param s the stream - * @serialData - * the key (Object) and value (Object) - * for each key-value mapping, followed by a null pair. - * The key-value mappings are emitted in no particular order. - */ - private void writeObject(java.io.ObjectOutputStream s) throws IOException { - // force all segments for serialization compatibility - for (int k = 0; k < segments.length; ++k) - ensureSegment(k); - s.defaultWriteObject(); - - final Segment<K,V>[] segments = this.segments; - for (int k = 0; k < segments.length; ++k) { - Segment<K,V> seg = segmentAt(segments, k); - seg.lock(); - try { - HashEntry<K,V>[] tab = seg.table; - for (int i = 0; i < tab.length; ++i) { - HashEntry<K,V> e; - for (e = entryAt(tab, i); e != null; e = e.next) { - s.writeObject(e.key); - s.writeObject(e.value); - } - } - } finally { - seg.unlock(); - } - } - s.writeObject(null); - s.writeObject(null); - } - - /** - * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a - * stream (i.e., deserialize it). - * @param s the stream - */ - @SuppressWarnings("unchecked") - private void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject(); - - // Re-initialize segments to be minimally sized, and let grow. - int cap = MIN_SEGMENT_TABLE_CAPACITY; - final Segment<K,V>[] segments = this.segments; - for (int k = 0; k < segments.length; ++k) { - Segment<K,V> seg = segments[k]; - if (seg != null) { - seg.threshold = (int)(cap * seg.loadFactor); - seg.table = (HashEntry<K,V>[]) new HashEntry[cap]; - } - } - - // Read the keys and values, and put the mappings in the table - for (;;) { - K key = (K) s.readObject(); - V value = (V) s.readObject(); - if (key == null) - break; - put(key, value); - } - } - - // Unsafe mechanics - private static final sun.misc.Unsafe UNSAFE; - private static final long SBASE; - private static final int SSHIFT; - private static final long TBASE; - private static final int TSHIFT; - - static { - int ss, ts; - try { - UNSAFE = sun.misc.Unsafe.getUnsafe(); - Class tc = HashEntry[].class; - Class sc = Segment[].class; - TBASE = UNSAFE.arrayBaseOffset(tc); - SBASE = UNSAFE.arrayBaseOffset(sc); - ts = UNSAFE.arrayIndexScale(tc); - ss = UNSAFE.arrayIndexScale(sc); - } catch (Exception e) { - throw new Error(e); - } - if ((ss & (ss-1)) != 0 || (ts & (ts-1)) != 0) - throw new Error("data type scale not a power of two"); - SSHIFT = 31 - Integer.numberOfLeadingZeros(ss); - TSHIFT = 31 - Integer.numberOfLeadingZeros(ts); - } - -} diff --git a/notes/src/HashMap.java b/notes/src/HashMap.java deleted file mode 100644 index 5afaa09c..00000000 --- a/notes/src/HashMap.java +++ /dev/null @@ -1,931 +0,0 @@ -package java.util; -import java.io.*; - -public class HashMap<K,V> - extends AbstractMap<K,V> - implements Map<K,V>, Cloneable, Serializable -{ - - /** - * The default initial capacity - MUST be a power of two. - */ - static final int DEFAULT_INITIAL_CAPACITY = 16; - - /** - * The maximum capacity, used if a higher value is implicitly specified - * by either of the constructors with arguments. - * MUST be a power of two <= 1<<30. - */ - static final int MAXIMUM_CAPACITY = 1 << 30; - - /** - * The load factor used when none specified in constructor. - */ - static final float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * The table, resized as necessary. Length MUST Always be a power of two. - */ - transient Entry[] table; - - /** - * The number of key-value mappings contained in this map. - */ - transient int size; - - /** - * The next size value at which to resize (capacity * load factor). - * @serial - */ - int threshold; - - /** - * The load factor for the hash table. - * - * @serial - */ - final float loadFactor; - - /** - * The number of times this HashMap has been structurally modified - * Structural modifications are those that change the number of mappings in - * the HashMap or otherwise modify its internal structure (e.g., - * rehash). This field is used to make iterators on Collection-views of - * the HashMap fail-fast. (See ConcurrentModificationException). - */ - transient int modCount; - - /** - * Constructs an empty <tt>HashMap</tt> with the specified initial - * capacity and load factor. - * - * @param initialCapacity the initial capacity - * @param loadFactor the load factor - * @throws IllegalArgumentException if the initial capacity is negative - * or the load factor is nonpositive - */ - public HashMap(int initialCapacity, float loadFactor) { - if (initialCapacity < 0) - throw new IllegalArgumentException("Illegal initial capacity: " + - initialCapacity); - if (initialCapacity > MAXIMUM_CAPACITY) - initialCapacity = MAXIMUM_CAPACITY; - if (loadFactor <= 0 || Float.isNaN(loadFactor)) - throw new IllegalArgumentException("Illegal load factor: " + - loadFactor); - - // Find a power of 2 >= initialCapacity - int capacity = 1; - while (capacity < initialCapacity) - capacity <<= 1; - - this.loadFactor = loadFactor; - threshold = (int)(capacity * loadFactor); - table = new Entry[capacity]; - init(); - } - - /** - * Constructs an empty <tt>HashMap</tt> with the specified initial - * capacity and the default load factor (0.75). - * - * @param initialCapacity the initial capacity. - * @throws IllegalArgumentException if the initial capacity is negative. - */ - public HashMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR); - } - - /** - * Constructs an empty <tt>HashMap</tt> with the default initial capacity - * (16) and the default load factor (0.75). - */ - public HashMap() { - this.loadFactor = DEFAULT_LOAD_FACTOR; - threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); - table = new Entry[DEFAULT_INITIAL_CAPACITY]; - init(); - } - - /** - * Constructs a new <tt>HashMap</tt> with the same mappings as the - * specified <tt>Map</tt>. The <tt>HashMap</tt> is created with - * default load factor (0.75) and an initial capacity sufficient to - * hold the mappings in the specified <tt>Map</tt>. - * - * @param m the map whose mappings are to be placed in this map - * @throws NullPointerException if the specified map is null - */ - public HashMap(Map<? extends K, ? extends V> m) { - this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, - DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); - putAllForCreate(m); - } - - // internal utilities - - /** - * Initialization hook for subclasses. This method is called - * in all constructors and pseudo-constructors (clone, readObject) - * after HashMap has been initialized but before any entries have - * been inserted. (In the absence of this method, readObject would - * require explicit knowledge of subclasses.) - */ - void init() { - } - - /** - * Applies a supplemental hash function to a given hashCode, which - * defends against poor quality hash functions. This is critical - * because HashMap uses power-of-two length hash tables, that - * otherwise encounter collisions for hashCodes that do not differ - * in lower bits. Note: Null keys always map to hash 0, thus index 0. - */ - static int hash(int h) { - // This function ensures that hashCodes that differ only by - // constant multiples at each bit position have a bounded - // number of collisions (approximately 8 at default load factor). - h ^= (h >>> 20) ^ (h >>> 12); - return h ^ (h >>> 7) ^ (h >>> 4); - } - - /** - * Returns index for hash code h. - */ - static int indexFor(int h, int length) { - return h & (length-1); - } - - /** - * Returns the number of key-value mappings in this map. - * - * @return the number of key-value mappings in this map - */ - public int size() { - return size; - } - - /** - * Returns <tt>true</tt> if this map contains no key-value mappings. - * - * @return <tt>true</tt> if this map contains no key-value mappings - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Returns the value to which the specified key is mapped, - * or {@code null} if this map contains no mapping for the key. - * - * <p>More formally, if this map contains a mapping from a key - * {@code k} to a value {@code v} such that {@code (key==null ? k==null : - * key.equals(k))}, then this method returns {@code v}; otherwise - * it returns {@code null}. (There can be at most one such mapping.) - * - * <p>A return value of {@code null} does not <i>necessarily</i> - * indicate that the map contains no mapping for the key; it's also - * possible that the map explicitly maps the key to {@code null}. - * The {@link #containsKey containsKey} operation may be used to - * distinguish these two cases. - * - * @see #put(Object, Object) - */ - public V get(Object key) { - if (key == null) - return getForNullKey(); - int hash = hash(key.hashCode()); - for (Entry<K,V> e = table[indexFor(hash, table.length)]; - e != null; - e = e.next) { - Object k; - if (e.hash == hash && ((k = e.key) == key || key.equals(k))) - return e.value; - } - return null; - } - - /** - * Offloaded version of get() to look up null keys. Null keys map - * to index 0. This null case is split out into separate methods - * for the sake of performance in the two most commonly used - * operations (get and put), but incorporated with conditionals in - * others. - */ - private V getForNullKey() { - for (Entry<K,V> e = table[0]; e != null; e = e.next) { - if (e.key == null) - return e.value; - } - return null; - } - - /** - * Returns <tt>true</tt> if this map contains a mapping for the - * specified key. - * - * @param key The key whose presence in this map is to be tested - * @return <tt>true</tt> if this map contains a mapping for the specified - * key. - */ - public boolean containsKey(Object key) { - return getEntry(key) != null; - } - - /** - * Returns the entry associated with the specified key in the - * HashMap. Returns null if the HashMap contains no mapping - * for the key. - */ - final Entry<K,V> getEntry(Object key) { - int hash = (key == null) ? 0 : hash(key.hashCode()); - for (Entry<K,V> e = table[indexFor(hash, table.length)]; - e != null; - e = e.next) { - Object k; - if (e.hash == hash && - ((k = e.key) == key || (key != null && key.equals(k)))) - return e; - } - return null; - } - - - /** - * Associates the specified value with the specified key in this map. - * If the map previously contained a mapping for the key, the old - * value is replaced. - * - * @param key key with which the specified value is to be associated - * @param value value to be associated with the specified key - * @return the previous value associated with <tt>key</tt>, or - * <tt>null</tt> if there was no mapping for <tt>key</tt>. - * (A <tt>null</tt> return can also indicate that the map - * previously associated <tt>null</tt> with <tt>key</tt>.) - */ - public V put(K key, V value) { - if (key == null) - return putForNullKey(value); - int hash = hash(key.hashCode()); - int i = indexFor(hash, table.length); - for (Entry<K,V> e = table[i]; e != null; e = e.next) { - Object k; - if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { - V oldValue = e.value; - e.value = value; - e.recordAccess(this); - return oldValue; - } - } - - modCount++; - addEntry(hash, key, value, i); - return null; - } - - /** - * Offloaded version of put for null keys - */ - private V putForNullKey(V value) { - for (Entry<K,V> e = table[0]; e != null; e = e.next) { - if (e.key == null) { - V oldValue = e.value; - e.value = value; - e.recordAccess(this); - return oldValue; - } - } - modCount++; - addEntry(0, null, value, 0); - return null; - } - - /** - * This method is used instead of put by constructors and - * pseudoconstructors (clone, readObject). It does not resize the table, - * check for comodification, etc. It calls createEntry rather than - * addEntry. - */ - private void putForCreate(K key, V value) { - int hash = (key == null) ? 0 : hash(key.hashCode()); - int i = indexFor(hash, table.length); - - /** - * Look for preexisting entry for key. This will never happen for - * clone or deserialize. It will only happen for construction if the - * input Map is a sorted map whose ordering is inconsistent w/ equals. - */ - for (Entry<K,V> e = table[i]; e != null; e = e.next) { - Object k; - if (e.hash == hash && - ((k = e.key) == key || (key != null && key.equals(k)))) { - e.value = value; - return; - } - } - - createEntry(hash, key, value, i); - } - - private void putAllForCreate(Map<? extends K, ? extends V> m) { - for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) - putForCreate(e.getKey(), e.getValue()); - } - - /** - * Rehashes the contents of this map into a new array with a - * larger capacity. This method is called automatically when the - * number of keys in this map reaches its threshold. - * - * If current capacity is MAXIMUM_CAPACITY, this method does not - * resize the map, but sets threshold to Integer.MAX_VALUE. - * This has the effect of preventing future calls. - * - * @param newCapacity the new capacity, MUST be a power of two; - * must be greater than current capacity unless current - * capacity is MAXIMUM_CAPACITY (in which case value - * is irrelevant). - */ - void resize(int newCapacity) { - Entry[] oldTable = table; - int oldCapacity = oldTable.length; - if (oldCapacity == MAXIMUM_CAPACITY) { - threshold = Integer.MAX_VALUE; - return; - } - - Entry[] newTable = new Entry[newCapacity]; - transfer(newTable); - table = newTable; - threshold = (int)(newCapacity * loadFactor); - } - - /** - * Transfers all entries from current table to newTable. - */ - void transfer(Entry[] newTable) { - Entry[] src = table; - int newCapacity = newTable.length; - for (int j = 0; j < src.length; j++) { - Entry<K,V> e = src[j]; - if (e != null) { - src[j] = null; - do { - Entry<K,V> next = e.next; - int i = indexFor(e.hash, newCapacity); - e.next = newTable[i]; - newTable[i] = e; - e = next; - } while (e != null); - } - } - } - - /** - * Copies all of the mappings from the specified map to this map. - * These mappings will replace any mappings that this map had for - * any of the keys currently in the specified map. - * - * @param m mappings to be stored in this map - * @throws NullPointerException if the specified map is null - */ - public void putAll(Map<? extends K, ? extends V> m) { - int numKeysToBeAdded = m.size(); - if (numKeysToBeAdded == 0) - return; - - /* - * Expand the map if the map if the number of mappings to be added - * is greater than or equal to threshold. This is conservative; the - * obvious condition is (m.size() + size) >= threshold, but this - * condition could result in a map with twice the appropriate capacity, - * if the keys to be added overlap with the keys already in this map. - * By using the conservative calculation, we subject ourself - * to at most one extra resize. - */ - if (numKeysToBeAdded > threshold) { - int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1); - if (targetCapacity > MAXIMUM_CAPACITY) - targetCapacity = MAXIMUM_CAPACITY; - int newCapacity = table.length; - while (newCapacity < targetCapacity) - newCapacity <<= 1; - if (newCapacity > table.length) - resize(newCapacity); - } - - for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) - put(e.getKey(), e.getValue()); - } - - /** - * Removes the mapping for the specified key from this map if present. - * - * @param key key whose mapping is to be removed from the map - * @return the previous value associated with <tt>key</tt>, or - * <tt>null</tt> if there was no mapping for <tt>key</tt>. - * (A <tt>null</tt> return can also indicate that the map - * previously associated <tt>null</tt> with <tt>key</tt>.) - */ - public V remove(Object key) { - Entry<K,V> e = removeEntryForKey(key); - return (e == null ? null : e.value); - } - - /** - * Removes and returns the entry associated with the specified key - * in the HashMap. Returns null if the HashMap contains no mapping - * for this key. - */ - final Entry<K,V> removeEntryForKey(Object key) { - int hash = (key == null) ? 0 : hash(key.hashCode()); - int i = indexFor(hash, table.length); - Entry<K,V> prev = table[i]; - Entry<K,V> e = prev; - - while (e != null) { - Entry<K,V> next = e.next; - Object k; - if (e.hash == hash && - ((k = e.key) == key || (key != null && key.equals(k)))) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - e.recordRemoval(this); - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Special version of remove for EntrySet. - */ - final Entry<K,V> removeMapping(Object o) { - if (!(o instanceof Map.Entry)) - return null; - - Map.Entry<K,V> entry = (Map.Entry<K,V>) o; - Object key = entry.getKey(); - int hash = (key == null) ? 0 : hash(key.hashCode()); - int i = indexFor(hash, table.length); - Entry<K,V> prev = table[i]; - Entry<K,V> e = prev; - - while (e != null) { - Entry<K,V> next = e.next; - if (e.hash == hash && e.equals(entry)) { - modCount++; - size--; - if (prev == e) - table[i] = next; - else - prev.next = next; - e.recordRemoval(this); - return e; - } - prev = e; - e = next; - } - - return e; - } - - /** - * Removes all of the mappings from this map. - * The map will be empty after this call returns. - */ - public void clear() { - modCount++; - Entry[] tab = table; - for (int i = 0; i < tab.length; i++) - tab[i] = null; - size = 0; - } - - /** - * Returns <tt>true</tt> if this map maps one or more keys to the - * specified value. - * - * @param value value whose presence in this map is to be tested - * @return <tt>true</tt> if this map maps one or more keys to the - * specified value - */ - public boolean containsValue(Object value) { - if (value == null) - return containsNullValue(); - - Entry[] tab = table; - for (int i = 0; i < tab.length ; i++) - for (Entry e = tab[i] ; e != null ; e = e.next) - if (value.equals(e.value)) - return true; - return false; - } - - /** - * Special-case code for containsValue with null argument - */ - private boolean containsNullValue() { - Entry[] tab = table; - for (int i = 0; i < tab.length ; i++) - for (Entry e = tab[i] ; e != null ; e = e.next) - if (e.value == null) - return true; - return false; - } - - /** - * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and - * values themselves are not cloned. - * - * @return a shallow copy of this map - */ - public Object clone() { - HashMap<K,V> result = null; - try { - result = (HashMap<K,V>)super.clone(); - } catch (CloneNotSupportedException e) { - // assert false; - } - result.table = new Entry[table.length]; - result.entrySet = null; - result.modCount = 0; - result.size = 0; - result.init(); - result.putAllForCreate(this); - - return result; - } - - static class Entry<K,V> implements Map.Entry<K,V> { - final K key; - V value; - Entry<K,V> next; - final int hash; - - /** - * Creates new entry. - */ - Entry(int h, K k, V v, Entry<K,V> n) { - value = v; - next = n; - key = k; - hash = h; - } - - public final K getKey() { - return key; - } - - public final V getValue() { - return value; - } - - public final V setValue(V newValue) { - V oldValue = value; - value = newValue; - return oldValue; - } - - public final boolean equals(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry e = (Map.Entry)o; - Object k1 = getKey(); - Object k2 = e.getKey(); - if (k1 == k2 || (k1 != null && k1.equals(k2))) { - Object v1 = getValue(); - Object v2 = e.getValue(); - if (v1 == v2 || (v1 != null && v1.equals(v2))) - return true; - } - return false; - } - - public final int hashCode() { - return (key==null ? 0 : key.hashCode()) ^ - (value==null ? 0 : value.hashCode()); - } - - public final String toString() { - return getKey() + "=" + getValue(); - } - - /** - * This method is invoked whenever the value in an entry is - * overwritten by an invocation of put(k,v) for a key k that's already - * in the HashMap. - */ - void recordAccess(HashMap<K,V> m) { - } - - /** - * This method is invoked whenever the entry is - * removed from the table. - */ - void recordRemoval(HashMap<K,V> m) { - } - } - - /** - * Adds a new entry with the specified key, value and hash code to - * the specified bucket. It is the responsibility of this - * method to resize the table if appropriate. - * - * Subclass overrides this to alter the behavior of put method. - */ - void addEntry(int hash, K key, V value, int bucketIndex) { - Entry<K,V> e = table[bucketIndex]; - table[bucketIndex] = new Entry<>(hash, key, value, e); - if (size++ >= threshold) - resize(2 * table.length); - } - - /** - * Like addEntry except that this version is used when creating entries - * as part of Map construction or "pseudo-construction" (cloning, - * deserialization). This version needn't worry about resizing the table. - * - * Subclass overrides this to alter the behavior of HashMap(Map), - * clone, and readObject. - */ - void createEntry(int hash, K key, V value, int bucketIndex) { - Entry<K,V> e = table[bucketIndex]; - table[bucketIndex] = new Entry<>(hash, key, value, e); - size++; - } - - private abstract class HashIterator<E> implements Iterator<E> { - Entry<K,V> next; // next entry to return - int expectedModCount; // For fast-fail - int index; // current slot - Entry<K,V> current; // current entry - - HashIterator() { - expectedModCount = modCount; - if (size > 0) { // advance to first entry - Entry[] t = table; - while (index < t.length && (next = t[index++]) == null) - ; - } - } - - public final boolean hasNext() { - return next != null; - } - - final Entry<K,V> nextEntry() { - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - Entry<K,V> e = next; - if (e == null) - throw new NoSuchElementException(); - - if ((next = e.next) == null) { - Entry[] t = table; - while (index < t.length && (next = t[index++]) == null) - ; - } - current = e; - return e; - } - - public void remove() { - if (current == null) - throw new IllegalStateException(); - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - Object k = current.key; - current = null; - HashMap.this.removeEntryForKey(k); - expectedModCount = modCount; - } - - } - - private final class ValueIterator extends HashIterator<V> { - public V next() { - return nextEntry().value; - } - } - - private final class KeyIterator extends HashIterator<K> { - public K next() { - return nextEntry().getKey(); - } - } - - private final class EntryIterator extends HashIterator<Map.Entry<K,V>> { - public Map.Entry<K,V> next() { - return nextEntry(); - } - } - - // Subclass overrides these to alter behavior of views' iterator() method - Iterator<K> newKeyIterator() { - return new KeyIterator(); - } - Iterator<V> newValueIterator() { - return new ValueIterator(); - } - Iterator<Map.Entry<K,V>> newEntryIterator() { - return new EntryIterator(); - } - - - // Views - - private transient Set<Map.Entry<K,V>> entrySet = 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 <tt>remove</tt> operation), the results of - * the iteration are undefined. The set supports element removal, - * which removes the corresponding mapping from the map, via the - * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, - * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> - * operations. It does not support the <tt>add</tt> or <tt>addAll</tt> - * operations. - */ - public Set<K> keySet() { - Set<K> ks = keySet; - return (ks != null ? ks : (keySet = new KeySet())); - } - - private final class KeySet extends AbstractSet<K> { - public Iterator<K> iterator() { - return newKeyIterator(); - } - public int size() { - return size; - } - public boolean contains(Object o) { - return containsKey(o); - } - public boolean remove(Object o) { - return HashMap.this.removeEntryForKey(o) != null; - } - public void clear() { - HashMap.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 <tt>remove</tt> operation), - * the results of the iteration are undefined. The collection - * supports element removal, which removes the corresponding - * mapping from the map, via the <tt>Iterator.remove</tt>, - * <tt>Collection.remove</tt>, <tt>removeAll</tt>, - * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not - * support the <tt>add</tt> or <tt>addAll</tt> operations. - */ - public Collection<V> values() { - Collection<V> vs = values; - return (vs != null ? vs : (values = new Values())); - } - - private final class Values extends AbstractCollection<V> { - public Iterator<V> iterator() { - return newValueIterator(); - } - public int size() { - return size; - } - public boolean contains(Object o) { - return containsValue(o); - } - public void clear() { - HashMap.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 <tt>remove</tt> operation, or through the - * <tt>setValue</tt> operation on a map entry returned by the - * iterator) the results of the iteration are undefined. The set - * supports element removal, which removes the corresponding - * mapping from the map, via the <tt>Iterator.remove</tt>, - * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and - * <tt>clear</tt> operations. It does not support the - * <tt>add</tt> or <tt>addAll</tt> operations. - * - * @return a set view of the mappings contained in this map - */ - public Set<Map.Entry<K,V>> entrySet() { - return entrySet0(); - } - - private Set<Map.Entry<K,V>> entrySet0() { - Set<Map.Entry<K,V>> es = entrySet; - return es != null ? es : (entrySet = new EntrySet()); - } - - private final class EntrySet extends AbstractSet<Map.Entry<K,V>> { - public Iterator<Map.Entry<K,V>> iterator() { - return newEntryIterator(); - } - public boolean contains(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry<K,V> e = (Map.Entry<K,V>) o; - Entry<K,V> candidate = getEntry(e.getKey()); - return candidate != null && candidate.equals(e); - } - public boolean remove(Object o) { - return removeMapping(o) != null; - } - public int size() { - return size; - } - public void clear() { - HashMap.this.clear(); - } - } - - /** - * Save the state of the <tt>HashMap</tt> instance to a stream (i.e., - * serialize it). - * - * @serialData The <i>capacity</i> of the HashMap (the length of the - * bucket array) is emitted (int), followed by the - * <i>size</i> (an int, the number of key-value - * mappings), followed by the key (Object) and value (Object) - * for each key-value mapping. The key-value mappings are - * emitted in no particular order. - */ - private void writeObject(java.io.ObjectOutputStream s) - throws IOException - { - Iterator<Map.Entry<K,V>> i = - (size > 0) ? entrySet0().iterator() : null; - - // Write out the threshold, loadfactor, and any hidden stuff - s.defaultWriteObject(); - - // Write out number of buckets - s.writeInt(table.length); - - // Write out size (number of Mappings) - s.writeInt(size); - - // Write out keys and values (alternating) - if (i != null) { - while (i.hasNext()) { - Map.Entry<K,V> e = i.next(); - s.writeObject(e.getKey()); - s.writeObject(e.getValue()); - } - } - } - - private static final long serialVersionUID = 362498820763181265L; - - /** - * Reconstitute the <tt>HashMap</tt> instance from a stream (i.e., - * deserialize it). - */ - private void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException - { - // Read in the threshold, loadfactor, and any hidden stuff - s.defaultReadObject(); - - // Read in number of buckets and allocate the bucket array; - int numBuckets = s.readInt(); - table = new Entry[numBuckets]; - - init(); // Give subclass a chance to do its thing. - - // Read in size (number of Mappings) - int size = s.readInt(); - - // Read the keys and values, and put the mappings in the HashMap - for (int i=0; i<size; i++) { - K key = (K) s.readObject(); - V value = (V) s.readObject(); - putForCreate(key, value); - } - } - - // These methods are used when serializing HashSets - int capacity() { return table.length; } - float loadFactor() { return loadFactor; } -} diff --git a/notes/src/HashSet.java b/notes/src/HashSet.java deleted file mode 100644 index b2fca169..00000000 --- a/notes/src/HashSet.java +++ /dev/null @@ -1,228 +0,0 @@ -package java.util; - -public class HashSet<E> - extends AbstractSet<E> - implements Set<E>, Cloneable, java.io.Serializable -{ - static final long serialVersionUID = -5024744406713321676L; - - private transient HashMap<E,Object> map; - - // Dummy value to associate with an Object in the backing Map - private static final Object PRESENT = new Object(); - - /** - * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has - * default initial capacity (16) and load factor (0.75). - */ - public HashSet() { - map = new HashMap<>(); - } - - /** - * Constructs a new set containing the elements in the specified - * collection. The <tt>HashMap</tt> is created with default load factor - * (0.75) and an initial capacity sufficient to contain the elements in - * the specified collection. - * - * @param c the collection whose elements are to be placed into this set - * @throws NullPointerException if the specified collection is null - */ - public HashSet(Collection<? extends E> c) { - map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); - addAll(c); - } - - /** - * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has - * the specified initial capacity and the specified load factor. - * - * @param initialCapacity the initial capacity of the hash map - * @param loadFactor the load factor of the hash map - * @throws IllegalArgumentException if the initial capacity is less - * than zero, or if the load factor is nonpositive - */ - public HashSet(int initialCapacity, float loadFactor) { - map = new HashMap<>(initialCapacity, loadFactor); - } - - /** - * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has - * the specified initial capacity and default load factor (0.75). - * - * @param initialCapacity the initial capacity of the hash table - * @throws IllegalArgumentException if the initial capacity is less - * than zero - */ - public HashSet(int initialCapacity) { - map = new HashMap<>(initialCapacity); - } - - /** - * Constructs a new, empty linked hash set. (This package private - * constructor is only used by LinkedHashSet.) The backing - * HashMap instance is a LinkedHashMap with the specified initial - * capacity and the specified load factor. - * - * @param initialCapacity the initial capacity of the hash map - * @param loadFactor the load factor of the hash map - * @param dummy ignored (distinguishes this - * constructor from other int, float constructor.) - * @throws IllegalArgumentException if the initial capacity is less - * than zero, or if the load factor is nonpositive - */ - HashSet(int initialCapacity, float loadFactor, boolean dummy) { - map = new LinkedHashMap<>(initialCapacity, loadFactor); - } - - /** - * Returns an iterator over the elements in this set. The elements - * are returned in no particular order. - * - * @return an Iterator over the elements in this set - * @see ConcurrentModificationException - */ - public Iterator<E> iterator() { - return map.keySet().iterator(); - } - - /** - * Returns the number of elements in this set (its cardinality). - * - * @return the number of elements in this set (its cardinality) - */ - public int size() { - return map.size(); - } - - /** - * Returns <tt>true</tt> if this set contains no elements. - * - * @return <tt>true</tt> if this set contains no elements - */ - public boolean isEmpty() { - return map.isEmpty(); - } - - /** - * Returns <tt>true</tt> if this set contains the specified element. - * More formally, returns <tt>true</tt> if and only if this set - * contains an element <tt>e</tt> such that - * <tt>(o==null ? e==null : o.equals(e))</tt>. - * - * @param o element whose presence in this set is to be tested - * @return <tt>true</tt> if this set contains the specified element - */ - public boolean contains(Object o) { - return map.containsKey(o); - } - - /** - * Adds the specified element to this set if it is not already present. - * More formally, adds the specified element <tt>e</tt> to this set if - * this set contains no element <tt>e2</tt> such that - * <tt>(e==null ? e2==null : e.equals(e2))</tt>. - * If this set already contains the element, the call leaves the set - * unchanged and returns <tt>false</tt>. - * - * @param e element to be added to this set - * @return <tt>true</tt> if this set did not already contain the specified - * element - */ - public boolean add(E e) { - return map.put(e, PRESENT)==null; - } - - /** - * Removes the specified element from this set if it is present. - * More formally, removes an element <tt>e</tt> such that - * <tt>(o==null ? e==null : o.equals(e))</tt>, - * if this set contains such an element. Returns <tt>true</tt> if - * this set contained the element (or equivalently, if this set - * changed as a result of the call). (This set will not contain the - * element once the call returns.) - * - * @param o object to be removed from this set, if present - * @return <tt>true</tt> if the set contained the specified element - */ - public boolean remove(Object o) { - return map.remove(o)==PRESENT; - } - - /** - * Removes all of the elements from this set. - * The set will be empty after this call returns. - */ - public void clear() { - map.clear(); - } - - /** - * Returns a shallow copy of this <tt>HashSet</tt> instance: the elements - * themselves are not cloned. - * - * @return a shallow copy of this set - */ - public Object clone() { - try { - HashSet<E> newSet = (HashSet<E>) super.clone(); - newSet.map = (HashMap<E, Object>) map.clone(); - return newSet; - } catch (CloneNotSupportedException e) { - throw new InternalError(); - } - } - - /** - * Save the state of this <tt>HashSet</tt> instance to a stream (that is, - * serialize it). - * - * @serialData The capacity of the backing <tt>HashMap</tt> instance - * (int), and its load factor (float) are emitted, followed by - * the size of the set (the number of elements it contains) - * (int), followed by all of its elements (each an Object) in - * no particular order. - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - // Write out any hidden serialization magic - s.defaultWriteObject(); - - // Write out HashMap capacity and load factor - s.writeInt(map.capacity()); - s.writeFloat(map.loadFactor()); - - // Write out size - s.writeInt(map.size()); - - // Write out all elements in the proper order. - for (E e : map.keySet()) - s.writeObject(e); - } - - /** - * Reconstitute the <tt>HashSet</tt> instance from a stream (that is, - * deserialize it). - */ - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - // Read in any hidden serialization magic - s.defaultReadObject(); - - // Read in HashMap capacity and load factor and create backing HashMap - int capacity = s.readInt(); - float loadFactor = s.readFloat(); - map = (((HashSet)this) instanceof LinkedHashSet ? - new LinkedHashMap<E,Object>(capacity, loadFactor) : - new HashMap<E,Object>(capacity, loadFactor)); - - // Read in size - int size = s.readInt(); - - // Read in all elements in the proper order. - for (int i=0; i<size; i++) { - E e = (E) s.readObject(); - map.put(e, PRESENT); - } - } -} diff --git a/notes/src/LinkedHashMap.java b/notes/src/LinkedHashMap.java deleted file mode 100644 index 946ac9a8..00000000 --- a/notes/src/LinkedHashMap.java +++ /dev/null @@ -1,349 +0,0 @@ - -package java.util; -import java.io.*; - -public class LinkedHashMap<K,V> - extends HashMap<K,V> - implements Map<K,V> -{ - - private static final long serialVersionUID = 3801124242820219131L; - - /** - * The head of the doubly linked list. - */ - private transient Entry<K,V> header; - - /** - * The iteration ordering method for this linked hash map: <tt>true</tt> - * for access-order, <tt>false</tt> for insertion-order. - * - * @serial - */ - private final boolean accessOrder; - - /** - * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance - * with the specified initial capacity and load factor. - * - * @param initialCapacity the initial capacity - * @param loadFactor the load factor - * @throws IllegalArgumentException if the initial capacity is negative - * or the load factor is nonpositive - */ - public LinkedHashMap(int initialCapacity, float loadFactor) { - super(initialCapacity, loadFactor); - accessOrder = false; - } - - /** - * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance - * with the specified initial capacity and a default load factor (0.75). - * - * @param initialCapacity the initial capacity - * @throws IllegalArgumentException if the initial capacity is negative - */ - public LinkedHashMap(int initialCapacity) { - super(initialCapacity); - accessOrder = false; - } - - /** - * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance - * with the default initial capacity (16) and load factor (0.75). - */ - public LinkedHashMap() { - super(); - accessOrder = false; - } - - /** - * Constructs an insertion-ordered <tt>LinkedHashMap</tt> instance with - * the same mappings as the specified map. The <tt>LinkedHashMap</tt> - * instance is created with a default load factor (0.75) and an initial - * capacity sufficient to hold the mappings in the specified map. - * - * @param m the map whose mappings are to be placed in this map - * @throws NullPointerException if the specified map is null - */ - public LinkedHashMap(Map<? extends K, ? extends V> m) { - super(m); - accessOrder = false; - } - - /** - * Constructs an empty <tt>LinkedHashMap</tt> instance with the - * specified initial capacity, load factor and ordering mode. - * - * @param initialCapacity the initial capacity - * @param loadFactor the load factor - * @param accessOrder the ordering mode - <tt>true</tt> for - * access-order, <tt>false</tt> for insertion-order - * @throws IllegalArgumentException if the initial capacity is negative - * or the load factor is nonpositive - */ - public LinkedHashMap(int initialCapacity, - float loadFactor, - boolean accessOrder) { - super(initialCapacity, loadFactor); - this.accessOrder = accessOrder; - } - - /** - * Called by superclass constructors and pseudoconstructors (clone, - * readObject) before any entries are inserted into the map. Initializes - * the chain. - */ - void init() { - header = new Entry<>(-1, null, null, null); - header.before = header.after = header; - } - - /** - * Transfers all entries to new table array. This method is called - * by superclass resize. It is overridden for performance, as it is - * faster to iterate using our linked list. - */ - void transfer(HashMap.Entry[] newTable) { - int newCapacity = newTable.length; - for (Entry<K,V> e = header.after; e != header; e = e.after) { - int index = indexFor(e.hash, newCapacity); - e.next = newTable[index]; - newTable[index] = e; - } - } - - - /** - * Returns <tt>true</tt> if this map maps one or more keys to the - * specified value. - * - * @param value value whose presence in this map is to be tested - * @return <tt>true</tt> if this map maps one or more keys to the - * specified value - */ - public boolean containsValue(Object value) { - // Overridden to take advantage of faster iterator - if (value==null) { - for (Entry e = header.after; e != header; e = e.after) - if (e.value==null) - return true; - } else { - for (Entry e = header.after; e != header; e = e.after) - if (value.equals(e.value)) - return true; - } - return false; - } - - /** - * Returns the value to which the specified key is mapped, - * or {@code null} if this map contains no mapping for the key. - * - * <p>More formally, if this map contains a mapping from a key - * {@code k} to a value {@code v} such that {@code (key==null ? k==null : - * key.equals(k))}, then this method returns {@code v}; otherwise - * it returns {@code null}. (There can be at most one such mapping.) - * - * <p>A return value of {@code null} does not <i>necessarily</i> - * indicate that the map contains no mapping for the key; it's also - * possible that the map explicitly maps the key to {@code null}. - * The {@link #containsKey containsKey} operation may be used to - * distinguish these two cases. - */ - public V get(Object key) { - Entry<K,V> e = (Entry<K,V>)getEntry(key); - if (e == null) - return null; - e.recordAccess(this); - return e.value; - } - - /** - * Removes all of the mappings from this map. - * The map will be empty after this call returns. - */ - public void clear() { - super.clear(); - header.before = header.after = header; - } - - /** - * LinkedHashMap entry. - */ - private static class Entry<K,V> extends HashMap.Entry<K,V> { - // These fields comprise the doubly linked list used for iteration. - Entry<K,V> before, after; - - Entry(int hash, K key, V value, HashMap.Entry<K,V> next) { - super(hash, key, value, next); - } - - /** - * Removes this entry from the linked list. - */ - private void remove() { - before.after = after; - after.before = before; - } - - /** - * Inserts this entry before the specified existing entry in the list. - */ - private void addBefore(Entry<K,V> existingEntry) { - after = existingEntry; - before = existingEntry.before; - before.after = this; - after.before = this; - } - - /** - * This method is invoked by the superclass whenever the value - * of a pre-existing entry is read by Map.get or modified by Map.set. - * If the enclosing Map is access-ordered, it moves the entry - * to the end of the list; otherwise, it does nothing. - */ - void recordAccess(HashMap<K,V> m) { - LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; - if (lm.accessOrder) { - lm.modCount++; - remove(); - addBefore(lm.header); - } - } - - void recordRemoval(HashMap<K,V> m) { - remove(); - } - } - - private abstract class LinkedHashIterator<T> implements Iterator<T> { - Entry<K,V> nextEntry = header.after; - Entry<K,V> lastReturned = null; - - /** - * The modCount value that the iterator believes that the backing - * List should have. If this expectation is violated, the iterator - * has detected concurrent modification. - */ - int expectedModCount = modCount; - - public boolean hasNext() { - return nextEntry != header; - } - - public void remove() { - if (lastReturned == null) - throw new IllegalStateException(); - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - - LinkedHashMap.this.remove(lastReturned.key); - lastReturned = null; - expectedModCount = modCount; - } - - Entry<K,V> nextEntry() { - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - if (nextEntry == header) - throw new NoSuchElementException(); - - Entry<K,V> e = lastReturned = nextEntry; - nextEntry = e.after; - return e; - } - } - - private class KeyIterator extends LinkedHashIterator<K> { - public K next() { return nextEntry().getKey(); } - } - - private class ValueIterator extends LinkedHashIterator<V> { - public V next() { return nextEntry().value; } - } - - private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> { - public Map.Entry<K,V> next() { return nextEntry(); } - } - - // These Overrides alter the behavior of superclass view iterator() methods - Iterator<K> newKeyIterator() { return new KeyIterator(); } - Iterator<V> newValueIterator() { return new ValueIterator(); } - Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); } - - /** - * This override alters behavior of superclass put method. It causes newly - * allocated entry to get inserted at the end of the linked list and - * removes the eldest entry if appropriate. - */ - void addEntry(int hash, K key, V value, int bucketIndex) { - createEntry(hash, key, value, bucketIndex); - - // Remove eldest entry if instructed, else grow capacity if appropriate - Entry<K,V> eldest = header.after; - if (removeEldestEntry(eldest)) { - removeEntryForKey(eldest.key); - } else { - if (size >= threshold) - resize(2 * table.length); - } - } - - /** - * This override differs from addEntry in that it doesn't resize the - * table or remove the eldest entry. - */ - void createEntry(int hash, K key, V value, int bucketIndex) { - HashMap.Entry<K,V> old = table[bucketIndex]; - Entry<K,V> e = new Entry<>(hash, key, value, old); - table[bucketIndex] = e; - e.addBefore(header); - size++; - } - - /** - * Returns <tt>true</tt> if this map should remove its eldest entry. - * This method is invoked by <tt>put</tt> and <tt>putAll</tt> after - * inserting a new entry into the map. It provides the implementor - * with the opportunity to remove the eldest entry each time a new one - * is added. This is useful if the map represents a cache: it allows - * the map to reduce memory consumption by deleting stale entries. - * - * <p>Sample use: this override will allow the map to grow up to 100 - * entries and then delete the eldest entry each time a new entry is - * added, maintaining a steady state of 100 entries. - * <pre> - * private static final int MAX_ENTRIES = 100; - * - * protected boolean removeEldestEntry(Map.Entry eldest) { - * return size() > MAX_ENTRIES; - * } - * </pre> - * - * <p>This method typically does not modify the map in any way, - * instead allowing the map to modify itself as directed by its - * return value. It <i>is</i> permitted for this method to modify - * the map directly, but if it does so, it <i>must</i> return - * <tt>false</tt> (indicating that the map should not attempt any - * further modification). The effects of returning <tt>true</tt> - * after modifying the map from within this method are unspecified. - * - * <p>This implementation merely returns <tt>false</tt> (so that this - * map acts like a normal map - the eldest element is never removed). - * - * @param eldest The least recently inserted entry in the map, or if - * this is an access-ordered map, the least recently accessed - * entry. This is the entry that will be removed it this - * method returns <tt>true</tt>. If the map was empty prior - * to the <tt>put</tt> or <tt>putAll</tt> invocation resulting - * in this invocation, this will be the entry that was just - * inserted; in other words, if the map contains a single - * entry, the eldest entry is also the newest. - * @return <tt>true</tt> if the eldest entry should be removed - * from the map; <tt>false</tt> if it should be retained. - */ - protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { - return false; - } -} diff --git a/notes/src/LinkedHashSet.java b/notes/src/LinkedHashSet.java deleted file mode 100644 index 9859c3cf..00000000 --- a/notes/src/LinkedHashSet.java +++ /dev/null @@ -1,57 +0,0 @@ - -package java.util; - -public class LinkedHashSet<E> - extends HashSet<E> - implements Set<E>, Cloneable, java.io.Serializable { - - private static final long serialVersionUID = -2851667679971038690L; - - /** - * Constructs a new, empty linked hash set with the specified initial - * capacity and load factor. - * - * @param initialCapacity the initial capacity of the linked hash set - * @param loadFactor the load factor of the linked hash set - * @throws IllegalArgumentException if the initial capacity is less - * than zero, or if the load factor is nonpositive - */ - public LinkedHashSet(int initialCapacity, float loadFactor) { - super(initialCapacity, loadFactor, true); - } - - /** - * Constructs a new, empty linked hash set with the specified initial - * capacity and the default load factor (0.75). - * - * @param initialCapacity the initial capacity of the LinkedHashSet - * @throws IllegalArgumentException if the initial capacity is less - * than zero - */ - public LinkedHashSet(int initialCapacity) { - super(initialCapacity, .75f, true); - } - - /** - * Constructs a new, empty linked hash set with the default initial - * capacity (16) and load factor (0.75). - */ - public LinkedHashSet() { - super(16, .75f, true); - } - - /** - * Constructs a new linked hash set with the same elements as the - * specified collection. The linked hash set is created with an initial - * capacity sufficient to hold the elements in the specified collection - * and the default load factor (0.75). - * - * @param c the collection whose elements are to be placed into - * this set - * @throws NullPointerException if the specified collection is null - */ - public LinkedHashSet(Collection<? extends E> c) { - super(Math.max(2*c.size(), 11), .75f, true); - addAll(c); - } -} diff --git a/notes/src/LinkedList.java b/notes/src/LinkedList.java deleted file mode 100644 index 10f800de..00000000 --- a/notes/src/LinkedList.java +++ /dev/null @@ -1,1061 +0,0 @@ - -package java.util; - -public class LinkedList<E> - extends AbstractSequentialList<E> - implements List<E>, Deque<E>, 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<E> first; - - /** - * Pointer to last node. - * Invariant: (first == null && last == null) || - * (last.next == null && last.item != null) - */ - transient Node<E> 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<? extends E> c) { - this(); - addAll(c); - } - - /** - * Links e as first element. - */ - private void linkFirst(E e) { - final Node<E> f = first; - final Node<E> 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<E> l = last; - final Node<E> 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<E> succ) { - // assert succ != null; - final Node<E> pred = succ.prev; - final Node<E> 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<E> f) { - // assert f == first && f != null; - final E element = f.item; - final Node<E> 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<E> l) { - // assert l == last && l != null; - final E element = l.item; - final Node<E> 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<E> x) { - // assert x != null; - final E element = x.item; - final Node<E> next = x.next; - final Node<E> 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<E> 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<E> 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<E> 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<E> 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. - * - * <p>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 - * <tt>(o==null ? e==null : o.equals(e))</tt>. - * - * @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. - * - * <p>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 - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> - * (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<E> x = first; x != null; x = x.next) { - if (x.item == null) { - unlink(x); - return true; - } - } - } else { - for (Node<E> 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<? extends E> 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<? extends E> c) { - checkPositionIndex(index); - - Object[] a = c.toArray(); - int numNew = a.length; - if (numNew == 0) - return false; - - Node<E> 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<E> 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<E> x = first; x != null; ) { - Node<E> 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<E> 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<E> node(int index) { - // assert isElementIndex(index); - - if (index < (size >> 1)) { - Node<E> x = first; - for (int i = 0; i < index; i++) - x = x.next; - return x; - } else { - Node<E> 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 - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, - * or -1 if there is no such index. - * - * @param o element to search for - * @return the index of the first occurrence of the specified element in - * this list, or -1 if this list does not contain the element - */ - public int indexOf(Object o) { - int index = 0; - if (o == null) { - for (Node<E> x = first; x != null; x = x.next) { - if (x.item == null) - return index; - index++; - } - } else { - for (Node<E> 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 - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, - * or -1 if there is no such index. - * - * @param o element to search for - * @return the index of the last occurrence of the specified element in - * this list, or -1 if this list does not contain the element - */ - public int lastIndexOf(Object o) { - int index = size; - if (o == null) { - for (Node<E> x = last; x != null; x = x.prev) { - index--; - if (x.item == null) - return index; - } - } else { - for (Node<E> 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<E> 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<E> 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<E> 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<E> 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<E> 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<E> 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. - * - * <p>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. - * - * <p>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<E> x = last; x != null; x = x.prev) { - if (x.item == null) { - unlink(x); - return true; - } - } - } else { - for (Node<E> 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)}.<p> - * - * The list-iterator is <i>fail-fast</i>: 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<E> listIterator(int index) { - checkPositionIndex(index); - return new ListItr(index); - } - - private class ListItr implements ListIterator<E> { - private Node<E> lastReturned = null; - private Node<E> 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<E> 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> { - E item; - Node<E> next; - Node<E> prev; - - Node(Node<E> prev, E element, Node<E> next) { - this.item = element; - this.next = next; - this.prev = prev; - } - } - - /** - * @since 1.6 - */ - public Iterator<E> descendingIterator() { - return new DescendingIterator(); - } - - /** - * Adapter to provide descending iterators via ListItr.previous - */ - private class DescendingIterator implements Iterator<E> { - 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<E> superClone() { - try { - return (LinkedList<E>) 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<E> 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<E> 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). - * - * <p>The returned array will be "safe" in that no references to it are - * maintained by this list. (In other words, this method must allocate - * a new array). The caller is thus free to modify the returned array. - * - * <p>This method acts as bridge between array-based and collection-based - * APIs. - * - * @return an array containing all of the elements in this list - * in proper sequence - */ - public Object[] toArray() { - Object[] result = new Object[size]; - int i = 0; - for (Node<E> 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. - * - * <p>If the list fits in the specified array with room to spare (i.e., - * the array has more elements than the list), the element in the array - * immediately following the end of the list is set to {@code null}. - * (This is useful in determining the length of the list <i>only</i> if - * the caller knows that the list does not contain any null elements.) - * - * <p>Like the {@link #toArray()} method, this method acts as bridge between - * array-based and collection-based APIs. Further, this method allows - * precise control over the runtime type of the output array, and may, - * under certain circumstances, be used to save allocation costs. - * - * <p>Suppose {@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}: - * - * <pre> - * String[] y = x.toArray(new String[0]);</pre> - * - * Note that {@code toArray(new Object[0])} is identical in function to - * {@code toArray()}. - * - * @param a the array into which the elements of 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> 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<E> 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<E> 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 --git a/notes/src/PriorityQueue.java b/notes/src/PriorityQueue.java deleted file mode 100644 index b76c1d96..00000000 --- a/notes/src/PriorityQueue.java +++ /dev/null @@ -1,698 +0,0 @@ -package java.util; - -public class PriorityQueue<E> extends AbstractQueue<E> - implements java.io.Serializable { - - private static final long serialVersionUID = -7720805057305804111L; - - private static final int DEFAULT_INITIAL_CAPACITY = 11; - - /** - * Priority queue represented as a balanced binary heap: the two - * children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The - * priority queue is ordered by comparator, or by the elements' - * natural ordering, if comparator is null: For each node n in the - * heap and each descendant d of n, n <= d. The element with the - * lowest value is in queue[0], assuming the queue is nonempty. - */ - private transient Object[] queue; - - /** - * The number of elements in the priority queue. - */ - private int size = 0; - - /** - * The comparator, or null if priority queue uses elements' - * natural ordering. - */ - private final Comparator<? super E> comparator; - - /** - * The number of times this priority queue has been - * <i>structurally modified</i>. See AbstractList for gory details. - */ - private transient int modCount = 0; - - /** - * Creates a {@code PriorityQueue} with the default initial - * capacity (11) that orders its elements according to their - * {@linkplain Comparable natural ordering}. - */ - public PriorityQueue() { - this(DEFAULT_INITIAL_CAPACITY, null); - } - - /** - * Creates a {@code PriorityQueue} with the specified initial - * capacity that orders its elements according to their - * {@linkplain Comparable natural ordering}. - * - * @param initialCapacity the initial capacity for this priority queue - * @throws IllegalArgumentException if {@code initialCapacity} is less - * than 1 - */ - public PriorityQueue(int initialCapacity) { - this(initialCapacity, null); - } - - /** - * Creates a {@code PriorityQueue} with the specified initial capacity - * that orders its elements according to the specified comparator. - * - * @param initialCapacity the initial capacity for this priority queue - * @param comparator the comparator that will be used to order this - * priority queue. If {@code null}, the {@linkplain Comparable - * natural ordering} of the elements will be used. - * @throws IllegalArgumentException if {@code initialCapacity} is - * less than 1 - */ - public PriorityQueue(int initialCapacity, - Comparator<? super E> comparator) { - // Note: This restriction of at least one is not actually needed, - // but continues for 1.5 compatibility - if (initialCapacity < 1) - throw new IllegalArgumentException(); - this.queue = new Object[initialCapacity]; - this.comparator = comparator; - } - - /** - * Creates a {@code PriorityQueue} containing the elements in the - * specified collection. If the specified collection is an instance of - * a {@link SortedSet} or is another {@code PriorityQueue}, this - * priority queue will be ordered according to the same ordering. - * Otherwise, this priority queue will be ordered according to the - * {@linkplain Comparable natural ordering} of its elements. - * - * @param c the collection whose elements are to be placed - * into this priority queue - * @throws ClassCastException if elements of the specified collection - * cannot be compared to one another according to the priority - * queue's ordering - * @throws NullPointerException if the specified collection or any - * of its elements are null - */ - @SuppressWarnings("unchecked") - public PriorityQueue(Collection<? extends E> c) { - if (c instanceof SortedSet<?>) { - SortedSet<? extends E> ss = (SortedSet<? extends E>) c; - this.comparator = (Comparator<? super E>) ss.comparator(); - initElementsFromCollection(ss); - } - else if (c instanceof PriorityQueue<?>) { - PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c; - this.comparator = (Comparator<? super E>) pq.comparator(); - initFromPriorityQueue(pq); - } - else { - this.comparator = null; - initFromCollection(c); - } - } - - /** - * Creates a {@code PriorityQueue} containing the elements in the - * specified priority queue. This priority queue will be - * ordered according to the same ordering as the given priority - * queue. - * - * @param c the priority queue whose elements are to be placed - * into this priority queue - * @throws ClassCastException if elements of {@code c} cannot be - * compared to one another according to {@code c}'s - * ordering - * @throws NullPointerException if the specified priority queue or any - * of its elements are null - */ - @SuppressWarnings("unchecked") - public PriorityQueue(PriorityQueue<? extends E> c) { - this.comparator = (Comparator<? super E>) c.comparator(); - initFromPriorityQueue(c); - } - - /** - * Creates a {@code PriorityQueue} containing the elements in the - * specified sorted set. This priority queue will be ordered - * according to the same ordering as the given sorted set. - * - * @param c the sorted set whose elements are to be placed - * into this priority queue - * @throws ClassCastException if elements of the specified sorted - * set cannot be compared to one another according to the - * sorted set's ordering - * @throws NullPointerException if the specified sorted set or any - * of its elements are null - */ - @SuppressWarnings("unchecked") - public PriorityQueue(SortedSet<? extends E> c) { - this.comparator = (Comparator<? super E>) c.comparator(); - initElementsFromCollection(c); - } - - private void initFromPriorityQueue(PriorityQueue<? extends E> c) { - if (c.getClass() == PriorityQueue.class) { - this.queue = c.toArray(); - this.size = c.size(); - } else { - initFromCollection(c); - } - } - - private void initElementsFromCollection(Collection<? extends E> c) { - Object[] a = c.toArray(); - // If c.toArray incorrectly doesn't return Object[], copy it. - if (a.getClass() != Object[].class) - a = Arrays.copyOf(a, a.length, Object[].class); - int len = a.length; - if (len == 1 || this.comparator != null) - for (int i = 0; i < len; i++) - if (a[i] == null) - throw new NullPointerException(); - this.queue = a; - this.size = a.length; - } - - /** - * Initializes queue array with elements from the given Collection. - * - * @param c the collection - */ - private void initFromCollection(Collection<? extends E> c) { - initElementsFromCollection(c); - heapify(); - } - - /** - * The maximum size of array to allocate. - * Some VMs reserve some header words in an array. - * Attempts to allocate larger arrays may result in - * OutOfMemoryError: Requested array size exceeds VM limit - */ - private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; - - /** - * Increases the capacity of the array. - * - * @param minCapacity the desired minimum capacity - */ - private void grow(int minCapacity) { - int oldCapacity = queue.length; - // Double size if small; else grow by 50% - int newCapacity = oldCapacity + ((oldCapacity < 64) ? - (oldCapacity + 2) : - (oldCapacity >> 1)); - // overflow-conscious code - if (newCapacity - MAX_ARRAY_SIZE > 0) - newCapacity = hugeCapacity(minCapacity); - queue = Arrays.copyOf(queue, newCapacity); - } - - private static int hugeCapacity(int minCapacity) { - if (minCapacity < 0) // overflow - throw new OutOfMemoryError(); - return (minCapacity > MAX_ARRAY_SIZE) ? - Integer.MAX_VALUE : - MAX_ARRAY_SIZE; - } - - /** - * Inserts the specified element into this priority queue. - * - * @return {@code true} (as specified by {@link Collection#add}) - * @throws ClassCastException if the specified element cannot be - * compared with elements currently in this priority queue - * according to the priority queue's ordering - * @throws NullPointerException if the specified element is null - */ - public boolean add(E e) { - return offer(e); - } - - /** - * Inserts the specified element into this priority queue. - * - * @return {@code true} (as specified by {@link Queue#offer}) - * @throws ClassCastException if the specified element cannot be - * compared with elements currently in this priority queue - * according to the priority queue's ordering - * @throws NullPointerException if the specified element is null - */ - public boolean offer(E e) { - if (e == null) - throw new NullPointerException(); - modCount++; - int i = size; - if (i >= queue.length) - grow(i + 1); - size = i + 1; - if (i == 0) - queue[0] = e; - else - siftUp(i, e); - return true; - } - - public E peek() { - if (size == 0) - return null; - return (E) queue[0]; - } - - private int indexOf(Object o) { - if (o != null) { - for (int i = 0; i < size; i++) - if (o.equals(queue[i])) - return i; - } - return -1; - } - - /** - * Removes a single instance of the specified element from this queue, - * if it is present. More formally, removes an element {@code e} such - * that {@code o.equals(e)}, if this queue contains one or more such - * elements. Returns {@code true} if and only if this queue contained - * the specified element (or equivalently, if this queue changed as a - * result of the call). - * - * @param o element to be removed from this queue, if present - * @return {@code true} if this queue changed as a result of the call - */ - public boolean remove(Object o) { - int i = indexOf(o); - if (i == -1) - return false; - else { - removeAt(i); - return true; - } - } - - /** - * Version of remove using reference equality, not equals. - * Needed by iterator.remove. - * - * @param o element to be removed from this queue, if present - * @return {@code true} if removed - */ - boolean removeEq(Object o) { - for (int i = 0; i < size; i++) { - if (o == queue[i]) { - removeAt(i); - return true; - } - } - return false; - } - - /** - * Returns {@code true} if this queue contains the specified element. - * More formally, returns {@code true} if and only if this queue contains - * at least one element {@code e} such that {@code o.equals(e)}. - * - * @param o object to be checked for containment in this queue - * @return {@code true} if this queue contains the specified element - */ - public boolean contains(Object o) { - return indexOf(o) != -1; - } - - /** - * Returns an array containing all of the elements in this queue. - * The elements are in no particular order. - * - * <p>The returned array will be "safe" in that no references to it are - * maintained by this queue. (In other words, this method must allocate - * a new array). The caller is thus free to modify the returned array. - * - * <p>This method acts as bridge between array-based and collection-based - * APIs. - * - * @return an array containing all of the elements in this queue - */ - public Object[] toArray() { - return Arrays.copyOf(queue, size); - } - - /** - * Returns an array containing all of the elements in this queue; the - * runtime type of the returned array is that of the specified array. - * The returned array elements are in no particular order. - * If the queue fits in the specified array, it is returned therein. - * Otherwise, a new array is allocated with the runtime type of the - * specified array and the size of this queue. - * - * <p>If the queue fits in the specified array with room to spare - * (i.e., the array has more elements than the queue), the element in - * the array immediately following the end of the collection is set to - * {@code null}. - * - * <p>Like the {@link #toArray()} method, this method acts as bridge between - * array-based and collection-based APIs. Further, this method allows - * precise control over the runtime type of the output array, and may, - * under certain circumstances, be used to save allocation costs. - * - * <p>Suppose <tt>x</tt> is a queue known to contain only strings. - * The following code can be used to dump the queue into a newly - * allocated array of <tt>String</tt>: - * - * <pre> - * String[] y = x.toArray(new String[0]);</pre> - * - * Note that <tt>toArray(new Object[0])</tt> is identical in function to - * <tt>toArray()</tt>. - * - * @param a the array into which the elements of the queue are to - * be stored, if it is big enough; otherwise, a new array of the - * same runtime type is allocated for this purpose. - * @return an array containing all of the elements in this queue - * @throws ArrayStoreException if the runtime type of the specified array - * is not a supertype of the runtime type of every element in - * this queue - * @throws NullPointerException if the specified array is null - */ - public <T> T[] toArray(T[] a) { - if (a.length < size) - // Make a new array of a's runtime type, but my contents: - return (T[]) Arrays.copyOf(queue, size, a.getClass()); - System.arraycopy(queue, 0, a, 0, size); - if (a.length > size) - a[size] = null; - return a; - } - - /** - * Returns an iterator over the elements in this queue. The iterator - * does not return the elements in any particular order. - * - * @return an iterator over the elements in this queue - */ - public Iterator<E> iterator() { - return new Itr(); - } - - private final class Itr implements Iterator<E> { - /** - * Index (into queue array) of element to be returned by - * subsequent call to next. - */ - private int cursor = 0; - - /** - * Index of element returned by most recent call to next, - * unless that element came from the forgetMeNot list. - * Set to -1 if element is deleted by a call to remove. - */ - private int lastRet = -1; - - /** - * A queue of elements that were moved from the unvisited portion of - * the heap into the visited portion as a result of "unlucky" element - * removals during the iteration. (Unlucky element removals are those - * that require a siftup instead of a siftdown.) We must visit all of - * the elements in this list to complete the iteration. We do this - * after we've completed the "normal" iteration. - * - * We expect that most iterations, even those involving removals, - * will not need to store elements in this field. - */ - private ArrayDeque<E> forgetMeNot = null; - - /** - * Element returned by the most recent call to next iff that - * element was drawn from the forgetMeNot list. - */ - private E lastRetElt = null; - - /** - * The modCount value that the iterator believes that the backing - * Queue should have. If this expectation is violated, the iterator - * has detected concurrent modification. - */ - private int expectedModCount = modCount; - - public boolean hasNext() { - return cursor < size || - (forgetMeNot != null && !forgetMeNot.isEmpty()); - } - - public E next() { - if (expectedModCount != modCount) - throw new ConcurrentModificationException(); - if (cursor < size) - return (E) queue[lastRet = cursor++]; - if (forgetMeNot != null) { - lastRet = -1; - lastRetElt = forgetMeNot.poll(); - if (lastRetElt != null) - return lastRetElt; - } - throw new NoSuchElementException(); - } - - public void remove() { - if (expectedModCount != modCount) - throw new ConcurrentModificationException(); - if (lastRet != -1) { - E moved = PriorityQueue.this.removeAt(lastRet); - lastRet = -1; - if (moved == null) - cursor--; - else { - if (forgetMeNot == null) - forgetMeNot = new ArrayDeque<>(); - forgetMeNot.add(moved); - } - } else if (lastRetElt != null) { - PriorityQueue.this.removeEq(lastRetElt); - lastRetElt = null; - } else { - throw new IllegalStateException(); - } - expectedModCount = modCount; - } - } - - public int size() { - return size; - } - - /** - * Removes all of the elements from this priority queue. - * The queue will be empty after this call returns. - */ - public void clear() { - modCount++; - for (int i = 0; i < size; i++) - queue[i] = null; - size = 0; - } - - public E poll() { - if (size == 0) - return null; - int s = --size; - modCount++; - E result = (E) queue[0]; - E x = (E) queue[s]; - queue[s] = null; - if (s != 0) - siftDown(0, x); - return result; - } - - /** - * Removes the ith element from queue. - * - * Normally this method leaves the elements at up to i-1, - * inclusive, untouched. Under these circumstances, it returns - * null. Occasionally, in order to maintain the heap invariant, - * it must swap a later element of the list with one earlier than - * i. Under these circumstances, this method returns the element - * that was previously at the end of the list and is now at some - * position before i. This fact is used by iterator.remove so as to - * avoid missing traversing elements. - */ - private E removeAt(int i) { - assert i >= 0 && i < size; - modCount++; - int s = --size; - if (s == i) // removed last element - queue[i] = null; - else { - E moved = (E) queue[s]; - queue[s] = null; - siftDown(i, moved); - if (queue[i] == moved) { - siftUp(i, moved); - if (queue[i] != moved) - return moved; - } - } - return null; - } - - /** - * Inserts item x at position k, maintaining heap invariant by - * promoting x up the tree until it is greater than or equal to - * its parent, or is the root. - * - * To simplify and speed up coercions and comparisons. the - * Comparable and Comparator versions are separated into different - * methods that are otherwise identical. (Similarly for siftDown.) - * - * @param k the position to fill - * @param x the item to insert - */ - private void siftUp(int k, E x) { - if (comparator != null) - siftUpUsingComparator(k, x); - else - siftUpComparable(k, x); - } - - private void siftUpComparable(int k, E x) { - Comparable<? super E> key = (Comparable<? super E>) x; - while (k > 0) { - int parent = (k - 1) >>> 1; - Object e = queue[parent]; - if (key.compareTo((E) e) >= 0) - break; - queue[k] = e; - k = parent; - } - queue[k] = key; - } - - private void siftUpUsingComparator(int k, E x) { - while (k > 0) { - int parent = (k - 1) >>> 1; - Object e = queue[parent]; - if (comparator.compare(x, (E) e) >= 0) - break; - queue[k] = e; - k = parent; - } - queue[k] = x; - } - - /** - * Inserts item x at position k, maintaining heap invariant by - * demoting x down the tree repeatedly until it is less than or - * equal to its children or is a leaf. - * - * @param k the position to fill - * @param x the item to insert - */ - private void siftDown(int k, E x) { - if (comparator != null) - siftDownUsingComparator(k, x); - else - siftDownComparable(k, x); - } - - private void siftDownComparable(int k, E x) { - Comparable<? super E> key = (Comparable<? super E>)x; - int half = size >>> 1; // loop while a non-leaf - while (k < half) { - int child = (k << 1) + 1; // assume left child is least - Object c = queue[child]; - int right = child + 1; - if (right < size && - ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0) - c = queue[child = right]; - if (key.compareTo((E) c) <= 0) - break; - queue[k] = c; - k = child; - } - queue[k] = key; - } - - private void siftDownUsingComparator(int k, E x) { - int half = size >>> 1; - while (k < half) { - int child = (k << 1) + 1; - Object c = queue[child]; - int right = child + 1; - if (right < size && - comparator.compare((E) c, (E) queue[right]) > 0) - c = queue[child = right]; - if (comparator.compare(x, (E) c) <= 0) - break; - queue[k] = c; - k = child; - } - queue[k] = x; - } - - /** - * Establishes the heap invariant (described above) in the entire tree, - * assuming nothing about the order of the elements prior to the call. - */ - private void heapify() { - for (int i = (size >>> 1) - 1; i >= 0; i--) - siftDown(i, (E) queue[i]); - } - - /** - * Returns the comparator used to order the elements in this - * queue, or {@code null} if this queue is sorted according to - * the {@linkplain Comparable natural ordering} of its elements. - * - * @return the comparator used to order this queue, or - * {@code null} if this queue is sorted according to the - * natural ordering of its elements - */ - public Comparator<? super E> comparator() { - return comparator; - } - - /** - * Saves the state of the instance to a stream (that - * is, serializes it). - * - * @serialData The length of the array backing the instance is - * emitted (int), followed by all of its elements - * (each an {@code Object}) in the proper order. - * @param s the stream - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException{ - // Write out element count, and any hidden stuff - s.defaultWriteObject(); - - // Write out array length, for compatibility with 1.5 version - s.writeInt(Math.max(2, size + 1)); - - // Write out all elements in the "proper order". - for (int i = 0; i < size; i++) - s.writeObject(queue[i]); - } - - /** - * Reconstitutes the {@code PriorityQueue} instance from a stream - * (that is, deserializes it). - * - * @param s the stream - */ - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - // Read in size, and any hidden stuff - s.defaultReadObject(); - - // Read in (and discard) array length - s.readInt(); - - queue = new Object[size]; - - // Read in all elements. - for (int i = 0; i < size; i++) - queue[i] = s.readObject(); - - // Elements are guaranteed to be in "proper order", but the - // spec has never explained what that might be. - heapify(); - } -} diff --git a/notes/src/Queue.java b/notes/src/Queue.java deleted file mode 100644 index 05088a39..00000000 --- a/notes/src/Queue.java +++ /dev/null @@ -1,78 +0,0 @@ - -package java.util; - -public interface Queue<E> extends Collection<E> { - /** - * Inserts the specified element into this queue if it is possible to do so - * immediately without violating capacity restrictions, returning - * <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt> - * if no space is currently available. - * - * @param e the element to add - * @return <tt>true</tt> (as specified by {@link Collection#add}) - * @throws IllegalStateException if the element cannot be added at this - * time due to capacity restrictions - * @throws ClassCastException if the class of the specified element - * prevents it from being added to this queue - * @throws NullPointerException if the specified element is null and - * this queue does not permit null elements - * @throws IllegalArgumentException if some property of this element - * prevents it from being added to this queue - */ - 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 <tt>true</tt> if the element was added to this queue, else - * <tt>false</tt> - * @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 <tt>null</tt> if this queue is empty. - * - * @return the head of this queue, or <tt>null</tt> 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 <tt>null</tt> if this queue is empty. - * - * @return the head of this queue, or <tt>null</tt> if this queue is empty - */ - E peek(); -} diff --git a/notes/src/Stack.java b/notes/src/Stack.java deleted file mode 100644 index 96acf05b..00000000 --- a/notes/src/Stack.java +++ /dev/null @@ -1,97 +0,0 @@ - -package java.util; - -public -class Stack<E> extends Vector<E> { - /** - * Creates an empty Stack. - */ - public Stack() { - } - - /** - * Pushes an item onto the top of this stack. This has exactly - * the same effect as: - * <blockquote><pre> - * addElement(item)</pre></blockquote> - * - * @param item the item to be pushed onto this stack. - * @return the <code>item</code> 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 <tt>Vector</tt> 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 <tt>Vector</tt> 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 <code>true</code> if and only if this stack contains - * no items; <code>false</code> otherwise. - */ - public boolean empty() { - return size() == 0; - } - - /** - * Returns the 1-based position where an object is on this stack. - * If the object <tt>o</tt> 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 <tt>1</tt>. The <tt>equals</tt> - * method is used to compare <tt>o</tt> 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 <code>-1</code> - * 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 --git a/notes/src/String.java b/notes/src/String.java deleted file mode 100644 index b68f7ff2..00000000 --- a/notes/src/String.java +++ /dev/null @@ -1,2984 +0,0 @@ - -package java.lang; - -import java.io.ObjectStreamClass; -import java.io.ObjectStreamField; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Formatter; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -public final class String - implements java.io.Serializable, Comparable<String>, CharSequence -{ - /** The value is used for character storage. */ - private final char value[]; - - /** The offset is the first index of the storage that is used. */ - private final int offset; - - /** The count is the number of characters in the String. */ - private final int count; - - /** Cache the hash code for the string */ - private int hash; // Default to 0 - - /** use serialVersionUID from JDK 1.0.2 for interoperability */ - private static final long serialVersionUID = -6849794470754667710L; - - /** - * Class String is special cased within the Serialization Stream Protocol. - * - * A String instance is written initially into an ObjectOutputStream in the - * following format: - * <pre> - * <code>TC_STRING</code> (utf String) - * </pre> - * The String is written by method <code>DataOutput.writeUTF</code>. - * A new handle is generated to refer to all future references to the - * string instance within the stream. - */ - private static final ObjectStreamField[] serialPersistentFields = - new ObjectStreamField[0]; - - /** - * Initializes a newly created {@code String} object so that it represents - * an empty character sequence. Note that use of this constructor is - * unnecessary since Strings are immutable. - */ - public String() { - this.offset = 0; - this.count = 0; - this.value = new char[0]; - } - - /** - * Initializes a newly created {@code String} object so that it represents - * the same sequence of characters as the argument; in other words, the - * newly created string is a copy of the argument string. Unless an - * explicit copy of {@code original} is needed, use of this constructor is - * unnecessary since Strings are immutable. - * - * @param original - * A {@code String} - */ - public String(String original) { - int size = original.count; - char[] originalValue = original.value; - char[] v; - if (originalValue.length > size) { - // The array representing the String is bigger than the new - // String itself. Perhaps this constructor is being called - // in order to trim the baggage, so make a copy of the array. - int off = original.offset; - v = Arrays.copyOfRange(originalValue, off, off+size); - } else { - // The array representing the String is the same - // size as the String, so no point in making a copy. - v = originalValue; - } - this.offset = 0; - this.count = size; - this.value = v; - } - - /** - * Allocates a new {@code String} so that it represents the sequence of - * characters currently contained in the character array argument. The - * contents of the character array are copied; subsequent modification of - * the character array does not affect the newly created string. - * - * @param value - * The initial value of the string - */ - public String(char value[]) { - int size = value.length; - this.offset = 0; - this.count = size; - this.value = Arrays.copyOf(value, size); - } - - /** - * Allocates a new {@code String} that contains characters from a subarray - * of the character array argument. The {@code offset} argument is the - * index of the first character of the subarray and the {@code count} - * argument specifies the length of the subarray. The contents of the - * subarray are copied; subsequent modification of the character array does - * not affect the newly created string. - * - * @param value - * Array that is the source of characters - * - * @param offset - * The initial offset - * - * @param count - * The length - * - * @throws IndexOutOfBoundsException - * If the {@code offset} and {@code count} arguments index - * characters outside the bounds of the {@code value} array - */ - public String(char value[], int offset, int count) { - if (offset < 0) { - throw new StringIndexOutOfBoundsException(offset); - } - if (count < 0) { - throw new StringIndexOutOfBoundsException(count); - } - // Note: offset or count might be near -1>>>1. - if (offset > value.length - count) { - throw new StringIndexOutOfBoundsException(offset + count); - } - this.offset = 0; - this.count = count; - this.value = Arrays.copyOfRange(value, offset, offset+count); - } - - /** - * Allocates a new {@code String} that contains characters from a subarray - * of the <a href="Character.html#unicode">Unicode code point</a> array - * argument. The {@code offset} argument is the index of the first code - * point of the subarray and the {@code count} argument specifies the - * length of the subarray. The contents of the subarray are converted to - * {@code char}s; subsequent modification of the {@code int} array does not - * affect the newly created string. - * - * @param codePoints - * Array that is the source of Unicode code points - * - * @param offset - * The initial offset - * - * @param count - * The length - * - * @throws IllegalArgumentException - * If any invalid Unicode code point is found in {@code - * codePoints} - * - * @throws IndexOutOfBoundsException - * If the {@code offset} and {@code count} arguments index - * characters outside the bounds of the {@code codePoints} array - * - * @since 1.5 - */ - public String(int[] codePoints, int offset, int count) { - if (offset < 0) { - throw new StringIndexOutOfBoundsException(offset); - } - if (count < 0) { - throw new StringIndexOutOfBoundsException(count); - } - // Note: offset or count might be near -1>>>1. - if (offset > codePoints.length - count) { - throw new StringIndexOutOfBoundsException(offset + count); - } - - final int end = offset + count; - - // Pass 1: Compute precise size of char[] - int n = count; - for (int i = offset; i < end; i++) { - int c = codePoints[i]; - if (Character.isBmpCodePoint(c)) - continue; - else if (Character.isValidCodePoint(c)) - n++; - else throw new IllegalArgumentException(Integer.toString(c)); - } - - // Pass 2: Allocate and fill in char[] - final char[] v = new char[n]; - - for (int i = offset, j = 0; i < end; i++, j++) { - int c = codePoints[i]; - if (Character.isBmpCodePoint(c)) - v[j] = (char) c; - else - Character.toSurrogates(c, v, j++); - } - - this.value = v; - this.count = n; - this.offset = 0; - } - - /** - * Allocates a new {@code String} constructed from a subarray of an array - * of 8-bit integer values. - * - * <p> The {@code offset} argument is the index of the first byte of the - * subarray, and the {@code count} argument specifies the length of the - * subarray. - * - * <p> Each {@code byte} in the subarray is converted to a {@code char} as - * specified in the method above. - * - * @deprecated This method does not properly convert bytes into characters. - * As of JDK 1.1, the preferred way to do this is via the - * {@code String} constructors that take a {@link - * java.nio.charset.Charset}, charset name, or that use the platform's - * default charset. - * - * @param ascii - * The bytes to be converted to characters - * - * @param hibyte - * The top 8 bits of each 16-bit Unicode code unit - * - * @param offset - * The initial offset - * @param count - * The length - * - * @throws IndexOutOfBoundsException - * If the {@code offset} or {@code count} argument is invalid - * - * @see #String(byte[], int) - * @see #String(byte[], int, int, java.lang.String) - * @see #String(byte[], int, int, java.nio.charset.Charset) - * @see #String(byte[], int, int) - * @see #String(byte[], java.lang.String) - * @see #String(byte[], java.nio.charset.Charset) - * @see #String(byte[]) - */ - @Deprecated - public String(byte ascii[], int hibyte, int offset, int count) { - checkBounds(ascii, offset, count); - char value[] = new char[count]; - - if (hibyte == 0) { - for (int i = count ; i-- > 0 ;) { - value[i] = (char) (ascii[i + offset] & 0xff); - } - } else { - hibyte <<= 8; - for (int i = count ; i-- > 0 ;) { - value[i] = (char) (hibyte | (ascii[i + offset] & 0xff)); - } - } - this.offset = 0; - this.count = count; - this.value = value; - } - - /** - * Allocates a new {@code String} containing characters constructed from - * an array of 8-bit integer values. Each character <i>c</i>in the - * resulting string is constructed from the corresponding component - * <i>b</i> in the byte array such that: - * - * <blockquote><pre> - * <b><i>c</i></b> == (char)(((hibyte & 0xff) << 8) - * | (<b><i>b</i></b> & 0xff)) - * </pre></blockquote> - * - * @deprecated This method does not properly convert bytes into - * characters. As of JDK 1.1, the preferred way to do this is via the - * {@code String} constructors that take a {@link - * java.nio.charset.Charset}, charset name, or that use the platform's - * default charset. - * - * @param ascii - * The bytes to be converted to characters - * - * @param hibyte - * The top 8 bits of each 16-bit Unicode code unit - * - * @see #String(byte[], int, int, java.lang.String) - * @see #String(byte[], int, int, java.nio.charset.Charset) - * @see #String(byte[], int, int) - * @see #String(byte[], java.lang.String) - * @see #String(byte[], java.nio.charset.Charset) - * @see #String(byte[]) - */ - @Deprecated - public String(byte ascii[], int hibyte) { - this(ascii, hibyte, 0, ascii.length); - } - - /* Common private utility method used to bounds check the byte array - * and requested offset & length values used by the String(byte[],..) - * constructors. - */ - private static void checkBounds(byte[] bytes, int offset, int length) { - if (length < 0) - throw new StringIndexOutOfBoundsException(length); - if (offset < 0) - throw new StringIndexOutOfBoundsException(offset); - if (offset > bytes.length - length) - throw new StringIndexOutOfBoundsException(offset + length); - } - - /** - * Constructs a new {@code String} by decoding the specified subarray of - * bytes using the specified charset. The length of the new {@code String} - * is a function of the charset, and hence may not be equal to the length - * of the subarray. - * - * <p> The behavior of this constructor when the given bytes are not valid - * in the given charset is unspecified. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @param offset - * The index of the first byte to decode - * - * @param length - * The number of bytes to decode - - * @param charsetName - * The name of a supported {@linkplain java.nio.charset.Charset - * charset} - * - * @throws UnsupportedEncodingException - * If the named charset is not supported - * - * @throws IndexOutOfBoundsException - * If the {@code offset} and {@code length} arguments index - * characters outside the bounds of the {@code bytes} array - * - * @since JDK1.1 - */ - public String(byte bytes[], int offset, int length, String charsetName) - throws UnsupportedEncodingException - { - if (charsetName == null) - throw new NullPointerException("charsetName"); - checkBounds(bytes, offset, length); - char[] v = StringCoding.decode(charsetName, bytes, offset, length); - this.offset = 0; - this.count = v.length; - this.value = v; - } - - /** - * Constructs a new {@code String} by decoding the specified subarray of - * bytes using the specified {@linkplain java.nio.charset.Charset charset}. - * The length of the new {@code String} is a function of the charset, and - * hence may not be equal to the length of the subarray. - * - * <p> This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement string. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @param offset - * The index of the first byte to decode - * - * @param length - * The number of bytes to decode - * - * @param charset - * The {@linkplain java.nio.charset.Charset charset} to be used to - * decode the {@code bytes} - * - * @throws IndexOutOfBoundsException - * If the {@code offset} and {@code length} arguments index - * characters outside the bounds of the {@code bytes} array - * - * @since 1.6 - */ - public String(byte bytes[], int offset, int length, Charset charset) { - if (charset == null) - throw new NullPointerException("charset"); - checkBounds(bytes, offset, length); - char[] v = StringCoding.decode(charset, bytes, offset, length); - this.offset = 0; - this.count = v.length; - this.value = v; - } - - /** - * Constructs a new {@code String} by decoding the specified array of bytes - * using the specified {@linkplain java.nio.charset.Charset charset}. The - * length of the new {@code String} is a function of the charset, and hence - * may not be equal to the length of the byte array. - * - * <p> The behavior of this constructor when the given bytes are not valid - * in the given charset is unspecified. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @param charsetName - * The name of a supported {@linkplain java.nio.charset.Charset - * charset} - * - * @throws UnsupportedEncodingException - * If the named charset is not supported - * - * @since JDK1.1 - */ - public String(byte bytes[], String charsetName) - throws UnsupportedEncodingException - { - this(bytes, 0, bytes.length, charsetName); - } - - /** - * Constructs a new {@code String} by decoding the specified array of - * bytes using the specified {@linkplain java.nio.charset.Charset charset}. - * The length of the new {@code String} is a function of the charset, and - * hence may not be equal to the length of the byte array. - * - * <p> This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement string. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @param charset - * The {@linkplain java.nio.charset.Charset charset} to be used to - * decode the {@code bytes} - * - * @since 1.6 - */ - public String(byte bytes[], Charset charset) { - this(bytes, 0, bytes.length, charset); - } - - /** - * Constructs a new {@code String} by decoding the specified subarray of - * bytes using the platform's default charset. The length of the new - * {@code String} is a function of the charset, and hence may not be equal - * to the length of the subarray. - * - * <p> The behavior of this constructor when the given bytes are not valid - * in the default charset is unspecified. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @param offset - * The index of the first byte to decode - * - * @param length - * The number of bytes to decode - * - * @throws IndexOutOfBoundsException - * If the {@code offset} and the {@code length} arguments index - * characters outside the bounds of the {@code bytes} array - * - * @since JDK1.1 - */ - public String(byte bytes[], int offset, int length) { - checkBounds(bytes, offset, length); - char[] v = StringCoding.decode(bytes, offset, length); - this.offset = 0; - this.count = v.length; - this.value = v; - } - - /** - * Constructs a new {@code String} by decoding the specified array of bytes - * using the platform's default charset. The length of the new {@code - * String} is a function of the charset, and hence may not be equal to the - * length of the byte array. - * - * <p> The behavior of this constructor when the given bytes are not valid - * in the default charset is unspecified. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - * - * @param bytes - * The bytes to be decoded into characters - * - * @since JDK1.1 - */ - public String(byte bytes[]) { - this(bytes, 0, bytes.length); - } - - /** - * Allocates a new string that contains the sequence of characters - * currently contained in the string buffer argument. The contents of the - * string buffer are copied; subsequent modification of the string buffer - * does not affect the newly created string. - * - * @param buffer - * A {@code StringBuffer} - */ - public String(StringBuffer buffer) { - String result = buffer.toString(); - this.value = result.value; - this.count = result.count; - this.offset = result.offset; - } - - /** - * Allocates a new string that contains the sequence of characters - * currently contained in the string builder argument. The contents of the - * string builder are copied; subsequent modification of the string builder - * does not affect the newly created string. - * - * <p> This constructor is provided to ease migration to {@code - * StringBuilder}. Obtaining a string from a string builder via the {@code - * toString} method is likely to run faster and is generally preferred. - * - * @param builder - * A {@code StringBuilder} - * - * @since 1.5 - */ - public String(StringBuilder builder) { - String result = builder.toString(); - this.value = result.value; - this.count = result.count; - this.offset = result.offset; - } - - - // Package private constructor which shares value array for speed. - String(int offset, int count, char value[]) { - this.value = value; - this.offset = offset; - this.count = count; - } - - /** - * Returns the length of this string. - * The length is equal to the number of <a href="Character.html#unicode">Unicode - * code units</a> in the string. - * - * @return the length of the sequence of characters represented by this - * object. - */ - public int length() { - return count; - } - - /** - * Returns <tt>true</tt> if, and only if, {@link #length()} is <tt>0</tt>. - * - * @return <tt>true</tt> if {@link #length()} is <tt>0</tt>, otherwise - * <tt>false</tt> - * - * @since 1.6 - */ - public boolean isEmpty() { - return count == 0; - } - - /** - * Returns the <code>char</code> value at the - * specified index. An index ranges from <code>0</code> to - * <code>length() - 1</code>. The first <code>char</code> value of the sequence - * is at index <code>0</code>, the next at index <code>1</code>, - * and so on, as for array indexing. - * - * <p>If the <code>char</code> value specified by the index is a - * <a href="Character.html#unicode">surrogate</a>, the surrogate - * value is returned. - * - * @param index the index of the <code>char</code> value. - * @return the <code>char</code> value at the specified index of this string. - * The first <code>char</code> value is at index <code>0</code>. - * @exception IndexOutOfBoundsException if the <code>index</code> - * argument is negative or not less than the length of this - * string. - */ - public char charAt(int index) { - if ((index < 0) || (index >= count)) { - throw new StringIndexOutOfBoundsException(index); - } - return value[index + offset]; - } - - /** - * Returns the character (Unicode code point) at the specified - * index. The index refers to <code>char</code> values - * (Unicode code units) and ranges from <code>0</code> to - * {@link #length()}<code> - 1</code>. - * - * <p> If the <code>char</code> value specified at the given index - * is in the high-surrogate range, the following index is less - * than the length of this <code>String</code>, and the - * <code>char</code> value at the following index is in the - * low-surrogate range, then the supplementary code point - * corresponding to this surrogate pair is returned. Otherwise, - * the <code>char</code> value at the given index is returned. - * - * @param index the index to the <code>char</code> values - * @return the code point value of the character at the - * <code>index</code> - * @exception IndexOutOfBoundsException if the <code>index</code> - * argument is negative or not less than the length of this - * string. - * @since 1.5 - */ - public int codePointAt(int index) { - if ((index < 0) || (index >= count)) { - throw new StringIndexOutOfBoundsException(index); - } - return Character.codePointAtImpl(value, offset + index, offset + count); - } - - /** - * Returns the character (Unicode code point) before the specified - * index. The index refers to <code>char</code> values - * (Unicode code units) and ranges from <code>1</code> to {@link - * CharSequence#length() length}. - * - * <p> If the <code>char</code> value at <code>(index - 1)</code> - * is in the low-surrogate range, <code>(index - 2)</code> is not - * negative, and the <code>char</code> value at <code>(index - - * 2)</code> is in the high-surrogate range, then the - * supplementary code point value of the surrogate pair is - * returned. If the <code>char</code> value at <code>index - - * 1</code> is an unpaired low-surrogate or a high-surrogate, the - * surrogate value is returned. - * - * @param index the index following the code point that should be returned - * @return the Unicode code point value before the given index. - * @exception IndexOutOfBoundsException if the <code>index</code> - * argument is less than 1 or greater than the length - * of this string. - * @since 1.5 - */ - public int codePointBefore(int index) { - int i = index - 1; - if ((i < 0) || (i >= count)) { - throw new StringIndexOutOfBoundsException(index); - } - return Character.codePointBeforeImpl(value, offset + index, offset); - } - - /** - * Returns the number of Unicode code points in the specified text - * range of this <code>String</code>. The text range begins at the - * specified <code>beginIndex</code> and extends to the - * <code>char</code> at index <code>endIndex - 1</code>. Thus the - * length (in <code>char</code>s) of the text range is - * <code>endIndex-beginIndex</code>. Unpaired surrogates within - * the text range count as one code point each. - * - * @param beginIndex the index to the first <code>char</code> of - * the text range. - * @param endIndex the index after the last <code>char</code> of - * the text range. - * @return the number of Unicode code points in the specified text - * range - * @exception IndexOutOfBoundsException if the - * <code>beginIndex</code> is negative, or <code>endIndex</code> - * is larger than the length of this <code>String</code>, or - * <code>beginIndex</code> is larger than <code>endIndex</code>. - * @since 1.5 - */ - public int codePointCount(int beginIndex, int endIndex) { - if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { - throw new IndexOutOfBoundsException(); - } - return Character.codePointCountImpl(value, offset+beginIndex, endIndex-beginIndex); - } - - /** - * Returns the index within this <code>String</code> that is - * offset from the given <code>index</code> by - * <code>codePointOffset</code> code points. Unpaired surrogates - * within the text range given by <code>index</code> and - * <code>codePointOffset</code> count as one code point each. - * - * @param index the index to be offset - * @param codePointOffset the offset in code points - * @return the index within this <code>String</code> - * @exception IndexOutOfBoundsException if <code>index</code> - * is negative or larger then the length of this - * <code>String</code>, or if <code>codePointOffset</code> is positive - * and the substring starting with <code>index</code> has fewer - * than <code>codePointOffset</code> code points, - * or if <code>codePointOffset</code> is negative and the substring - * before <code>index</code> has fewer than the absolute value - * of <code>codePointOffset</code> code points. - * @since 1.5 - */ - public int offsetByCodePoints(int index, int codePointOffset) { - if (index < 0 || index > count) { - throw new IndexOutOfBoundsException(); - } - return Character.offsetByCodePointsImpl(value, offset, count, - offset+index, codePointOffset) - offset; - } - - /** - * Copy characters from this string into dst starting at dstBegin. - * This method doesn't perform any range checking. - */ - void getChars(char dst[], int dstBegin) { - System.arraycopy(value, offset, dst, dstBegin, count); - } - - /** - * Copies characters from this string into the destination character - * array. - * <p> - * The first character to be copied is at index <code>srcBegin</code>; - * the last character to be copied is at index <code>srcEnd-1</code> - * (thus the total number of characters to be copied is - * <code>srcEnd-srcBegin</code>). The characters are copied into the - * subarray of <code>dst</code> starting at index <code>dstBegin</code> - * and ending at index: - * <p><blockquote><pre> - * dstbegin + (srcEnd-srcBegin) - 1 - * </pre></blockquote> - * - * @param srcBegin index of the first character in the string - * to copy. - * @param srcEnd index after the last character in the string - * to copy. - * @param dst the destination array. - * @param dstBegin the start offset in the destination array. - * @exception IndexOutOfBoundsException If any of the following - * is true: - * <ul><li><code>srcBegin</code> is negative. - * <li><code>srcBegin</code> is greater than <code>srcEnd</code> - * <li><code>srcEnd</code> is greater than the length of this - * string - * <li><code>dstBegin</code> is negative - * <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than - * <code>dst.length</code></ul> - */ - public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { - if (srcBegin < 0) { - throw new StringIndexOutOfBoundsException(srcBegin); - } - if (srcEnd > count) { - throw new StringIndexOutOfBoundsException(srcEnd); - } - if (srcBegin > srcEnd) { - throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); - } - System.arraycopy(value, offset + srcBegin, dst, dstBegin, - srcEnd - srcBegin); - } - - /** - * Copies characters from this string into the destination byte array. Each - * byte receives the 8 low-order bits of the corresponding character. The - * eight high-order bits of each character are not copied and do not - * participate in the transfer in any way. - * - * <p> The first character to be copied is at index {@code srcBegin}; the - * last character to be copied is at index {@code srcEnd-1}. The total - * number of characters to be copied is {@code srcEnd-srcBegin}. The - * characters, converted to bytes, are copied into the subarray of {@code - * dst} starting at index {@code dstBegin} and ending at index: - * - * <blockquote><pre> - * dstbegin + (srcEnd-srcBegin) - 1 - * </pre></blockquote> - * - * @deprecated This method does not properly convert characters into - * bytes. As of JDK 1.1, the preferred way to do this is via the - * {@link #getBytes()} method, which uses the platform's default charset. - * - * @param srcBegin - * Index of the first character in the string to copy - * - * @param srcEnd - * Index after the last character in the string to copy - * - * @param dst - * The destination array - * - * @param dstBegin - * The start offset in the destination array - * - * @throws IndexOutOfBoundsException - * If any of the following is true: - * <ul> - * <li> {@code srcBegin} is negative - * <li> {@code srcBegin} is greater than {@code srcEnd} - * <li> {@code srcEnd} is greater than the length of this String - * <li> {@code dstBegin} is negative - * <li> {@code dstBegin+(srcEnd-srcBegin)} is larger than {@code - * dst.length} - * </ul> - */ - @Deprecated - public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) { - if (srcBegin < 0) { - throw new StringIndexOutOfBoundsException(srcBegin); - } - if (srcEnd > count) { - throw new StringIndexOutOfBoundsException(srcEnd); - } - if (srcBegin > srcEnd) { - throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); - } - int j = dstBegin; - int n = offset + srcEnd; - int i = offset + srcBegin; - char[] val = value; /* avoid getfield opcode */ - - while (i < n) { - dst[j++] = (byte)val[i++]; - } - } - - /** - * Encodes this {@code String} into a sequence of bytes using the named - * charset, storing the result into a new byte array. - * - * <p> The behavior of this method when this string cannot be encoded in - * the given charset is unspecified. The {@link - * java.nio.charset.CharsetEncoder} class should be used when more control - * over the encoding process is required. - * - * @param charsetName - * The name of a supported {@linkplain java.nio.charset.Charset - * charset} - * - * @return The resultant byte array - * - * @throws UnsupportedEncodingException - * If the named charset is not supported - * - * @since JDK1.1 - */ - public byte[] getBytes(String charsetName) - throws UnsupportedEncodingException - { - if (charsetName == null) throw new NullPointerException(); - return StringCoding.encode(charsetName, value, offset, count); - } - - /** - * Encodes this {@code String} into a sequence of bytes using the given - * {@linkplain java.nio.charset.Charset charset}, storing the result into a - * new byte array. - * - * <p> This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement byte array. The - * {@link java.nio.charset.CharsetEncoder} class should be used when more - * control over the encoding process is required. - * - * @param charset - * The {@linkplain java.nio.charset.Charset} to be used to encode - * the {@code String} - * - * @return The resultant byte array - * - * @since 1.6 - */ - public byte[] getBytes(Charset charset) { - if (charset == null) throw new NullPointerException(); - return StringCoding.encode(charset, value, offset, count); - } - - /** - * Encodes this {@code String} into a sequence of bytes using the - * platform's default charset, storing the result into a new byte array. - * - * <p> The behavior of this method when this string cannot be encoded in - * the default charset is unspecified. The {@link - * java.nio.charset.CharsetEncoder} class should be used when more control - * over the encoding process is required. - * - * @return The resultant byte array - * - * @since JDK1.1 - */ - public byte[] getBytes() { - return StringCoding.encode(value, offset, count); - } - - /** - * Compares this string to the specified object. The result is {@code - * true} if and only if the argument is not {@code null} and is a {@code - * String} object that represents the same sequence of characters as this - * object. - * - * @param anObject - * The object to compare this {@code String} against - * - * @return {@code true} if the given object represents a {@code String} - * equivalent to this string, {@code false} otherwise - * - * @see #compareTo(String) - * @see #equalsIgnoreCase(String) - */ - public boolean equals(Object anObject) { - if (this == anObject) { - return true; - } - if (anObject instanceof String) { - String anotherString = (String)anObject; - int n = count; - if (n == anotherString.count) { - char v1[] = value; - char v2[] = anotherString.value; - int i = offset; - int j = anotherString.offset; - while (n-- != 0) { - if (v1[i++] != v2[j++]) - return false; - } - return true; - } - } - return false; - } - - /** - * Compares this string to the specified {@code StringBuffer}. The result - * is {@code true} if and only if this {@code String} represents the same - * sequence of characters as the specified {@code StringBuffer}. - * - * @param sb - * The {@code StringBuffer} to compare this {@code String} against - * - * @return {@code true} if this {@code String} represents the same - * sequence of characters as the specified {@code StringBuffer}, - * {@code false} otherwise - * - * @since 1.4 - */ - public boolean contentEquals(StringBuffer sb) { - synchronized(sb) { - return contentEquals((CharSequence)sb); - } - } - - /** - * Compares this string to the specified {@code CharSequence}. The result - * is {@code true} if and only if this {@code String} represents the same - * sequence of char values as the specified sequence. - * - * @param cs - * The sequence to compare this {@code String} against - * - * @return {@code true} if this {@code String} represents the same - * sequence of char values as the specified sequence, {@code - * false} otherwise - * - * @since 1.5 - */ - public boolean contentEquals(CharSequence cs) { - if (count != cs.length()) - return false; - // Argument is a StringBuffer, StringBuilder - if (cs instanceof AbstractStringBuilder) { - char v1[] = value; - char v2[] = ((AbstractStringBuilder)cs).getValue(); - int i = offset; - int j = 0; - int n = count; - while (n-- != 0) { - if (v1[i++] != v2[j++]) - return false; - } - return true; - } - // Argument is a String - if (cs.equals(this)) - return true; - // Argument is a generic CharSequence - char v1[] = value; - int i = offset; - int j = 0; - int n = count; - while (n-- != 0) { - if (v1[i++] != cs.charAt(j++)) - return false; - } - return true; - } - - /** - * Compares this {@code String} to another {@code String}, ignoring case - * considerations. Two strings are considered equal ignoring case if they - * are of the same length and corresponding characters in the two strings - * are equal ignoring case. - * - * <p> Two characters {@code c1} and {@code c2} are considered the same - * ignoring case if at least one of the following is true: - * <ul> - * <li> The two characters are the same (as compared by the - * {@code ==} operator) - * <li> Applying the method {@link - * java.lang.Character#toUpperCase(char)} to each character - * produces the same result - * <li> Applying the method {@link - * java.lang.Character#toLowerCase(char)} to each character - * produces the same result - * </ul> - * - * @param anotherString - * The {@code String} to compare this {@code String} against - * - * @return {@code true} if the argument is not {@code null} and it - * represents an equivalent {@code String} ignoring case; {@code - * false} otherwise - * - * @see #equals(Object) - */ - public boolean equalsIgnoreCase(String anotherString) { - return (this == anotherString) ? true : - (anotherString != null) && (anotherString.count == count) && - regionMatches(true, 0, anotherString, 0, count); - } - - /** - * Compares two strings lexicographically. - * The comparison is based on the Unicode value of each character in - * the strings. The character sequence represented by this - * <code>String</code> object is compared lexicographically to the - * character sequence represented by the argument string. The result is - * a negative integer if this <code>String</code> object - * lexicographically precedes the argument string. The result is a - * positive integer if this <code>String</code> object lexicographically - * follows the argument string. The result is zero if the strings - * are equal; <code>compareTo</code> returns <code>0</code> exactly when - * the {@link #equals(Object)} method would return <code>true</code>. - * <p> - * This is the definition of lexicographic ordering. If two strings are - * different, then either they have different characters at some index - * that is a valid index for both strings, or their lengths are different, - * or both. If they have different characters at one or more index - * positions, let <i>k</i> be the smallest such index; then the string - * whose character at position <i>k</i> has the smaller value, as - * determined by using the < operator, lexicographically precedes the - * other string. In this case, <code>compareTo</code> returns the - * difference of the two character values at position <code>k</code> in - * the two string -- that is, the value: - * <blockquote><pre> - * this.charAt(k)-anotherString.charAt(k) - * </pre></blockquote> - * If there is no index position at which they differ, then the shorter - * string lexicographically precedes the longer string. In this case, - * <code>compareTo</code> returns the difference of the lengths of the - * strings -- that is, the value: - * <blockquote><pre> - * this.length()-anotherString.length() - * </pre></blockquote> - * - * @param anotherString the <code>String</code> to be compared. - * @return the value <code>0</code> if the argument string is equal to - * this string; a value less than <code>0</code> if this string - * is lexicographically less than the string argument; and a - * value greater than <code>0</code> if this string is - * lexicographically greater than the string argument. - */ - public int compareTo(String anotherString) { - int len1 = count; - int len2 = anotherString.count; - int n = Math.min(len1, len2); - char v1[] = value; - char v2[] = anotherString.value; - int i = offset; - int j = anotherString.offset; - - if (i == j) { - int k = i; - int lim = n + i; - while (k < lim) { - char c1 = v1[k]; - char c2 = v2[k]; - if (c1 != c2) { - return c1 - c2; - } - k++; - } - } else { - while (n-- != 0) { - char c1 = v1[i++]; - char c2 = v2[j++]; - if (c1 != c2) { - return c1 - c2; - } - } - } - return len1 - len2; - } - - /** - * A Comparator that orders <code>String</code> objects as by - * <code>compareToIgnoreCase</code>. This comparator is serializable. - * <p> - * Note that this Comparator does <em>not</em> take locale into account, - * and will result in an unsatisfactory ordering for certain locales. - * The java.text package provides <em>Collators</em> to allow - * locale-sensitive ordering. - * - * @see java.text.Collator#compare(String, String) - * @since 1.2 - */ - public static final Comparator<String> CASE_INSENSITIVE_ORDER - = new CaseInsensitiveComparator(); - private static class CaseInsensitiveComparator - implements Comparator<String>, java.io.Serializable { - // use serialVersionUID from JDK 1.2.2 for interoperability - private static final long serialVersionUID = 8575799808933029326L; - - public int compare(String s1, String s2) { - int n1 = s1.length(); - int n2 = s2.length(); - int min = Math.min(n1, n2); - for (int i = 0; i < min; i++) { - char c1 = s1.charAt(i); - char c2 = s2.charAt(i); - if (c1 != c2) { - c1 = Character.toUpperCase(c1); - c2 = Character.toUpperCase(c2); - if (c1 != c2) { - c1 = Character.toLowerCase(c1); - c2 = Character.toLowerCase(c2); - if (c1 != c2) { - // No overflow because of numeric promotion - return c1 - c2; - } - } - } - } - return n1 - n2; - } - } - - /** - * Compares two strings lexicographically, ignoring case - * differences. This method returns an integer whose sign is that of - * calling <code>compareTo</code> with normalized versions of the strings - * where case differences have been eliminated by calling - * <code>Character.toLowerCase(Character.toUpperCase(character))</code> on - * each character. - * <p> - * Note that this method does <em>not</em> take locale into account, - * and will result in an unsatisfactory ordering for certain locales. - * The java.text package provides <em>collators</em> to allow - * locale-sensitive ordering. - * - * @param str the <code>String</code> to be compared. - * @return a negative integer, zero, or a positive integer as the - * specified String is greater than, equal to, or less - * than this String, ignoring case considerations. - * @see java.text.Collator#compare(String, String) - * @since 1.2 - */ - public int compareToIgnoreCase(String str) { - return CASE_INSENSITIVE_ORDER.compare(this, str); - } - - /** - * Tests if two string regions are equal. - * <p> - * A substring of this <tt>String</tt> object is compared to a substring - * of the argument other. The result is true if these substrings - * represent identical character sequences. The substring of this - * <tt>String</tt> object to be compared begins at index <tt>toffset</tt> - * and has length <tt>len</tt>. The substring of other to be compared - * begins at index <tt>ooffset</tt> and has length <tt>len</tt>. The - * result is <tt>false</tt> if and only if at least one of the following - * is true: - * <ul><li><tt>toffset</tt> is negative. - * <li><tt>ooffset</tt> is negative. - * <li><tt>toffset+len</tt> is greater than the length of this - * <tt>String</tt> object. - * <li><tt>ooffset+len</tt> is greater than the length of the other - * argument. - * <li>There is some nonnegative integer <i>k</i> less than <tt>len</tt> - * such that: - * <tt>this.charAt(toffset+<i>k</i>) != other.charAt(ooffset+<i>k</i>)</tt> - * </ul> - * - * @param toffset the starting offset of the subregion in this string. - * @param other the string argument. - * @param ooffset the starting offset of the subregion in the string - * argument. - * @param len the number of characters to compare. - * @return <code>true</code> if the specified subregion of this string - * exactly matches the specified subregion of the string argument; - * <code>false</code> otherwise. - */ - public boolean regionMatches(int toffset, String other, int ooffset, - int len) { - char ta[] = value; - int to = offset + toffset; - char pa[] = other.value; - int po = other.offset + ooffset; - // Note: toffset, ooffset, or len might be near -1>>>1. - if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) - || (ooffset > (long)other.count - len)) { - return false; - } - while (len-- > 0) { - if (ta[to++] != pa[po++]) { - return false; - } - } - return true; - } - - /** - * Tests if two string regions are equal. - * <p> - * A substring of this <tt>String</tt> object is compared to a substring - * of the argument <tt>other</tt>. The result is <tt>true</tt> if these - * substrings represent character sequences that are the same, ignoring - * case if and only if <tt>ignoreCase</tt> is true. The substring of - * this <tt>String</tt> object to be compared begins at index - * <tt>toffset</tt> and has length <tt>len</tt>. The substring of - * <tt>other</tt> to be compared begins at index <tt>ooffset</tt> and - * has length <tt>len</tt>. The result is <tt>false</tt> if and only if - * at least one of the following is true: - * <ul><li><tt>toffset</tt> is negative. - * <li><tt>ooffset</tt> is negative. - * <li><tt>toffset+len</tt> is greater than the length of this - * <tt>String</tt> object. - * <li><tt>ooffset+len</tt> is greater than the length of the other - * argument. - * <li><tt>ignoreCase</tt> is <tt>false</tt> and there is some nonnegative - * integer <i>k</i> less than <tt>len</tt> such that: - * <blockquote><pre> - * this.charAt(toffset+k) != other.charAt(ooffset+k) - * </pre></blockquote> - * <li><tt>ignoreCase</tt> is <tt>true</tt> and there is some nonnegative - * integer <i>k</i> less than <tt>len</tt> such that: - * <blockquote><pre> - * Character.toLowerCase(this.charAt(toffset+k)) != - Character.toLowerCase(other.charAt(ooffset+k)) - * </pre></blockquote> - * and: - * <blockquote><pre> - * Character.toUpperCase(this.charAt(toffset+k)) != - * Character.toUpperCase(other.charAt(ooffset+k)) - * </pre></blockquote> - * </ul> - * - * @param ignoreCase if <code>true</code>, ignore case when comparing - * characters. - * @param toffset the starting offset of the subregion in this - * string. - * @param other the string argument. - * @param ooffset the starting offset of the subregion in the string - * argument. - * @param len the number of characters to compare. - * @return <code>true</code> if the specified subregion of this string - * matches the specified subregion of the string argument; - * <code>false</code> otherwise. Whether the matching is exact - * or case insensitive depends on the <code>ignoreCase</code> - * argument. - */ - public boolean regionMatches(boolean ignoreCase, int toffset, - String other, int ooffset, int len) { - char ta[] = value; - int to = offset + toffset; - char pa[] = other.value; - int po = other.offset + ooffset; - // Note: toffset, ooffset, or len might be near -1>>>1. - if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) || - (ooffset > (long)other.count - len)) { - return false; - } - while (len-- > 0) { - char c1 = ta[to++]; - char c2 = pa[po++]; - if (c1 == c2) { - continue; - } - if (ignoreCase) { - // If characters don't match but case may be ignored, - // try converting both characters to uppercase. - // If the results match, then the comparison scan should - // continue. - char u1 = Character.toUpperCase(c1); - char u2 = Character.toUpperCase(c2); - if (u1 == u2) { - continue; - } - // Unfortunately, conversion to uppercase does not work properly - // for the Georgian alphabet, which has strange rules about case - // conversion. So we need to make one last check before - // exiting. - if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { - continue; - } - } - return false; - } - return true; - } - - /** - * Tests if the substring of this string beginning at the - * specified index starts with the specified prefix. - * - * @param prefix the prefix. - * @param toffset where to begin looking in this string. - * @return <code>true</code> if the character sequence represented by the - * argument is a prefix of the substring of this object starting - * at index <code>toffset</code>; <code>false</code> otherwise. - * The result is <code>false</code> if <code>toffset</code> is - * negative or greater than the length of this - * <code>String</code> object; otherwise the result is the same - * as the result of the expression - * <pre> - * this.substring(toffset).startsWith(prefix) - * </pre> - */ - public boolean startsWith(String prefix, int toffset) { - char ta[] = value; - int to = offset + toffset; - char pa[] = prefix.value; - int po = prefix.offset; - int pc = prefix.count; - // Note: toffset might be near -1>>>1. - if ((toffset < 0) || (toffset > count - pc)) { - return false; - } - while (--pc >= 0) { - if (ta[to++] != pa[po++]) { - return false; - } - } - return true; - } - - /** - * Tests if this string starts with the specified prefix. - * - * @param prefix the prefix. - * @return <code>true</code> if the character sequence represented by the - * argument is a prefix of the character sequence represented by - * this string; <code>false</code> otherwise. - * Note also that <code>true</code> will be returned if the - * argument is an empty string or is equal to this - * <code>String</code> object as determined by the - * {@link #equals(Object)} method. - * @since 1. 0 - */ - public boolean startsWith(String prefix) { - return startsWith(prefix, 0); - } - - /** - * Tests if this string ends with the specified suffix. - * - * @param suffix the suffix. - * @return <code>true</code> if the character sequence represented by the - * argument is a suffix of the character sequence represented by - * this object; <code>false</code> otherwise. Note that the - * result will be <code>true</code> if the argument is the - * empty string or is equal to this <code>String</code> object - * as determined by the {@link #equals(Object)} method. - */ - public boolean endsWith(String suffix) { - return startsWith(suffix, count - suffix.count); - } - - /** - * Returns a hash code for this string. The hash code for a - * <code>String</code> object is computed as - * <blockquote><pre> - * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] - * </pre></blockquote> - * using <code>int</code> arithmetic, where <code>s[i]</code> is the - * <i>i</i>th character of the string, <code>n</code> is the length of - * the string, and <code>^</code> indicates exponentiation. - * (The hash value of the empty string is zero.) - * - * @return a hash code value for this object. - */ - public int hashCode() { - int h = hash; - if (h == 0 && count > 0) { - int off = offset; - char val[] = value; - int len = count; - - for (int i = 0; i < len; i++) { - h = 31*h + val[off++]; - } - hash = h; - } - return h; - } - - /** - * Returns the index within this string of the first occurrence of - * the specified character. If a character with value - * <code>ch</code> occurs in the character sequence represented by - * this <code>String</code> object, then the index (in Unicode - * code units) of the first such occurrence is returned. For - * values of <code>ch</code> in the range from 0 to 0xFFFF - * (inclusive), this is the smallest value <i>k</i> such that: - * <blockquote><pre> - * this.charAt(<i>k</i>) == ch - * </pre></blockquote> - * is true. For other values of <code>ch</code>, it is the - * smallest value <i>k</i> such that: - * <blockquote><pre> - * this.codePointAt(<i>k</i>) == ch - * </pre></blockquote> - * is true. In either case, if no such character occurs in this - * string, then <code>-1</code> is returned. - * - * @param ch a character (Unicode code point). - * @return the index of the first occurrence of the character in the - * character sequence represented by this object, or - * <code>-1</code> if the character does not occur. - */ - public int indexOf(int ch) { - return indexOf(ch, 0); - } - - /** - * Returns the index within this string of the first occurrence of the - * specified character, starting the search at the specified index. - * <p> - * If a character with value <code>ch</code> occurs in the - * character sequence represented by this <code>String</code> - * object at an index no smaller than <code>fromIndex</code>, then - * the index of the first such occurrence is returned. For values - * of <code>ch</code> in the range from 0 to 0xFFFF (inclusive), - * this is the smallest value <i>k</i> such that: - * <blockquote><pre> - * (this.charAt(<i>k</i>) == ch) && (<i>k</i> >= fromIndex) - * </pre></blockquote> - * is true. For other values of <code>ch</code>, it is the - * smallest value <i>k</i> such that: - * <blockquote><pre> - * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> >= fromIndex) - * </pre></blockquote> - * is true. In either case, if no such character occurs in this - * string at or after position <code>fromIndex</code>, then - * <code>-1</code> is returned. - * - * <p> - * There is no restriction on the value of <code>fromIndex</code>. If it - * is negative, it has the same effect as if it were zero: this entire - * string may be searched. If it is greater than the length of this - * string, it has the same effect as if it were equal to the length of - * this string: <code>-1</code> is returned. - * - * <p>All indices are specified in <code>char</code> values - * (Unicode code units). - * - * @param ch a character (Unicode code point). - * @param fromIndex the index to start the search from. - * @return the index of the first occurrence of the character in the - * character sequence represented by this object that is greater - * than or equal to <code>fromIndex</code>, or <code>-1</code> - * if the character does not occur. - */ - public int indexOf(int ch, int fromIndex) { - if (fromIndex < 0) { - fromIndex = 0; - } else if (fromIndex >= count) { - // Note: fromIndex might be near -1>>>1. - return -1; - } - - if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { - // handle most cases here (ch is a BMP code point or a - // negative value (invalid code point)) - final char[] value = this.value; - final int offset = this.offset; - final int max = offset + count; - for (int i = offset + fromIndex; i < max ; i++) { - if (value[i] == ch) { - return i - offset; - } - } - return -1; - } else { - return indexOfSupplementary(ch, fromIndex); - } - } - - /** - * Handles (rare) calls of indexOf with a supplementary character. - */ - private int indexOfSupplementary(int ch, int fromIndex) { - if (Character.isValidCodePoint(ch)) { - final char[] value = this.value; - final int offset = this.offset; - final char hi = Character.highSurrogate(ch); - final char lo = Character.lowSurrogate(ch); - final int max = offset + count - 1; - for (int i = offset + fromIndex; i < max; i++) { - if (value[i] == hi && value[i+1] == lo) { - return i - offset; - } - } - } - return -1; - } - - /** - * Returns the index within this string of the last occurrence of - * the specified character. For values of <code>ch</code> in the - * range from 0 to 0xFFFF (inclusive), the index (in Unicode code - * units) returned is the largest value <i>k</i> such that: - * <blockquote><pre> - * this.charAt(<i>k</i>) == ch - * </pre></blockquote> - * is true. For other values of <code>ch</code>, it is the - * largest value <i>k</i> such that: - * <blockquote><pre> - * this.codePointAt(<i>k</i>) == ch - * </pre></blockquote> - * is true. In either case, if no such character occurs in this - * string, then <code>-1</code> is returned. The - * <code>String</code> is searched backwards starting at the last - * character. - * - * @param ch a character (Unicode code point). - * @return the index of the last occurrence of the character in the - * character sequence represented by this object, or - * <code>-1</code> if the character does not occur. - */ - public int lastIndexOf(int ch) { - return lastIndexOf(ch, count - 1); - } - - /** - * Returns the index within this string of the last occurrence of - * the specified character, searching backward starting at the - * specified index. For values of <code>ch</code> in the range - * from 0 to 0xFFFF (inclusive), the index returned is the largest - * value <i>k</i> such that: - * <blockquote><pre> - * (this.charAt(<i>k</i>) == ch) && (<i>k</i> <= fromIndex) - * </pre></blockquote> - * is true. For other values of <code>ch</code>, it is the - * largest value <i>k</i> such that: - * <blockquote><pre> - * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> <= fromIndex) - * </pre></blockquote> - * is true. In either case, if no such character occurs in this - * string at or before position <code>fromIndex</code>, then - * <code>-1</code> is returned. - * - * <p>All indices are specified in <code>char</code> values - * (Unicode code units). - * - * @param ch a character (Unicode code point). - * @param fromIndex the index to start the search from. There is no - * restriction on the value of <code>fromIndex</code>. If it is - * greater than or equal to the length of this string, it has - * the same effect as if it were equal to one less than the - * length of this string: this entire string may be searched. - * If it is negative, it has the same effect as if it were -1: - * -1 is returned. - * @return the index of the last occurrence of the character in the - * character sequence represented by this object that is less - * than or equal to <code>fromIndex</code>, or <code>-1</code> - * if the character does not occur before that point. - */ - public int lastIndexOf(int ch, int fromIndex) { - if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { - // handle most cases here (ch is a BMP code point or a - // negative value (invalid code point)) - final char[] value = this.value; - final int offset = this.offset; - int i = offset + Math.min(fromIndex, count - 1); - for (; i >= offset ; i--) { - if (value[i] == ch) { - return i - offset; - } - } - return -1; - } else { - return lastIndexOfSupplementary(ch, fromIndex); - } - } - - /** - * Handles (rare) calls of lastIndexOf with a supplementary character. - */ - private int lastIndexOfSupplementary(int ch, int fromIndex) { - if (Character.isValidCodePoint(ch)) { - final char[] value = this.value; - final int offset = this.offset; - char hi = Character.highSurrogate(ch); - char lo = Character.lowSurrogate(ch); - int i = offset + Math.min(fromIndex, count - 2); - for (; i >= offset; i--) { - if (value[i] == hi && value[i+1] == lo) { - return i - offset; - } - } - } - return -1; - } - - /** - * Returns the index within this string of the first occurrence of the - * specified substring. - * - * <p>The returned index is the smallest value <i>k</i> for which: - * <blockquote><pre> - * this.startsWith(str, <i>k</i>) - * </pre></blockquote> - * If no such value of <i>k</i> exists, then {@code -1} is returned. - * - * @param str the substring to search for. - * @return the index of the first occurrence of the specified substring, - * or {@code -1} if there is no such occurrence. - */ - public int indexOf(String str) { - return indexOf(str, 0); - } - - /** - * Returns the index within this string of the first occurrence of the - * specified substring, starting at the specified index. - * - * <p>The returned index is the smallest value <i>k</i> for which: - * <blockquote><pre> - * <i>k</i> >= fromIndex && this.startsWith(str, <i>k</i>) - * </pre></blockquote> - * If no such value of <i>k</i> exists, then {@code -1} is returned. - * - * @param str the substring to search for. - * @param fromIndex the index from which to start the search. - * @return the index of the first occurrence of the specified substring, - * starting at the specified index, - * or {@code -1} if there is no such occurrence. - */ - public int indexOf(String str, int fromIndex) { - return indexOf(value, offset, count, - str.value, str.offset, str.count, fromIndex); - } - - /** - * Code shared by String and StringBuffer to do searches. The - * source is the character array being searched, and the target - * is the string being searched for. - * - * @param source the characters being searched. - * @param sourceOffset offset of the source string. - * @param sourceCount count of the source string. - * @param target the characters being searched for. - * @param targetOffset offset of the target string. - * @param targetCount count of the target string. - * @param fromIndex the index to begin searching from. - */ - static int indexOf(char[] source, int sourceOffset, int sourceCount, - char[] target, int targetOffset, int targetCount, - int fromIndex) { - if (fromIndex >= sourceCount) { - return (targetCount == 0 ? sourceCount : -1); - } - if (fromIndex < 0) { - fromIndex = 0; - } - if (targetCount == 0) { - return fromIndex; - } - - char first = target[targetOffset]; - int max = sourceOffset + (sourceCount - targetCount); - - for (int i = sourceOffset + fromIndex; i <= max; i++) { - /* Look for first character. */ - if (source[i] != first) { - while (++i <= max && source[i] != first); - } - - /* Found first character, now look at the rest of v2 */ - if (i <= max) { - int j = i + 1; - int end = j + targetCount - 1; - for (int k = targetOffset + 1; j < end && source[j] == - target[k]; j++, k++); - - if (j == end) { - /* Found whole string. */ - return i - sourceOffset; - } - } - } - return -1; - } - - /** - * Returns the index within this string of the last occurrence of the - * specified substring. The last occurrence of the empty string "" - * is considered to occur at the index value {@code this.length()}. - * - * <p>The returned index is the largest value <i>k</i> for which: - * <blockquote><pre> - * this.startsWith(str, <i>k</i>) - * </pre></blockquote> - * If no such value of <i>k</i> exists, then {@code -1} is returned. - * - * @param str the substring to search for. - * @return the index of the last occurrence of the specified substring, - * or {@code -1} if there is no such occurrence. - */ - public int lastIndexOf(String str) { - return lastIndexOf(str, count); - } - - /** - * Returns the index within this string of the last occurrence of the - * specified substring, searching backward starting at the specified index. - * - * <p>The returned index is the largest value <i>k</i> for which: - * <blockquote><pre> - * <i>k</i> <= fromIndex && this.startsWith(str, <i>k</i>) - * </pre></blockquote> - * If no such value of <i>k</i> exists, then {@code -1} is returned. - * - * @param str the substring to search for. - * @param fromIndex the index to start the search from. - * @return the index of the last occurrence of the specified substring, - * searching backward from the specified index, - * or {@code -1} if there is no such occurrence. - */ - public int lastIndexOf(String str, int fromIndex) { - return lastIndexOf(value, offset, count, - str.value, str.offset, str.count, fromIndex); - } - - /** - * Code shared by String and StringBuffer to do searches. The - * source is the character array being searched, and the target - * is the string being searched for. - * - * @param source the characters being searched. - * @param sourceOffset offset of the source string. - * @param sourceCount count of the source string. - * @param target the characters being searched for. - * @param targetOffset offset of the target string. - * @param targetCount count of the target string. - * @param fromIndex the index to begin searching from. - */ - static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, - char[] target, int targetOffset, int targetCount, - int fromIndex) { - /* - * Check arguments; return immediately where possible. For - * consistency, don't check for null str. - */ - int rightIndex = sourceCount - targetCount; - if (fromIndex < 0) { - return -1; - } - if (fromIndex > rightIndex) { - fromIndex = rightIndex; - } - /* Empty string always matches. */ - if (targetCount == 0) { - return fromIndex; - } - - int strLastIndex = targetOffset + targetCount - 1; - char strLastChar = target[strLastIndex]; - int min = sourceOffset + targetCount - 1; - int i = min + fromIndex; - - startSearchForLastChar: - while (true) { - while (i >= min && source[i] != strLastChar) { - i--; - } - if (i < min) { - return -1; - } - int j = i - 1; - int start = j - (targetCount - 1); - int k = strLastIndex - 1; - - while (j > start) { - if (source[j--] != target[k--]) { - i--; - continue startSearchForLastChar; - } - } - return start - sourceOffset + 1; - } - } - - /** - * Returns a new string that is a substring of this string. The - * substring begins with the character at the specified index and - * extends to the end of this string. <p> - * Examples: - * <blockquote><pre> - * "unhappy".substring(2) returns "happy" - * "Harbison".substring(3) returns "bison" - * "emptiness".substring(9) returns "" (an empty string) - * </pre></blockquote> - * - * @param beginIndex the beginning index, inclusive. - * @return the specified substring. - * @exception IndexOutOfBoundsException if - * <code>beginIndex</code> is negative or larger than the - * length of this <code>String</code> object. - */ - public String substring(int beginIndex) { - return substring(beginIndex, count); - } - - /** - * Returns a new string that is a substring of this string. The - * substring begins at the specified <code>beginIndex</code> and - * extends to the character at index <code>endIndex - 1</code>. - * Thus the length of the substring is <code>endIndex-beginIndex</code>. - * <p> - * Examples: - * <blockquote><pre> - * "hamburger".substring(4, 8) returns "urge" - * "smiles".substring(1, 5) returns "mile" - * </pre></blockquote> - * - * @param beginIndex the beginning index, inclusive. - * @param endIndex the ending index, exclusive. - * @return the specified substring. - * @exception IndexOutOfBoundsException if the - * <code>beginIndex</code> is negative, or - * <code>endIndex</code> is larger than the length of - * this <code>String</code> object, or - * <code>beginIndex</code> is larger than - * <code>endIndex</code>. - */ - public String substring(int beginIndex, int endIndex) { - if (beginIndex < 0) { - throw new StringIndexOutOfBoundsException(beginIndex); - } - if (endIndex > count) { - throw new StringIndexOutOfBoundsException(endIndex); - } - if (beginIndex > endIndex) { - throw new StringIndexOutOfBoundsException(endIndex - beginIndex); - } - return ((beginIndex == 0) && (endIndex == count)) ? this : - new String(offset + beginIndex, endIndex - beginIndex, value); - } - - /** - * Returns a new character sequence that is a subsequence of this sequence. - * - * <p> An invocation of this method of the form - * - * <blockquote><pre> - * str.subSequence(begin, end)</pre></blockquote> - * - * behaves in exactly the same way as the invocation - * - * <blockquote><pre> - * str.substring(begin, end)</pre></blockquote> - * - * This method is defined so that the <tt>String</tt> class can implement - * the {@link CharSequence} interface. </p> - * - * @param beginIndex the begin index, inclusive. - * @param endIndex the end index, exclusive. - * @return the specified subsequence. - * - * @throws IndexOutOfBoundsException - * if <tt>beginIndex</tt> or <tt>endIndex</tt> are negative, - * if <tt>endIndex</tt> is greater than <tt>length()</tt>, - * or if <tt>beginIndex</tt> is greater than <tt>startIndex</tt> - * - * @since 1.4 - * @spec JSR-51 - */ - public CharSequence subSequence(int beginIndex, int endIndex) { - return this.substring(beginIndex, endIndex); - } - - /** - * Concatenates the specified string to the end of this string. - * <p> - * If the length of the argument string is <code>0</code>, then this - * <code>String</code> object is returned. Otherwise, a new - * <code>String</code> object is created, representing a character - * sequence that is the concatenation of the character sequence - * represented by this <code>String</code> object and the character - * sequence represented by the argument string.<p> - * Examples: - * <blockquote><pre> - * "cares".concat("s") returns "caress" - * "to".concat("get").concat("her") returns "together" - * </pre></blockquote> - * - * @param str the <code>String</code> that is concatenated to the end - * of this <code>String</code>. - * @return a string that represents the concatenation of this object's - * characters followed by the string argument's characters. - */ - public String concat(String str) { - int otherLen = str.length(); - if (otherLen == 0) { - return this; - } - char buf[] = new char[count + otherLen]; - getChars(0, count, buf, 0); - str.getChars(0, otherLen, buf, count); - return new String(0, count + otherLen, buf); - } - - /** - * Returns a new string resulting from replacing all occurrences of - * <code>oldChar</code> in this string with <code>newChar</code>. - * <p> - * If the character <code>oldChar</code> does not occur in the - * character sequence represented by this <code>String</code> object, - * then a reference to this <code>String</code> object is returned. - * Otherwise, a new <code>String</code> object is created that - * represents a character sequence identical to the character sequence - * represented by this <code>String</code> object, except that every - * occurrence of <code>oldChar</code> is replaced by an occurrence - * of <code>newChar</code>. - * <p> - * Examples: - * <blockquote><pre> - * "mesquite in your cellar".replace('e', 'o') - * returns "mosquito in your collar" - * "the war of baronets".replace('r', 'y') - * returns "the way of bayonets" - * "sparring with a purple porpoise".replace('p', 't') - * returns "starring with a turtle tortoise" - * "JonL".replace('q', 'x') returns "JonL" (no change) - * </pre></blockquote> - * - * @param oldChar the old character. - * @param newChar the new character. - * @return a string derived from this string by replacing every - * occurrence of <code>oldChar</code> with <code>newChar</code>. - */ - public String replace(char oldChar, char newChar) { - if (oldChar != newChar) { - int len = count; - int i = -1; - char[] val = value; /* avoid getfield opcode */ - int off = offset; /* avoid getfield opcode */ - - while (++i < len) { - if (val[off + i] == oldChar) { - break; - } - } - if (i < len) { - char buf[] = new char[len]; - for (int j = 0 ; j < i ; j++) { - buf[j] = val[off+j]; - } - while (i < len) { - char c = val[off + i]; - buf[i] = (c == oldChar) ? newChar : c; - i++; - } - return new String(0, len, buf); - } - } - return this; - } - - /** - * Tells whether or not this string matches the given <a - * href="../util/regex/Pattern.html#sum">regular expression</a>. - * - * <p> An invocation of this method of the form - * <i>str</i><tt>.matches(</tt><i>regex</i><tt>)</tt> yields exactly the - * same result as the expression - * - * <blockquote><tt> {@link java.util.regex.Pattern}.{@link - * java.util.regex.Pattern#matches(String,CharSequence) - * matches}(</tt><i>regex</i><tt>,</tt> <i>str</i><tt>)</tt></blockquote> - * - * @param regex - * the regular expression to which this string is to be matched - * - * @return <tt>true</tt> if, and only if, this string matches the - * given regular expression - * - * @throws PatternSyntaxException - * if the regular expression's syntax is invalid - * - * @see java.util.regex.Pattern - * - * @since 1.4 - * @spec JSR-51 - */ - public boolean matches(String regex) { - return Pattern.matches(regex, this); - } - - /** - * Returns true if and only if this string contains the specified - * sequence of char values. - * - * @param s the sequence to search for - * @return true if this string contains <code>s</code>, false otherwise - * @throws NullPointerException if <code>s</code> is <code>null</code> - * @since 1.5 - */ - public boolean contains(CharSequence s) { - return indexOf(s.toString()) > -1; - } - - /** - * Replaces the first substring of this string that matches the given <a - * href="../util/regex/Pattern.html#sum">regular expression</a> with the - * given replacement. - * - * <p> An invocation of this method of the form - * <i>str</i><tt>.replaceFirst(</tt><i>regex</i><tt>,</tt> <i>repl</i><tt>)</tt> - * yields exactly the same result as the expression - * - * <blockquote><tt> - * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile - * compile}(</tt><i>regex</i><tt>).{@link - * java.util.regex.Pattern#matcher(java.lang.CharSequence) - * matcher}(</tt><i>str</i><tt>).{@link java.util.regex.Matcher#replaceFirst - * replaceFirst}(</tt><i>repl</i><tt>)</tt></blockquote> - * - *<p> - * Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in the - * replacement string may cause the results to be different than if it were - * being treated as a literal replacement string; see - * {@link java.util.regex.Matcher#replaceFirst}. - * Use {@link java.util.regex.Matcher#quoteReplacement} to suppress the special - * meaning of these characters, if desired. - * - * @param regex - * the regular expression to which this string is to be matched - * @param replacement - * the string to be substituted for the first match - * - * @return The resulting <tt>String</tt> - * - * @throws PatternSyntaxException - * if the regular expression's syntax is invalid - * - * @see java.util.regex.Pattern - * - * @since 1.4 - * @spec JSR-51 - */ - public String replaceFirst(String regex, String replacement) { - return Pattern.compile(regex).matcher(this).replaceFirst(replacement); - } - - /** - * Replaces each substring of this string that matches the given <a - * href="../util/regex/Pattern.html#sum">regular expression</a> with the - * given replacement. - * - * <p> An invocation of this method of the form - * <i>str</i><tt>.replaceAll(</tt><i>regex</i><tt>,</tt> <i>repl</i><tt>)</tt> - * yields exactly the same result as the expression - * - * <blockquote><tt> - * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile - * compile}(</tt><i>regex</i><tt>).{@link - * java.util.regex.Pattern#matcher(java.lang.CharSequence) - * matcher}(</tt><i>str</i><tt>).{@link java.util.regex.Matcher#replaceAll - * replaceAll}(</tt><i>repl</i><tt>)</tt></blockquote> - * - *<p> - * Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in the - * replacement string may cause the results to be different than if it were - * being treated as a literal replacement string; see - * {@link java.util.regex.Matcher#replaceAll Matcher.replaceAll}. - * Use {@link java.util.regex.Matcher#quoteReplacement} to suppress the special - * meaning of these characters, if desired. - * - * @param regex - * the regular expression to which this string is to be matched - * @param replacement - * the string to be substituted for each match - * - * @return The resulting <tt>String</tt> - * - * @throws PatternSyntaxException - * if the regular expression's syntax is invalid - * - * @see java.util.regex.Pattern - * - * @since 1.4 - * @spec JSR-51 - */ - public String replaceAll(String regex, String replacement) { - return Pattern.compile(regex).matcher(this).replaceAll(replacement); - } - - /** - * Replaces each substring of this string that matches the literal target - * sequence with the specified literal replacement sequence. The - * replacement proceeds from the beginning of the string to the end, for - * example, replacing "aa" with "b" in the string "aaa" will result in - * "ba" rather than "ab". - * - * @param target The sequence of char values to be replaced - * @param replacement The replacement sequence of char values - * @return The resulting string - * @throws NullPointerException if <code>target</code> or - * <code>replacement</code> is <code>null</code>. - * @since 1.5 - */ - public String replace(CharSequence target, CharSequence replacement) { - return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( - this).replaceAll(Matcher.quoteReplacement(replacement.toString())); - } - - /** - * Splits this string around matches of the given - * <a href="../util/regex/Pattern.html#sum">regular expression</a>. - * - * <p> The array returned by this method contains each substring of this - * string that is terminated by another substring that matches the given - * expression or is terminated by the end of the string. The substrings in - * the array are in the order in which they occur in this string. If the - * expression does not match any part of the input then the resulting array - * has just one element, namely this string. - * - * <p> The <tt>limit</tt> parameter controls the number of times the - * pattern is applied and therefore affects the length of the resulting - * array. If the limit <i>n</i> is greater than zero then the pattern - * will be applied at most <i>n</i> - 1 times, the array's - * length will be no greater than <i>n</i>, and the array's last entry - * will contain all input beyond the last matched delimiter. If <i>n</i> - * is non-positive then the pattern will be applied as many times as - * possible and the array can have any length. If <i>n</i> is zero then - * the pattern will be applied as many times as possible, the array can - * have any length, and trailing empty strings will be discarded. - * - * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the - * following results with these parameters: - * - * <blockquote><table cellpadding=1 cellspacing=0 summary="Split example showing regex, limit, and result"> - * <tr> - * <th>Regex</th> - * <th>Limit</th> - * <th>Result</th> - * </tr> - * <tr><td align=center>:</td> - * <td align=center>2</td> - * <td><tt>{ "boo", "and:foo" }</tt></td></tr> - * <tr><td align=center>:</td> - * <td align=center>5</td> - * <td><tt>{ "boo", "and", "foo" }</tt></td></tr> - * <tr><td align=center>:</td> - * <td align=center>-2</td> - * <td><tt>{ "boo", "and", "foo" }</tt></td></tr> - * <tr><td align=center>o</td> - * <td align=center>5</td> - * <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr> - * <tr><td align=center>o</td> - * <td align=center>-2</td> - * <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr> - * <tr><td align=center>o</td> - * <td align=center>0</td> - * <td><tt>{ "b", "", ":and:f" }</tt></td></tr> - * </table></blockquote> - * - * <p> An invocation of this method of the form - * <i>str.</i><tt>split(</tt><i>regex</i><tt>,</tt> <i>n</i><tt>)</tt> - * yields the same result as the expression - * - * <blockquote> - * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile - * compile}<tt>(</tt><i>regex</i><tt>)</tt>.{@link - * java.util.regex.Pattern#split(java.lang.CharSequence,int) - * split}<tt>(</tt><i>str</i><tt>,</tt> <i>n</i><tt>)</tt> - * </blockquote> - * - * - * @param regex - * the delimiting regular expression - * - * @param limit - * the result threshold, as described above - * - * @return the array of strings computed by splitting this string - * around matches of the given regular expression - * - * @throws PatternSyntaxException - * if the regular expression's syntax is invalid - * - * @see java.util.regex.Pattern - * - * @since 1.4 - * @spec JSR-51 - */ - public String[] split(String regex, int limit) { - /* fastpath if the regex is a - (1)one-char String and this character is not one of the - RegEx's meta characters ".$|()[{^?*+\\", or - (2)two-char String and the first char is the backslash and - the second is not the ascii digit or ascii letter. - */ - char ch = 0; - if (((regex.count == 1 && - ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || - (regex.length() == 2 && - regex.charAt(0) == '\\' && - (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 && - ((ch-'a')|('z'-ch)) < 0 && - ((ch-'A')|('Z'-ch)) < 0)) && - (ch < Character.MIN_HIGH_SURROGATE || - ch > Character.MAX_LOW_SURROGATE)) - { - int off = 0; - int next = 0; - boolean limited = limit > 0; - ArrayList<String> list = new ArrayList<>(); - while ((next = indexOf(ch, off)) != -1) { - if (!limited || list.size() < limit - 1) { - list.add(substring(off, next)); - off = next + 1; - } else { // last one - //assert (list.size() == limit - 1); - list.add(substring(off, count)); - off = count; - break; - } - } - // If no match was found, return this - if (off == 0) - return new String[] { this }; - - // Add remaining segment - if (!limited || list.size() < limit) - list.add(substring(off, count)); - - // Construct result - int resultSize = list.size(); - if (limit == 0) - while (resultSize > 0 && list.get(resultSize-1).length() == 0) - resultSize--; - String[] result = new String[resultSize]; - return list.subList(0, resultSize).toArray(result); - } - return Pattern.compile(regex).split(this, limit); - } - - /** - * Splits this string around matches of the given <a - * href="../util/regex/Pattern.html#sum">regular expression</a>. - * - * <p> This method works as if by invoking the two-argument {@link - * #split(String, int) split} method with the given expression and a limit - * argument of zero. Trailing empty strings are therefore not included in - * the resulting array. - * - * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the following - * results with these expressions: - * - * <blockquote><table cellpadding=1 cellspacing=0 summary="Split examples showing regex and result"> - * <tr> - * <th>Regex</th> - * <th>Result</th> - * </tr> - * <tr><td align=center>:</td> - * <td><tt>{ "boo", "and", "foo" }</tt></td></tr> - * <tr><td align=center>o</td> - * <td><tt>{ "b", "", ":and:f" }</tt></td></tr> - * </table></blockquote> - * - * - * @param regex - * the delimiting regular expression - * - * @return the array of strings computed by splitting this string - * around matches of the given regular expression - * - * @throws PatternSyntaxException - * if the regular expression's syntax is invalid - * - * @see java.util.regex.Pattern - * - * @since 1.4 - * @spec JSR-51 - */ - public String[] split(String regex) { - return split(regex, 0); - } - - /** - * Converts all of the characters in this <code>String</code> to lower - * case using the rules of the given <code>Locale</code>. Case mapping is based - * on the Unicode Standard version specified by the {@link java.lang.Character Character} - * class. Since case mappings are not always 1:1 char mappings, the resulting - * <code>String</code> may be a different length than the original <code>String</code>. - * <p> - * Examples of lowercase mappings are in the following table: - * <table border="1" summary="Lowercase mapping examples showing language code of locale, upper case, lower case, and description"> - * <tr> - * <th>Language Code of Locale</th> - * <th>Upper Case</th> - * <th>Lower Case</th> - * <th>Description</th> - * </tr> - * <tr> - * <td>tr (Turkish)</td> - * <td>\u0130</td> - * <td>\u0069</td> - * <td>capital letter I with dot above -> small letter i</td> - * </tr> - * <tr> - * <td>tr (Turkish)</td> - * <td>\u0049</td> - * <td>\u0131</td> - * <td>capital letter I -> small letter dotless i </td> - * </tr> - * <tr> - * <td>(all)</td> - * <td>French Fries</td> - * <td>french fries</td> - * <td>lowercased all chars in String</td> - * </tr> - * <tr> - * <td>(all)</td> - * <td><img src="doc-files/capiota.gif" alt="capiota"><img src="doc-files/capchi.gif" alt="capchi"> - * <img src="doc-files/captheta.gif" alt="captheta"><img src="doc-files/capupsil.gif" alt="capupsil"> - * <img src="doc-files/capsigma.gif" alt="capsigma"></td> - * <td><img src="doc-files/iota.gif" alt="iota"><img src="doc-files/chi.gif" alt="chi"> - * <img src="doc-files/theta.gif" alt="theta"><img src="doc-files/upsilon.gif" alt="upsilon"> - * <img src="doc-files/sigma1.gif" alt="sigma"></td> - * <td>lowercased all chars in String</td> - * </tr> - * </table> - * - * @param locale use the case transformation rules for this locale - * @return the <code>String</code>, converted to lowercase. - * @see java.lang.String#toLowerCase() - * @see java.lang.String#toUpperCase() - * @see java.lang.String#toUpperCase(Locale) - * @since 1.1 - */ - public String toLowerCase(Locale locale) { - if (locale == null) { - throw new NullPointerException(); - } - - int firstUpper; - - /* Now check if there are any characters that need to be changed. */ - scan: { - for (firstUpper = 0 ; firstUpper < count; ) { - char c = value[offset+firstUpper]; - if ((c >= Character.MIN_HIGH_SURROGATE) && - (c <= Character.MAX_HIGH_SURROGATE)) { - int supplChar = codePointAt(firstUpper); - if (supplChar != Character.toLowerCase(supplChar)) { - break scan; - } - firstUpper += Character.charCount(supplChar); - } else { - if (c != Character.toLowerCase(c)) { - break scan; - } - firstUpper++; - } - } - return this; - } - - char[] result = new char[count]; - int resultOffset = 0; /* result may grow, so i+resultOffset - * is the write location in result */ - - /* Just copy the first few lowerCase characters. */ - System.arraycopy(value, offset, result, 0, firstUpper); - - String lang = locale.getLanguage(); - boolean localeDependent = - (lang == "tr" || lang == "az" || lang == "lt"); - char[] lowerCharArray; - int lowerChar; - int srcChar; - int srcCount; - for (int i = firstUpper; i < count; i += srcCount) { - srcChar = (int)value[offset+i]; - if ((char)srcChar >= Character.MIN_HIGH_SURROGATE && - (char)srcChar <= Character.MAX_HIGH_SURROGATE) { - srcChar = codePointAt(i); - srcCount = Character.charCount(srcChar); - } else { - srcCount = 1; - } - if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA - lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale); - } else if (srcChar == '\u0130') { // LATIN CAPITAL LETTER I DOT - lowerChar = Character.ERROR; - } else { - lowerChar = Character.toLowerCase(srcChar); - } - if ((lowerChar == Character.ERROR) || - (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { - if (lowerChar == Character.ERROR) { - if (!localeDependent && srcChar == '\u0130') { - lowerCharArray = - ConditionalSpecialCasing.toLowerCaseCharArray(this, i, Locale.ENGLISH); - } else { - lowerCharArray = - ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale); - } - } else if (srcCount == 2) { - resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount; - continue; - } else { - lowerCharArray = Character.toChars(lowerChar); - } - - /* Grow result if needed */ - int mapLen = lowerCharArray.length; - if (mapLen > srcCount) { - char[] result2 = new char[result.length + mapLen - srcCount]; - System.arraycopy(result, 0, result2, 0, - i + resultOffset); - result = result2; - } - for (int x=0; x<mapLen; ++x) { - result[i+resultOffset+x] = lowerCharArray[x]; - } - resultOffset += (mapLen - srcCount); - } else { - result[i+resultOffset] = (char)lowerChar; - } - } - return new String(0, count+resultOffset, result); - } - - /** - * Converts all of the characters in this <code>String</code> to lower - * case using the rules of the default locale. This is equivalent to calling - * <code>toLowerCase(Locale.getDefault())</code>. - * <p> - * <b>Note:</b> This method is locale sensitive, and may produce unexpected - * results if used for strings that are intended to be interpreted locale - * independently. - * Examples are programming language identifiers, protocol keys, and HTML - * tags. - * For instance, <code>"TITLE".toLowerCase()</code> in a Turkish locale - * returns <code>"t\u005Cu0131tle"</code>, where '\u005Cu0131' is the - * LATIN SMALL LETTER DOTLESS I character. - * To obtain correct results for locale insensitive strings, use - * <code>toLowerCase(Locale.ENGLISH)</code>. - * <p> - * @return the <code>String</code>, converted to lowercase. - * @see java.lang.String#toLowerCase(Locale) - */ - public String toLowerCase() { - return toLowerCase(Locale.getDefault()); - } - - /** - * Converts all of the characters in this <code>String</code> to upper - * case using the rules of the given <code>Locale</code>. Case mapping is based - * on the Unicode Standard version specified by the {@link java.lang.Character Character} - * class. Since case mappings are not always 1:1 char mappings, the resulting - * <code>String</code> may be a different length than the original <code>String</code>. - * <p> - * Examples of locale-sensitive and 1:M case mappings are in the following table. - * <p> - * <table border="1" summary="Examples of locale-sensitive and 1:M case mappings. Shows Language code of locale, lower case, upper case, and description."> - * <tr> - * <th>Language Code of Locale</th> - * <th>Lower Case</th> - * <th>Upper Case</th> - * <th>Description</th> - * </tr> - * <tr> - * <td>tr (Turkish)</td> - * <td>\u0069</td> - * <td>\u0130</td> - * <td>small letter i -> capital letter I with dot above</td> - * </tr> - * <tr> - * <td>tr (Turkish)</td> - * <td>\u0131</td> - * <td>\u0049</td> - * <td>small letter dotless i -> capital letter I</td> - * </tr> - * <tr> - * <td>(all)</td> - * <td>\u00df</td> - * <td>\u0053 \u0053</td> - * <td>small letter sharp s -> two letters: SS</td> - * </tr> - * <tr> - * <td>(all)</td> - * <td>Fahrvergnügen</td> - * <td>FAHRVERGNÜGEN</td> - * <td></td> - * </tr> - * </table> - * @param locale use the case transformation rules for this locale - * @return the <code>String</code>, converted to uppercase. - * @see java.lang.String#toUpperCase() - * @see java.lang.String#toLowerCase() - * @see java.lang.String#toLowerCase(Locale) - * @since 1.1 - */ - public String toUpperCase(Locale locale) { - if (locale == null) { - throw new NullPointerException(); - } - - int firstLower; - - /* Now check if there are any characters that need to be changed. */ - scan: { - for (firstLower = 0 ; firstLower < count; ) { - int c = (int)value[offset+firstLower]; - int srcCount; - if ((c >= Character.MIN_HIGH_SURROGATE) && - (c <= Character.MAX_HIGH_SURROGATE)) { - c = codePointAt(firstLower); - srcCount = Character.charCount(c); - } else { - srcCount = 1; - } - int upperCaseChar = Character.toUpperCaseEx(c); - if ((upperCaseChar == Character.ERROR) || - (c != upperCaseChar)) { - break scan; - } - firstLower += srcCount; - } - return this; - } - - char[] result = new char[count]; /* may grow */ - int resultOffset = 0; /* result may grow, so i+resultOffset - * is the write location in result */ - - /* Just copy the first few upperCase characters. */ - System.arraycopy(value, offset, result, 0, firstLower); - - String lang = locale.getLanguage(); - boolean localeDependent = - (lang == "tr" || lang == "az" || lang == "lt"); - char[] upperCharArray; - int upperChar; - int srcChar; - int srcCount; - for (int i = firstLower; i < count; i += srcCount) { - srcChar = (int)value[offset+i]; - if ((char)srcChar >= Character.MIN_HIGH_SURROGATE && - (char)srcChar <= Character.MAX_HIGH_SURROGATE) { - srcChar = codePointAt(i); - srcCount = Character.charCount(srcChar); - } else { - srcCount = 1; - } - if (localeDependent) { - upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale); - } else { - upperChar = Character.toUpperCaseEx(srcChar); - } - if ((upperChar == Character.ERROR) || - (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) { - if (upperChar == Character.ERROR) { - if (localeDependent) { - upperCharArray = - ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale); - } else { - upperCharArray = Character.toUpperCaseCharArray(srcChar); - } - } else if (srcCount == 2) { - resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount; - continue; - } else { - upperCharArray = Character.toChars(upperChar); - } - - /* Grow result if needed */ - int mapLen = upperCharArray.length; - if (mapLen > srcCount) { - char[] result2 = new char[result.length + mapLen - srcCount]; - System.arraycopy(result, 0, result2, 0, - i + resultOffset); - result = result2; - } - for (int x=0; x<mapLen; ++x) { - result[i+resultOffset+x] = upperCharArray[x]; - } - resultOffset += (mapLen - srcCount); - } else { - result[i+resultOffset] = (char)upperChar; - } - } - return new String(0, count+resultOffset, result); - } - - /** - * Converts all of the characters in this <code>String</code> to upper - * case using the rules of the default locale. This method is equivalent to - * <code>toUpperCase(Locale.getDefault())</code>. - * <p> - * <b>Note:</b> This method is locale sensitive, and may produce unexpected - * results if used for strings that are intended to be interpreted locale - * independently. - * Examples are programming language identifiers, protocol keys, and HTML - * tags. - * For instance, <code>"title".toUpperCase()</code> in a Turkish locale - * returns <code>"T\u005Cu0130TLE"</code>, where '\u005Cu0130' is the - * LATIN CAPITAL LETTER I WITH DOT ABOVE character. - * To obtain correct results for locale insensitive strings, use - * <code>toUpperCase(Locale.ENGLISH)</code>. - * <p> - * @return the <code>String</code>, converted to uppercase. - * @see java.lang.String#toUpperCase(Locale) - */ - public String toUpperCase() { - return toUpperCase(Locale.getDefault()); - } - - /** - * Returns a copy of the string, with leading and trailing whitespace - * omitted. - * <p> - * If this <code>String</code> object represents an empty character - * sequence, or the first and last characters of character sequence - * represented by this <code>String</code> object both have codes - * greater than <code>'\u0020'</code> (the space character), then a - * reference to this <code>String</code> object is returned. - * <p> - * Otherwise, if there is no character with a code greater than - * <code>'\u0020'</code> in the string, then a new - * <code>String</code> object representing an empty string is created - * and returned. - * <p> - * Otherwise, let <i>k</i> be the index of the first character in the - * string whose code is greater than <code>'\u0020'</code>, and let - * <i>m</i> be the index of the last character in the string whose code - * is greater than <code>'\u0020'</code>. A new <code>String</code> - * object is created, representing the substring of this string that - * begins with the character at index <i>k</i> and ends with the - * character at index <i>m</i>-that is, the result of - * <code>this.substring(<i>k</i>, <i>m</i>+1)</code>. - * <p> - * This method may be used to trim whitespace (as defined above) from - * the beginning and end of a string. - * - * @return A copy of this string with leading and trailing white - * space removed, or this string if it has no leading or - * trailing white space. - */ - public String trim() { - int len = count; - int st = 0; - int off = offset; /* avoid getfield opcode */ - char[] val = value; /* avoid getfield opcode */ - - while ((st < len) && (val[off + st] <= ' ')) { - st++; - } - while ((st < len) && (val[off + len - 1] <= ' ')) { - len--; - } - return ((st > 0) || (len < count)) ? substring(st, len) : this; - } - - /** - * This object (which is already a string!) is itself returned. - * - * @return the string itself. - */ - public String toString() { - return this; - } - - /** - * Converts this string to a new character array. - * - * @return a newly allocated character array whose length is the length - * of this string and whose contents are initialized to contain - * the character sequence represented by this string. - */ - public char[] toCharArray() { - char result[] = new char[count]; - getChars(0, count, result, 0); - return result; - } - - /** - * Returns a formatted string using the specified format string and - * arguments. - * - * <p> The locale always used is the one returned by {@link - * java.util.Locale#getDefault() Locale.getDefault()}. - * - * @param format - * A <a href="../util/Formatter.html#syntax">format string</a> - * - * @param args - * Arguments referenced by the format specifiers in the format - * string. If there are more arguments than format specifiers, the - * extra arguments are ignored. The number of arguments is - * variable and may be zero. The maximum number of arguments is - * limited by the maximum dimension of a Java array as defined by - * <cite>The Java™ Virtual Machine Specification</cite>. - * The behaviour on a - * <tt>null</tt> argument depends on the <a - * href="../util/Formatter.html#syntax">conversion</a>. - * - * @throws IllegalFormatException - * If a format string contains an illegal syntax, a format - * specifier that is incompatible with the given arguments, - * insufficient arguments given the format string, or other - * illegal conditions. For specification of all possible - * formatting errors, see the <a - * href="../util/Formatter.html#detail">Details</a> section of the - * formatter class specification. - * - * @throws NullPointerException - * If the <tt>format</tt> is <tt>null</tt> - * - * @return A formatted string - * - * @see java.util.Formatter - * @since 1.5 - */ - public static String format(String format, Object ... args) { - return new Formatter().format(format, args).toString(); - } - - /** - * Returns a formatted string using the specified locale, format string, - * and arguments. - * - * @param l - * The {@linkplain java.util.Locale locale} to apply during - * formatting. If <tt>l</tt> is <tt>null</tt> then no localization - * is applied. - * - * @param format - * A <a href="../util/Formatter.html#syntax">format string</a> - * - * @param args - * Arguments referenced by the format specifiers in the format - * string. If there are more arguments than format specifiers, the - * extra arguments are ignored. The number of arguments is - * variable and may be zero. The maximum number of arguments is - * limited by the maximum dimension of a Java array as defined by - * <cite>The Java™ Virtual Machine Specification</cite>. - * The behaviour on a - * <tt>null</tt> argument depends on the <a - * href="../util/Formatter.html#syntax">conversion</a>. - * - * @throws IllegalFormatException - * If a format string contains an illegal syntax, a format - * specifier that is incompatible with the given arguments, - * insufficient arguments given the format string, or other - * illegal conditions. For specification of all possible - * formatting errors, see the <a - * href="../util/Formatter.html#detail">Details</a> section of the - * formatter class specification - * - * @throws NullPointerException - * If the <tt>format</tt> is <tt>null</tt> - * - * @return A formatted string - * - * @see java.util.Formatter - * @since 1.5 - */ - public static String format(Locale l, String format, Object ... args) { - return new Formatter(l).format(format, args).toString(); - } - - /** - * Returns the string representation of the <code>Object</code> argument. - * - * @param obj an <code>Object</code>. - * @return if the argument is <code>null</code>, then a string equal to - * <code>"null"</code>; otherwise, the value of - * <code>obj.toString()</code> is returned. - * @see java.lang.Object#toString() - */ - public static String valueOf(Object obj) { - return (obj == null) ? "null" : obj.toString(); - } - - /** - * Returns the string representation of the <code>char</code> array - * argument. The contents of the character array are copied; subsequent - * modification of the character array does not affect the newly - * created string. - * - * @param data a <code>char</code> array. - * @return a newly allocated string representing the same sequence of - * characters contained in the character array argument. - */ - public static String valueOf(char data[]) { - return new String(data); - } - - /** - * Returns the string representation of a specific subarray of the - * <code>char</code> array argument. - * <p> - * The <code>offset</code> argument is the index of the first - * character of the subarray. The <code>count</code> argument - * specifies the length of the subarray. The contents of the subarray - * are copied; subsequent modification of the character array does not - * affect the newly created string. - * - * @param data the character array. - * @param offset the initial offset into the value of the - * <code>String</code>. - * @param count the length of the value of the <code>String</code>. - * @return a string representing the sequence of characters contained - * in the subarray of the character array argument. - * @exception IndexOutOfBoundsException if <code>offset</code> is - * negative, or <code>count</code> is negative, or - * <code>offset+count</code> is larger than - * <code>data.length</code>. - */ - public static String valueOf(char data[], int offset, int count) { - return new String(data, offset, count); - } - - /** - * Returns a String that represents the character sequence in the - * array specified. - * - * @param data the character array. - * @param offset initial offset of the subarray. - * @param count length of the subarray. - * @return a <code>String</code> that contains the characters of the - * specified subarray of the character array. - */ - public static String copyValueOf(char data[], int offset, int count) { - // All public String constructors now copy the data. - return new String(data, offset, count); - } - - /** - * Returns a String that represents the character sequence in the - * array specified. - * - * @param data the character array. - * @return a <code>String</code> that contains the characters of the - * character array. - */ - public static String copyValueOf(char data[]) { - return copyValueOf(data, 0, data.length); - } - - /** - * Returns the string representation of the <code>boolean</code> argument. - * - * @param b a <code>boolean</code>. - * @return if the argument is <code>true</code>, a string equal to - * <code>"true"</code> is returned; otherwise, a string equal to - * <code>"false"</code> is returned. - */ - public static String valueOf(boolean b) { - return b ? "true" : "false"; - } - - /** - * Returns the string representation of the <code>char</code> - * argument. - * - * @param c a <code>char</code>. - * @return a string of length <code>1</code> containing - * as its single character the argument <code>c</code>. - */ - public static String valueOf(char c) { - char data[] = {c}; - return new String(0, 1, data); - } - - /** - * Returns the string representation of the <code>int</code> argument. - * <p> - * The representation is exactly the one returned by the - * <code>Integer.toString</code> method of one argument. - * - * @param i an <code>int</code>. - * @return a string representation of the <code>int</code> argument. - * @see java.lang.Integer#toString(int, int) - */ - public static String valueOf(int i) { - return Integer.toString(i); - } - - /** - * Returns the string representation of the <code>long</code> argument. - * <p> - * The representation is exactly the one returned by the - * <code>Long.toString</code> method of one argument. - * - * @param l a <code>long</code>. - * @return a string representation of the <code>long</code> argument. - * @see java.lang.Long#toString(long) - */ - public static String valueOf(long l) { - return Long.toString(l); - } - - /** - * Returns the string representation of the <code>float</code> argument. - * <p> - * The representation is exactly the one returned by the - * <code>Float.toString</code> method of one argument. - * - * @param f a <code>float</code>. - * @return a string representation of the <code>float</code> argument. - * @see java.lang.Float#toString(float) - */ - public static String valueOf(float f) { - return Float.toString(f); - } - - /** - * Returns the string representation of the <code>double</code> argument. - * <p> - * The representation is exactly the one returned by the - * <code>Double.toString</code> method of one argument. - * - * @param d a <code>double</code>. - * @return a string representation of the <code>double</code> argument. - * @see java.lang.Double#toString(double) - */ - public static String valueOf(double d) { - return Double.toString(d); - } - - /** - * Returns a canonical representation for the string object. - * <p> - * A pool of strings, initially empty, is maintained privately by the - * class <code>String</code>. - * <p> - * When the intern method is invoked, if the pool already contains a - * string equal to this <code>String</code> object as determined by - * the {@link #equals(Object)} method, then the string from the pool is - * returned. Otherwise, this <code>String</code> object is added to the - * pool and a reference to this <code>String</code> object is returned. - * <p> - * It follows that for any two strings <code>s</code> and <code>t</code>, - * <code>s.intern() == t.intern()</code> is <code>true</code> - * if and only if <code>s.equals(t)</code> is <code>true</code>. - * <p> - * All literal strings and string-valued constant expressions are - * interned. String literals are defined in section 3.10.5 of the - * <cite>The Java™ Language Specification</cite>. - * - * @return a string that has the same contents as this string, but is - * guaranteed to be from a pool of unique strings. - */ - public native String intern(); - -} diff --git a/notes/src/StringBuffer.java b/notes/src/StringBuffer.java deleted file mode 100644 index b1d35977..00000000 --- a/notes/src/StringBuffer.java +++ /dev/null @@ -1,527 +0,0 @@ - - -package java.lang; - - public final class StringBuffer - extends AbstractStringBuilder - implements java.io.Serializable, CharSequence -{ - - /** use serialVersionUID from JDK 1.0.2 for interoperability */ - static final long serialVersionUID = 3388685877147921107L; - - /** - * Constructs a string buffer with no characters in it and an - * initial capacity of 16 characters. - */ - public StringBuffer() { - super(16); - } - - /** - * Constructs a string buffer with no characters in it and - * the specified initial capacity. - * - * @param capacity the initial capacity. - * @exception NegativeArraySizeException if the <code>capacity</code> - * argument is less than <code>0</code>. - */ - public StringBuffer(int capacity) { - super(capacity); - } - - /** - * Constructs a string buffer initialized to the contents of the - * specified string. The initial capacity of the string buffer is - * <code>16</code> plus the length of the string argument. - * - * @param str the initial contents of the buffer. - * @exception NullPointerException if <code>str</code> is <code>null</code> - */ - public StringBuffer(String str) { - super(str.length() + 16); - append(str); - } - - /** - * Constructs a string buffer that contains the same characters - * as the specified <code>CharSequence</code>. The initial capacity of - * the string buffer is <code>16</code> plus the length of the - * <code>CharSequence</code> argument. - * <p> - * If the length of the specified <code>CharSequence</code> is - * less than or equal to zero, then an empty buffer of capacity - * <code>16</code> is returned. - * - * @param seq the sequence to copy. - * @exception NullPointerException if <code>seq</code> is <code>null</code> - * @since 1.5 - */ - public StringBuffer(CharSequence seq) { - this(seq.length() + 16); - append(seq); - } - - public synchronized int length() { - return count; - } - - public synchronized int capacity() { - return value.length; - } - - - public synchronized void ensureCapacity(int minimumCapacity) { - if (minimumCapacity > value.length) { - expandCapacity(minimumCapacity); - } - } - - /** - * @since 1.5 - */ - public synchronized void trimToSize() { - super.trimToSize(); - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - * @see #length() - */ - public synchronized void setLength(int newLength) { - super.setLength(newLength); - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - * @see #length() - */ - public synchronized char charAt(int index) { - if ((index < 0) || (index >= count)) - throw new StringIndexOutOfBoundsException(index); - return value[index]; - } - - /** - * @since 1.5 - */ - public synchronized int codePointAt(int index) { - return super.codePointAt(index); - } - - /** - * @since 1.5 - */ - public synchronized int codePointBefore(int index) { - return super.codePointBefore(index); - } - - /** - * @since 1.5 - */ - public synchronized int codePointCount(int beginIndex, int endIndex) { - return super.codePointCount(beginIndex, endIndex); - } - - /** - * @since 1.5 - */ - public synchronized int offsetByCodePoints(int index, int codePointOffset) { - return super.offsetByCodePoints(index, codePointOffset); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public synchronized void getChars(int srcBegin, int srcEnd, char[] dst, - int dstBegin) - { - super.getChars(srcBegin, srcEnd, dst, dstBegin); - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - * @see #length() - */ - public synchronized void setCharAt(int index, char ch) { - if ((index < 0) || (index >= count)) - throw new StringIndexOutOfBoundsException(index); - value[index] = ch; - } - - public synchronized StringBuffer append(Object obj) { - super.append(String.valueOf(obj)); - return this; - } - - public synchronized StringBuffer append(String str) { - super.append(str); - return this; - } - - /** - * Appends the specified <tt>StringBuffer</tt> to this sequence. - * <p> - * The characters of the <tt>StringBuffer</tt> argument are appended, - * in order, to the contents of this <tt>StringBuffer</tt>, increasing the - * length of this <tt>StringBuffer</tt> by the length of the argument. - * If <tt>sb</tt> is <tt>null</tt>, then the four characters - * <tt>"null"</tt> are appended to this <tt>StringBuffer</tt>. - * <p> - * Let <i>n</i> be the length of the old character sequence, the one - * contained in the <tt>StringBuffer</tt> just prior to execution of the - * <tt>append</tt> method. Then the character at index <i>k</i> in - * the new character sequence is equal to the character at index <i>k</i> - * in the old character sequence, if <i>k</i> is less than <i>n</i>; - * otherwise, it is equal to the character at index <i>k-n</i> in the - * argument <code>sb</code>. - * <p> - * This method synchronizes on <code>this</code> (the destination) - * object but does not synchronize on the source (<code>sb</code>). - * - * @param sb the <tt>StringBuffer</tt> to append. - * @return a reference to this object. - * @since 1.4 - */ - public synchronized StringBuffer append(StringBuffer sb) { - super.append(sb); - return this; - } - - - /** - * Appends the specified <code>CharSequence</code> to this - * sequence. - * <p> - * The characters of the <code>CharSequence</code> argument are appended, - * in order, increasing the length of this sequence by the length of the - * argument. - * - * <p>The result of this method is exactly the same as if it were an - * invocation of this.append(s, 0, s.length()); - * - * <p>This method synchronizes on this (the destination) - * object but does not synchronize on the source (<code>s</code>). - * - * <p>If <code>s</code> is <code>null</code>, then the four characters - * <code>"null"</code> are appended. - * - * @param s the <code>CharSequence</code> to append. - * @return a reference to this object. - * @since 1.5 - */ - public StringBuffer append(CharSequence s) { - // Note, synchronization achieved via other invocations - if (s == null) - s = "null"; - if (s instanceof String) - return this.append((String)s); - if (s instanceof StringBuffer) - return this.append((StringBuffer)s); - return this.append(s, 0, s.length()); - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - * @since 1.5 - */ - public synchronized StringBuffer append(CharSequence s, int start, int end) - { - super.append(s, start, end); - return this; - } - - public synchronized StringBuffer append(char[] str) { - super.append(str); - return this; - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public synchronized StringBuffer append(char[] str, int offset, int len) { - super.append(str, offset, len); - return this; - } - - public synchronized StringBuffer append(boolean b) { - super.append(b); - return this; - } - - public synchronized StringBuffer append(char c) { - super.append(c); - return this; - } - - public synchronized StringBuffer append(int i) { - super.append(i); - return this; - } - - /** - * @since 1.5 - */ - public synchronized StringBuffer appendCodePoint(int codePoint) { - super.appendCodePoint(codePoint); - return this; - } - - public synchronized StringBuffer append(long lng) { - super.append(lng); - return this; - } - - public synchronized StringBuffer append(float f) { - super.append(f); - return this; - } - - public synchronized StringBuffer append(double d) { - super.append(d); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - * @since 1.2 - */ - public synchronized StringBuffer delete(int start, int end) { - super.delete(start, end); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - * @since 1.2 - */ - public synchronized StringBuffer deleteCharAt(int index) { - super.deleteCharAt(index); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - * @since 1.2 - */ - public synchronized StringBuffer replace(int start, int end, String str) { - super.replace(start, end, str); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - * @since 1.2 - */ - public synchronized String substring(int start) { - return substring(start, count); - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - * @since 1.4 - */ - public synchronized CharSequence subSequence(int start, int end) { - return super.substring(start, end); - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - * @since 1.2 - */ - public synchronized String substring(int start, int end) { - return super.substring(start, end); - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - * @since 1.2 - */ - public synchronized StringBuffer insert(int index, char[] str, int offset, - int len) - { - super.insert(index, str, offset, len); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public synchronized StringBuffer insert(int offset, Object obj) { - super.insert(offset, String.valueOf(obj)); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public synchronized StringBuffer insert(int offset, String str) { - super.insert(offset, str); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public synchronized StringBuffer insert(int offset, char[] str) { - super.insert(offset, str); - return this; - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - * @since 1.5 - */ - public StringBuffer insert(int dstOffset, CharSequence s) { - // Note, synchronization achieved via other invocations - if (s == null) - s = "null"; - if (s instanceof String) - return this.insert(dstOffset, (String)s); - return this.insert(dstOffset, s, 0, s.length()); - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - * @since 1.5 - */ - public synchronized StringBuffer insert(int dstOffset, CharSequence s, - int start, int end) - { - super.insert(dstOffset, s, start, end); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuffer insert(int offset, boolean b) { - return insert(offset, String.valueOf(b)); - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public synchronized StringBuffer insert(int offset, char c) { - super.insert(offset, c); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuffer insert(int offset, int i) { - return insert(offset, String.valueOf(i)); - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuffer insert(int offset, long l) { - return insert(offset, String.valueOf(l)); - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuffer insert(int offset, float f) { - return insert(offset, String.valueOf(f)); - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuffer insert(int offset, double d) { - return insert(offset, String.valueOf(d)); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.4 - */ - public int indexOf(String str) { - return indexOf(str, 0); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.4 - */ - public synchronized int indexOf(String str, int fromIndex) { - return String.indexOf(value, 0, count, - str.toCharArray(), 0, str.length(), fromIndex); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.4 - */ - public int lastIndexOf(String str) { - // Note, synchronization achieved via other invocations - return lastIndexOf(str, count); - } - - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.4 - */ - public synchronized int lastIndexOf(String str, int fromIndex) { - return String.lastIndexOf(value, 0, count, - str.toCharArray(), 0, str.length(), fromIndex); - } - - /** - * @since JDK1.0.2 - */ - public synchronized StringBuffer reverse() { - super.reverse(); - return this; - } - - public synchronized String toString() { - return new String(value, 0, count); - } - - /** - * Serializable fields for StringBuffer. - * - * @serialField value char[] - * The backing character array of this StringBuffer. - * @serialField count int - * The number of characters in this StringBuffer. - * @serialField shared boolean - * A flag indicating whether the backing array is shared. - * The value is ignored upon deserialization. - */ - private static final java.io.ObjectStreamField[] serialPersistentFields = - { - new java.io.ObjectStreamField("value", char[].class), - new java.io.ObjectStreamField("count", Integer.TYPE), - new java.io.ObjectStreamField("shared", Boolean.TYPE), - }; - - /** - * readObject is called to restore the state of the StringBuffer from - * a stream. - */ - private synchronized void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - java.io.ObjectOutputStream.PutField fields = s.putFields(); - fields.put("value", value); - fields.put("count", count); - fields.put("shared", false); - s.writeFields(); - } - - /** - * readObject is called to restore the state of the StringBuffer from - * a stream. - */ - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - java.io.ObjectInputStream.GetField fields = s.readFields(); - value = (char[])fields.get("value", null); - count = fields.get("count", 0); - } -} diff --git a/notes/src/StringBuilder.java b/notes/src/StringBuilder.java deleted file mode 100644 index 54f3b57f..00000000 --- a/notes/src/StringBuilder.java +++ /dev/null @@ -1,369 +0,0 @@ - -package java.lang; - -public final class StringBuilder - extends AbstractStringBuilder - implements java.io.Serializable, CharSequence -{ - - /** use serialVersionUID for interoperability */ - static final long serialVersionUID = 4383685877147921099L; - - /** - * Constructs a string builder with no characters in it and an - * initial capacity of 16 characters. - */ - public StringBuilder() { - super(16); - } - - /** - * Constructs a string builder with no characters in it and an - * initial capacity specified by the <code>capacity</code> argument. - * - * @param capacity the initial capacity. - * @throws NegativeArraySizeException if the <code>capacity</code> - * argument is less than <code>0</code>. - */ - public StringBuilder(int capacity) { - super(capacity); - } - - /** - * Constructs a string builder initialized to the contents of the - * specified string. The initial capacity of the string builder is - * <code>16</code> plus the length of the string argument. - * - * @param str the initial contents of the buffer. - * @throws NullPointerException if <code>str</code> is <code>null</code> - */ - public StringBuilder(String str) { - super(str.length() + 16); - append(str); - } - - /** - * Constructs a string builder that contains the same characters - * as the specified <code>CharSequence</code>. The initial capacity of - * the string builder is <code>16</code> plus the length of the - * <code>CharSequence</code> argument. - * - * @param seq the sequence to copy. - * @throws NullPointerException if <code>seq</code> is <code>null</code> - */ - public StringBuilder(CharSequence seq) { - this(seq.length() + 16); - append(seq); - } - - public StringBuilder append(Object obj) { - return append(String.valueOf(obj)); - } - - public StringBuilder append(String str) { - super.append(str); - return this; - } - - // Appends the specified string builder to this sequence. - private StringBuilder append(StringBuilder sb) { - if (sb == null) - return append("null"); - int len = sb.length(); - int newcount = count + len; - if (newcount > value.length) - expandCapacity(newcount); - sb.getChars(0, len, value, count); - count = newcount; - return this; - } - - /** - * Appends the specified <tt>StringBuffer</tt> to this sequence. - * <p> - * The characters of the <tt>StringBuffer</tt> argument are appended, - * in order, to this sequence, increasing the - * length of this sequence by the length of the argument. - * If <tt>sb</tt> is <tt>null</tt>, then the four characters - * <tt>"null"</tt> are appended to this sequence. - * <p> - * Let <i>n</i> be the length of this character sequence just prior to - * execution of the <tt>append</tt> method. Then the character at index - * <i>k</i> in the new character sequence is equal to the character at - * index <i>k</i> in the old character sequence, if <i>k</i> is less than - * <i>n</i>; otherwise, it is equal to the character at index <i>k-n</i> - * in the argument <code>sb</code>. - * - * @param sb the <tt>StringBuffer</tt> to append. - * @return a reference to this object. - */ - public StringBuilder append(StringBuffer sb) { - super.append(sb); - return this; - } - - /** - */ - public StringBuilder append(CharSequence s) { - if (s == null) - s = "null"; - if (s instanceof String) - return this.append((String)s); - if (s instanceof StringBuffer) - return this.append((StringBuffer)s); - if (s instanceof StringBuilder) - return this.append((StringBuilder)s); - return this.append(s, 0, s.length()); - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder append(CharSequence s, int start, int end) { - super.append(s, start, end); - return this; - } - - public StringBuilder append(char[] str) { - super.append(str); - return this; - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder append(char[] str, int offset, int len) { - super.append(str, offset, len); - return this; - } - - public StringBuilder append(boolean b) { - super.append(b); - return this; - } - - public StringBuilder append(char c) { - super.append(c); - return this; - } - - public StringBuilder append(int i) { - super.append(i); - return this; - } - - public StringBuilder append(long lng) { - super.append(lng); - return this; - } - - public StringBuilder append(float f) { - super.append(f); - return this; - } - - public StringBuilder append(double d) { - super.append(d); - return this; - } - - /** - * @since 1.5 - */ - public StringBuilder appendCodePoint(int codePoint) { - super.appendCodePoint(codePoint); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder delete(int start, int end) { - super.delete(start, end); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder deleteCharAt(int index) { - super.deleteCharAt(index); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder replace(int start, int end, String str) { - super.replace(start, end, str); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int index, char[] str, int offset, - int len) - { - super.insert(index, str, offset, len); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int offset, Object obj) { - return insert(offset, String.valueOf(obj)); - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int offset, String str) { - super.insert(offset, str); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int offset, char[] str) { - super.insert(offset, str); - return this; - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int dstOffset, CharSequence s) { - if (s == null) - s = "null"; - if (s instanceof String) - return this.insert(dstOffset, (String)s); - return this.insert(dstOffset, s, 0, s.length()); - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int dstOffset, CharSequence s, - int start, int end) - { - super.insert(dstOffset, s, start, end); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int offset, boolean b) { - super.insert(offset, b); - return this; - } - - /** - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int offset, char c) { - super.insert(offset, c); - return this; - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int offset, int i) { - return insert(offset, String.valueOf(i)); - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int offset, long l) { - return insert(offset, String.valueOf(l)); - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int offset, float f) { - return insert(offset, String.valueOf(f)); - } - - /** - * @throws StringIndexOutOfBoundsException {@inheritDoc} - */ - public StringBuilder insert(int offset, double d) { - return insert(offset, String.valueOf(d)); - } - - /** - * @throws NullPointerException {@inheritDoc} - */ - public int indexOf(String str) { - return indexOf(str, 0); - } - - /** - * @throws NullPointerException {@inheritDoc} - */ - public int indexOf(String str, int fromIndex) { - return String.indexOf(value, 0, count, - str.toCharArray(), 0, str.length(), fromIndex); - } - - /** - * @throws NullPointerException {@inheritDoc} - */ - public int lastIndexOf(String str) { - return lastIndexOf(str, count); - } - - /** - * @throws NullPointerException {@inheritDoc} - */ - public int lastIndexOf(String str, int fromIndex) { - return String.lastIndexOf(value, 0, count, - str.toCharArray(), 0, str.length(), fromIndex); - } - - public StringBuilder reverse() { - super.reverse(); - return this; - } - - public String toString() { - // Create a copy, don't share the array - return new String(value, 0, count); - } - - /** - * Save the state of the <tt>StringBuilder</tt> instance to a stream - * (that is, serialize it). - * - * @serialData the number of characters currently stored in the string - * builder (<tt>int</tt>), followed by the characters in the - * string builder (<tt>char[]</tt>). The length of the - * <tt>char</tt> array may be greater than the number of - * characters currently stored in the string builder, in which - * case extra characters are ignored. - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - s.defaultWriteObject(); - s.writeInt(count); - s.writeObject(value); - } - - /** - * readObject is called to restore the state of the StringBuffer from - * a stream. - */ - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - s.defaultReadObject(); - count = s.readInt(); - value = (char[]) s.readObject(); - } - -} diff --git a/notes/src/TreeMap.java b/notes/src/TreeMap.java deleted file mode 100644 index 120b46cf..00000000 --- a/notes/src/TreeMap.java +++ /dev/null @@ -1,2340 +0,0 @@ - -package java.util; - -public class TreeMap<K,V> - extends AbstractMap<K,V> - implements NavigableMap<K,V>, Cloneable, java.io.Serializable -{ - /** - * The comparator used to maintain order in this tree map, or - * null if it uses the natural ordering of its keys. - * - * @serial - */ - private final Comparator<? super K> comparator; - - private transient Entry<K,V> root = null; - - /** - * The number of entries in the tree - */ - private transient int size = 0; - - /** - * The number of structural modifications to the tree. - */ - private transient int modCount = 0; - - /** - * Constructs a new, empty tree map, using the natural ordering of its - * keys. All keys inserted into the map must implement the {@link - * Comparable} interface. Furthermore, all such keys must be - * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw - * a {@code ClassCastException} for any keys {@code k1} and - * {@code k2} in the map. If the user attempts to put a key into the - * map that violates this constraint (for example, the user attempts to - * put a string key into a map whose keys are integers), the - * {@code put(Object key, Object value)} call will throw a - * {@code ClassCastException}. - */ - public TreeMap() { - comparator = null; - } - - /** - * Constructs a new, empty tree map, ordered according to the given - * comparator. All keys inserted into the map must be <em>mutually - * comparable</em> by the given comparator: {@code comparator.compare(k1, - * k2)} must not throw a {@code ClassCastException} for any keys - * {@code k1} and {@code k2} in the map. If the user attempts to put - * a key into the map that violates this constraint, the {@code put(Object - * key, Object value)} call will throw a - * {@code ClassCastException}. - * - * @param comparator the comparator that will be used to order this map. - * If {@code null}, the {@linkplain Comparable natural - * ordering} of the keys will be used. - */ - public TreeMap(Comparator<? super K> comparator) { - this.comparator = comparator; - } - - /** - * Constructs a new tree map containing the same mappings as the given - * map, ordered according to the <em>natural ordering</em> of its keys. - * All keys inserted into the new map must implement the {@link - * Comparable} interface. Furthermore, all such keys must be - * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw - * a {@code ClassCastException} for any keys {@code k1} and - * {@code k2} in the map. This method runs in n*log(n) time. - * - * @param m the map whose mappings are to be placed in this map - * @throws ClassCastException if the keys in m are not {@link Comparable}, - * or are not mutually comparable - * @throws NullPointerException if the specified map is null - */ - public TreeMap(Map<? extends K, ? extends V> m) { - comparator = null; - putAll(m); - } - - /** - * Constructs a new tree map containing the same mappings and - * using the same ordering as the specified sorted map. This - * method runs in linear time. - * - * @param m the sorted map whose mappings are to be placed in this map, - * and whose comparator is to be used to sort this map - * @throws NullPointerException if the specified map is null - */ - public TreeMap(SortedMap<K, ? extends V> m) { - comparator = m.comparator(); - try { - buildFromSorted(m.size(), m.entrySet().iterator(), null, null); - } catch (java.io.IOException cannotHappen) { - } catch (ClassNotFoundException cannotHappen) { - } - } - - - // Query Operations - - /** - * Returns the number of key-value mappings in this map. - * - * @return the number of key-value mappings in this map - */ - public int size() { - return size; - } - - /** - * Returns {@code true} if this map contains a mapping for the specified - * key. - * - * @param key key whose presence in this map is to be tested - * @return {@code true} if this map contains a mapping for the - * specified key - * @throws ClassCastException if the specified key cannot be compared - * with the keys currently in the map - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - */ - public boolean containsKey(Object key) { - return getEntry(key) != null; - } - - /** - * Returns {@code true} if this map maps one or more keys to the - * specified value. More formally, returns {@code true} if and only if - * this map contains at least one mapping to a value {@code v} such - * that {@code (value==null ? v==null : value.equals(v))}. This - * operation will probably require time linear in the map size for - * most implementations. - * - * @param value value whose presence in this map is to be tested - * @return {@code true} if a mapping to {@code value} exists; - * {@code false} otherwise - * @since 1.2 - */ - public boolean containsValue(Object value) { - for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) - if (valEquals(value, e.value)) - return true; - return false; - } - - /** - * Returns the value to which the specified key is mapped, - * or {@code null} if this map contains no mapping for the key. - * - * <p>More formally, if this map contains a mapping from a key - * {@code k} to a value {@code v} such that {@code key} compares - * equal to {@code k} according to the map's ordering, then this - * method returns {@code v}; otherwise it returns {@code null}. - * (There can be at most one such mapping.) - * - * <p>A return value of {@code null} does not <em>necessarily</em> - * indicate that the map contains no mapping for the key; it's also - * possible that the map explicitly maps the key to {@code null}. - * The {@link #containsKey containsKey} operation may be used to - * distinguish these two cases. - * - * @throws ClassCastException if the specified key cannot be compared - * with the keys currently in the map - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - */ - public V get(Object key) { - Entry<K,V> p = getEntry(key); - return (p==null ? null : p.value); - } - - public Comparator<? super K> comparator() { - return comparator; - } - - /** - * @throws NoSuchElementException {@inheritDoc} - */ - public K firstKey() { - return key(getFirstEntry()); - } - - /** - * @throws NoSuchElementException {@inheritDoc} - */ - public K lastKey() { - return key(getLastEntry()); - } - - /** - * Copies all of the mappings from the specified map to this map. - * These mappings replace any mappings that this map had for any - * of the keys currently in the specified map. - * - * @param map mappings to be stored in this map - * @throws ClassCastException if the class of a key or value in - * the specified map prevents it from being stored in this map - * @throws NullPointerException if the specified map is null or - * the specified map contains a null key and this map does not - * permit null keys - */ - public void putAll(Map<? extends K, ? extends V> map) { - int mapSize = map.size(); - if (size==0 && mapSize!=0 && map instanceof SortedMap) { - Comparator c = ((SortedMap)map).comparator(); - if (c == comparator || (c != null && c.equals(comparator))) { - ++modCount; - try { - buildFromSorted(mapSize, map.entrySet().iterator(), - null, null); - } catch (java.io.IOException cannotHappen) { - } catch (ClassNotFoundException cannotHappen) { - } - return; - } - } - super.putAll(map); - } - - /** - * Returns this map's entry for the given key, or {@code null} if the map - * does not contain an entry for the key. - * - * @return this map's entry for the given key, or {@code null} if the map - * does not contain an entry for the key - * @throws ClassCastException if the specified key cannot be compared - * with the keys currently in the map - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - */ - final Entry<K,V> getEntry(Object key) { - // Offload comparator-based version for sake of performance - if (comparator != null) - return getEntryUsingComparator(key); - if (key == null) - throw new NullPointerException(); - Comparable<? super K> k = (Comparable<? super K>) key; - Entry<K,V> p = root; - while (p != null) { - int cmp = k.compareTo(p.key); - if (cmp < 0) - p = p.left; - else if (cmp > 0) - p = p.right; - else - return p; - } - return null; - } - - /** - * Version of getEntry using comparator. Split off from getEntry - * for performance. (This is not worth doing for most methods, - * that are less dependent on comparator performance, but is - * worthwhile here.) - */ - final Entry<K,V> getEntryUsingComparator(Object key) { - K k = (K) key; - Comparator<? super K> cpr = comparator; - if (cpr != null) { - Entry<K,V> p = root; - while (p != null) { - int cmp = cpr.compare(k, p.key); - if (cmp < 0) - p = p.left; - else if (cmp > 0) - p = p.right; - else - return p; - } - } - return null; - } - - /** - * Gets the entry corresponding to the specified key; if no such entry - * exists, returns the entry for the least key greater than the specified - * key; if no such entry exists (i.e., the greatest key in the Tree is less - * than the specified key), returns {@code null}. - */ - final Entry<K,V> getCeilingEntry(K key) { - Entry<K,V> p = root; - while (p != null) { - int cmp = compare(key, p.key); - if (cmp < 0) { - if (p.left != null) - p = p.left; - else - return p; - } else if (cmp > 0) { - if (p.right != null) { - p = p.right; - } else { - Entry<K,V> parent = p.parent; - Entry<K,V> ch = p; - while (parent != null && ch == parent.right) { - ch = parent; - parent = parent.parent; - } - return parent; - } - } else - return p; - } - return null; - } - - /** - * Gets the entry corresponding to the specified key; if no such entry - * exists, returns the entry for the greatest key less than the specified - * key; if no such entry exists, returns {@code null}. - */ - final Entry<K,V> getFloorEntry(K key) { - Entry<K,V> p = root; - while (p != null) { - int cmp = compare(key, p.key); - if (cmp > 0) { - if (p.right != null) - p = p.right; - else - return p; - } else if (cmp < 0) { - if (p.left != null) { - p = p.left; - } else { - Entry<K,V> parent = p.parent; - Entry<K,V> ch = p; - while (parent != null && ch == parent.left) { - ch = parent; - parent = parent.parent; - } - return parent; - } - } else - return p; - - } - return null; - } - - /** - * Gets the entry for the least key greater than the specified - * key; if no such entry exists, returns the entry for the least - * key greater than the specified key; if no such entry exists - * returns {@code null}. - */ - final Entry<K,V> getHigherEntry(K key) { - Entry<K,V> p = root; - while (p != null) { - int cmp = compare(key, p.key); - if (cmp < 0) { - if (p.left != null) - p = p.left; - else - return p; - } else { - if (p.right != null) { - p = p.right; - } else { - Entry<K,V> parent = p.parent; - Entry<K,V> ch = p; - while (parent != null && ch == parent.right) { - ch = parent; - parent = parent.parent; - } - return parent; - } - } - } - return null; - } - - /** - * Returns the entry for the greatest key less than the specified key; if - * no such entry exists (i.e., the least key in the Tree is greater than - * the specified key), returns {@code null}. - */ - final Entry<K,V> getLowerEntry(K key) { - Entry<K,V> p = root; - while (p != null) { - int cmp = compare(key, p.key); - if (cmp > 0) { - if (p.right != null) - p = p.right; - else - return p; - } else { - if (p.left != null) { - p = p.left; - } else { - Entry<K,V> parent = p.parent; - Entry<K,V> ch = p; - while (parent != null && ch == parent.left) { - ch = parent; - parent = parent.parent; - } - return parent; - } - } - } - return null; - } - - /** - * Associates the specified value with the specified key in this map. - * If the map previously contained a mapping for the key, the old - * value is replaced. - * - * @param key key with which the specified value is to be associated - * @param value value to be associated with the specified key - * - * @return the previous value associated with {@code key}, or - * {@code null} if there was no mapping for {@code key}. - * (A {@code null} return can also indicate that the map - * previously associated {@code null} with {@code key}.) - * @throws ClassCastException if the specified key cannot be compared - * with the keys currently in the map - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - */ - public V put(K key, V value) { - Entry<K,V> t = root; - if (t == null) { - compare(key, key); // type (and possibly null) check - - root = new Entry<>(key, value, null); - size = 1; - modCount++; - return null; - } - int cmp; - Entry<K,V> parent; - // split comparator and comparable paths - Comparator<? super K> cpr = comparator; - if (cpr != null) { - do { - parent = t; - cmp = cpr.compare(key, t.key); - if (cmp < 0) - t = t.left; - else if (cmp > 0) - t = t.right; - else - return t.setValue(value); - } while (t != null); - } - else { - if (key == null) - throw new NullPointerException(); - Comparable<? super K> k = (Comparable<? super K>) key; - do { - parent = t; - cmp = k.compareTo(t.key); - if (cmp < 0) - t = t.left; - else if (cmp > 0) - t = t.right; - else - return t.setValue(value); - } while (t != null); - } - Entry<K,V> e = new Entry<>(key, value, parent); - if (cmp < 0) - parent.left = e; - else - parent.right = e; - fixAfterInsertion(e); - size++; - modCount++; - return null; - } - - /** - * Removes the mapping for this key from this TreeMap if present. - * - * @param key key for which mapping should be removed - * @return the previous value associated with {@code key}, or - * {@code null} if there was no mapping for {@code key}. - * (A {@code null} return can also indicate that the map - * previously associated {@code null} with {@code key}.) - * @throws ClassCastException if the specified key cannot be compared - * with the keys currently in the map - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - */ - public V remove(Object key) { - Entry<K,V> p = getEntry(key); - if (p == null) - return null; - - V oldValue = p.value; - deleteEntry(p); - return oldValue; - } - - /** - * Removes all of the mappings from this map. - * The map will be empty after this call returns. - */ - public void clear() { - modCount++; - size = 0; - root = null; - } - - /** - * Returns a shallow copy of this {@code TreeMap} instance. (The keys and - * values themselves are not cloned.) - * - * @return a shallow copy of this map - */ - public Object clone() { - TreeMap<K,V> clone = null; - try { - clone = (TreeMap<K,V>) super.clone(); - } catch (CloneNotSupportedException e) { - throw new InternalError(); - } - - // Put clone into "virgin" state (except for comparator) - clone.root = null; - clone.size = 0; - clone.modCount = 0; - clone.entrySet = null; - clone.navigableKeySet = null; - clone.descendingMap = null; - - // Initialize clone with our mappings - try { - clone.buildFromSorted(size, entrySet().iterator(), null, null); - } catch (java.io.IOException cannotHappen) { - } catch (ClassNotFoundException cannotHappen) { - } - - return clone; - } - - // NavigableMap API methods - - /** - * @since 1.6 - */ - public Map.Entry<K,V> firstEntry() { - return exportEntry(getFirstEntry()); - } - - /** - * @since 1.6 - */ - public Map.Entry<K,V> lastEntry() { - return exportEntry(getLastEntry()); - } - - /** - * @since 1.6 - */ - public Map.Entry<K,V> pollFirstEntry() { - Entry<K,V> p = getFirstEntry(); - Map.Entry<K,V> result = exportEntry(p); - if (p != null) - deleteEntry(p); - return result; - } - - /** - * @since 1.6 - */ - public Map.Entry<K,V> pollLastEntry() { - Entry<K,V> p = getLastEntry(); - Map.Entry<K,V> result = exportEntry(p); - if (p != null) - deleteEntry(p); - return result; - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @since 1.6 - */ - public Map.Entry<K,V> lowerEntry(K key) { - return exportEntry(getLowerEntry(key)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @since 1.6 - */ - public K lowerKey(K key) { - return keyOrNull(getLowerEntry(key)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @since 1.6 - */ - public Map.Entry<K,V> floorEntry(K key) { - return exportEntry(getFloorEntry(key)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @since 1.6 - */ - public K floorKey(K key) { - return keyOrNull(getFloorEntry(key)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @since 1.6 - */ - public Map.Entry<K,V> ceilingEntry(K key) { - return exportEntry(getCeilingEntry(key)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @since 1.6 - */ - public K ceilingKey(K key) { - return keyOrNull(getCeilingEntry(key)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @since 1.6 - */ - public Map.Entry<K,V> higherEntry(K key) { - return exportEntry(getHigherEntry(key)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified key is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @since 1.6 - */ - public K higherKey(K key) { - return keyOrNull(getHigherEntry(key)); - } - - // Views - - /** - * Fields initialized to contain an instance of the entry set view - * the first time this view is requested. Views are stateless, so - * there's no reason to create more than one. - */ - private transient EntrySet entrySet = null; - private transient KeySet<K> navigableKeySet = null; - private transient NavigableMap<K,V> descendingMap = null; - - /** - * 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. - */ - public Set<K> keySet() { - return navigableKeySet(); - } - - /** - * @since 1.6 - */ - public NavigableSet<K> navigableKeySet() { - KeySet<K> nks = navigableKeySet; - return (nks != null) ? nks : (navigableKeySet = new KeySet(this)); - } - - /** - * @since 1.6 - */ - public NavigableSet<K> descendingKeySet() { - return descendingMap().navigableKeySet(); - } - - /** - * 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. - */ - public Collection<V> values() { - Collection<V> vs = values; - return (vs != null) ? vs : (values = new 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. - */ - public Set<Map.Entry<K,V>> entrySet() { - EntrySet es = entrySet; - return (es != null) ? es : (entrySet = new EntrySet()); - } - - /** - * @since 1.6 - */ - public NavigableMap<K, V> descendingMap() { - NavigableMap<K, V> km = descendingMap; - return (km != null) ? km : - (descendingMap = new DescendingSubMap(this, - true, null, true, - true, null, true)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code fromKey} or {@code toKey} is - * null and this map uses natural ordering, or its comparator - * does not permit null keys - * @throws IllegalArgumentException {@inheritDoc} - * @since 1.6 - */ - public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, - K toKey, boolean toInclusive) { - return new AscendingSubMap(this, - false, fromKey, fromInclusive, - false, toKey, toInclusive); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code toKey} is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @throws IllegalArgumentException {@inheritDoc} - * @since 1.6 - */ - public NavigableMap<K,V> headMap(K toKey, boolean inclusive) { - return new AscendingSubMap(this, - true, null, true, - false, toKey, inclusive); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code fromKey} is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @throws IllegalArgumentException {@inheritDoc} - * @since 1.6 - */ - public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) { - return new AscendingSubMap(this, - false, fromKey, inclusive, - true, null, true); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code fromKey} or {@code toKey} is - * null and this map uses natural ordering, or its comparator - * does not permit null keys - * @throws IllegalArgumentException {@inheritDoc} - */ - public SortedMap<K,V> subMap(K fromKey, K toKey) { - return subMap(fromKey, true, toKey, false); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code toKey} is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @throws IllegalArgumentException {@inheritDoc} - */ - public SortedMap<K,V> headMap(K toKey) { - return headMap(toKey, false); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code fromKey} is null - * and this map uses natural ordering, or its comparator - * does not permit null keys - * @throws IllegalArgumentException {@inheritDoc} - */ - public SortedMap<K,V> tailMap(K fromKey) { - return tailMap(fromKey, true); - } - - // View class support - - class Values extends AbstractCollection<V> { - public Iterator<V> iterator() { - return new ValueIterator(getFirstEntry()); - } - - public int size() { - return TreeMap.this.size(); - } - - public boolean contains(Object o) { - return TreeMap.this.containsValue(o); - } - - public boolean remove(Object o) { - for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) { - if (valEquals(e.getValue(), o)) { - deleteEntry(e); - return true; - } - } - return false; - } - - public void clear() { - TreeMap.this.clear(); - } - } - - class EntrySet extends AbstractSet<Map.Entry<K,V>> { - public Iterator<Map.Entry<K,V>> iterator() { - return new EntryIterator(getFirstEntry()); - } - - public boolean contains(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry<K,V> entry = (Map.Entry<K,V>) o; - V value = entry.getValue(); - Entry<K,V> p = getEntry(entry.getKey()); - return p != null && valEquals(p.getValue(), value); - } - - public boolean remove(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry<K,V> entry = (Map.Entry<K,V>) o; - V value = entry.getValue(); - Entry<K,V> p = getEntry(entry.getKey()); - if (p != null && valEquals(p.getValue(), value)) { - deleteEntry(p); - return true; - } - return false; - } - - public int size() { - return TreeMap.this.size(); - } - - public void clear() { - TreeMap.this.clear(); - } - } - - /* - * Unlike Values and EntrySet, the KeySet class is static, - * delegating to a NavigableMap to allow use by SubMaps, which - * outweighs the ugliness of needing type-tests for the following - * Iterator methods that are defined appropriately in main versus - * submap classes. - */ - - Iterator<K> keyIterator() { - return new KeyIterator(getFirstEntry()); - } - - Iterator<K> descendingKeyIterator() { - return new DescendingKeyIterator(getLastEntry()); - } - - static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> { - private final NavigableMap<E, Object> m; - KeySet(NavigableMap<E,Object> map) { m = map; } - - public Iterator<E> iterator() { - if (m instanceof TreeMap) - return ((TreeMap<E,Object>)m).keyIterator(); - else - return (Iterator<E>)(((TreeMap.NavigableSubMap)m).keyIterator()); - } - - public Iterator<E> descendingIterator() { - if (m instanceof TreeMap) - return ((TreeMap<E,Object>)m).descendingKeyIterator(); - else - return (Iterator<E>)(((TreeMap.NavigableSubMap)m).descendingKeyIterator()); - } - - public int size() { return m.size(); } - public boolean isEmpty() { return m.isEmpty(); } - public boolean contains(Object o) { return m.containsKey(o); } - public void clear() { m.clear(); } - public E lower(E e) { return m.lowerKey(e); } - public E floor(E e) { return m.floorKey(e); } - public E ceiling(E e) { return m.ceilingKey(e); } - public E higher(E e) { return m.higherKey(e); } - public E first() { return m.firstKey(); } - public E last() { return m.lastKey(); } - public Comparator<? super E> comparator() { return m.comparator(); } - public E pollFirst() { - Map.Entry<E,Object> e = m.pollFirstEntry(); - return (e == null) ? null : e.getKey(); - } - public E pollLast() { - Map.Entry<E,Object> e = m.pollLastEntry(); - return (e == null) ? null : e.getKey(); - } - public boolean remove(Object o) { - int oldSize = size(); - m.remove(o); - return size() != oldSize; - } - public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, - E toElement, boolean toInclusive) { - return new KeySet<>(m.subMap(fromElement, fromInclusive, - toElement, toInclusive)); - } - public NavigableSet<E> headSet(E toElement, boolean inclusive) { - return new KeySet<>(m.headMap(toElement, inclusive)); - } - public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { - return new KeySet<>(m.tailMap(fromElement, inclusive)); - } - public SortedSet<E> subSet(E fromElement, E toElement) { - return subSet(fromElement, true, toElement, false); - } - public SortedSet<E> headSet(E toElement) { - return headSet(toElement, false); - } - public SortedSet<E> tailSet(E fromElement) { - return tailSet(fromElement, true); - } - public NavigableSet<E> descendingSet() { - return new KeySet(m.descendingMap()); - } - } - - /** - * Base class for TreeMap Iterators - */ - abstract class PrivateEntryIterator<T> implements Iterator<T> { - Entry<K,V> next; - Entry<K,V> lastReturned; - int expectedModCount; - - PrivateEntryIterator(Entry<K,V> first) { - expectedModCount = modCount; - lastReturned = null; - next = first; - } - - public final boolean hasNext() { - return next != null; - } - - final Entry<K,V> nextEntry() { - Entry<K,V> e = next; - if (e == null) - throw new NoSuchElementException(); - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - next = successor(e); - lastReturned = e; - return e; - } - - final Entry<K,V> prevEntry() { - Entry<K,V> e = next; - if (e == null) - throw new NoSuchElementException(); - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - next = predecessor(e); - lastReturned = e; - return e; - } - - public void remove() { - if (lastReturned == null) - throw new IllegalStateException(); - if (modCount != expectedModCount) - throw new ConcurrentModificationException(); - // deleted entries are replaced by their successors - if (lastReturned.left != null && lastReturned.right != null) - next = lastReturned; - deleteEntry(lastReturned); - expectedModCount = modCount; - lastReturned = null; - } - } - - final class EntryIterator extends PrivateEntryIterator<Map.Entry<K,V>> { - EntryIterator(Entry<K,V> first) { - super(first); - } - public Map.Entry<K,V> next() { - return nextEntry(); - } - } - - final class ValueIterator extends PrivateEntryIterator<V> { - ValueIterator(Entry<K,V> first) { - super(first); - } - public V next() { - return nextEntry().value; - } - } - - final class KeyIterator extends PrivateEntryIterator<K> { - KeyIterator(Entry<K,V> first) { - super(first); - } - public K next() { - return nextEntry().key; - } - } - - final class DescendingKeyIterator extends PrivateEntryIterator<K> { - DescendingKeyIterator(Entry<K,V> first) { - super(first); - } - public K next() { - return prevEntry().key; - } - } - - // Little utilities - - /** - * Compares two keys using the correct comparison method for this TreeMap. - */ - final int compare(Object k1, Object k2) { - return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2) - : comparator.compare((K)k1, (K)k2); - } - - /** - * Test two values for equality. Differs from o1.equals(o2) only in - * that it copes with {@code null} o1 properly. - */ - static final boolean valEquals(Object o1, Object o2) { - return (o1==null ? o2==null : o1.equals(o2)); - } - - /** - * Return SimpleImmutableEntry for entry, or null if null - */ - static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) { - return (e == null) ? null : - new AbstractMap.SimpleImmutableEntry<>(e); - } - - /** - * Return key for entry, or null if null - */ - static <K,V> K keyOrNull(TreeMap.Entry<K,V> e) { - return (e == null) ? null : e.key; - } - - /** - * Returns the key corresponding to the specified Entry. - * @throws NoSuchElementException if the Entry is null - */ - static <K> K key(Entry<K,?> e) { - if (e==null) - throw new NoSuchElementException(); - return e.key; - } - - - // SubMaps - - /** - * Dummy value serving as unmatchable fence key for unbounded - * SubMapIterators - */ - private static final Object UNBOUNDED = new Object(); - - /** - * @serial include - */ - abstract static class NavigableSubMap<K,V> extends AbstractMap<K,V> - implements NavigableMap<K,V>, java.io.Serializable { - /** - * The backing map. - */ - final TreeMap<K,V> m; - - /** - * Endpoints are represented as triples (fromStart, lo, - * loInclusive) and (toEnd, hi, hiInclusive). If fromStart is - * true, then the low (absolute) bound is the start of the - * backing map, and the other values are ignored. Otherwise, - * if loInclusive is true, lo is the inclusive bound, else lo - * is the exclusive bound. Similarly for the upper bound. - */ - final K lo, hi; - final boolean fromStart, toEnd; - final boolean loInclusive, hiInclusive; - - NavigableSubMap(TreeMap<K,V> m, - boolean fromStart, K lo, boolean loInclusive, - boolean toEnd, K hi, boolean hiInclusive) { - if (!fromStart && !toEnd) { - if (m.compare(lo, hi) > 0) - throw new IllegalArgumentException("fromKey > toKey"); - } else { - if (!fromStart) // type check - m.compare(lo, lo); - if (!toEnd) - m.compare(hi, hi); - } - - this.m = m; - this.fromStart = fromStart; - this.lo = lo; - this.loInclusive = loInclusive; - this.toEnd = toEnd; - this.hi = hi; - this.hiInclusive = hiInclusive; - } - - // internal utilities - - final boolean tooLow(Object key) { - if (!fromStart) { - int c = m.compare(key, lo); - if (c < 0 || (c == 0 && !loInclusive)) - return true; - } - return false; - } - - final boolean tooHigh(Object key) { - if (!toEnd) { - int c = m.compare(key, hi); - if (c > 0 || (c == 0 && !hiInclusive)) - return true; - } - return false; - } - - final boolean inRange(Object key) { - return !tooLow(key) && !tooHigh(key); - } - - final boolean inClosedRange(Object key) { - return (fromStart || m.compare(key, lo) >= 0) - && (toEnd || m.compare(hi, key) >= 0); - } - - final boolean inRange(Object key, boolean inclusive) { - return inclusive ? inRange(key) : inClosedRange(key); - } - - /* - * Absolute versions of relation operations. - * Subclasses map to these using like-named "sub" - * versions that invert senses for descending maps - */ - - final TreeMap.Entry<K,V> absLowest() { - TreeMap.Entry<K,V> e = - (fromStart ? m.getFirstEntry() : - (loInclusive ? m.getCeilingEntry(lo) : - m.getHigherEntry(lo))); - return (e == null || tooHigh(e.key)) ? null : e; - } - - final TreeMap.Entry<K,V> absHighest() { - TreeMap.Entry<K,V> e = - (toEnd ? m.getLastEntry() : - (hiInclusive ? m.getFloorEntry(hi) : - m.getLowerEntry(hi))); - return (e == null || tooLow(e.key)) ? null : e; - } - - final TreeMap.Entry<K,V> absCeiling(K key) { - if (tooLow(key)) - return absLowest(); - TreeMap.Entry<K,V> e = m.getCeilingEntry(key); - return (e == null || tooHigh(e.key)) ? null : e; - } - - final TreeMap.Entry<K,V> absHigher(K key) { - if (tooLow(key)) - return absLowest(); - TreeMap.Entry<K,V> e = m.getHigherEntry(key); - return (e == null || tooHigh(e.key)) ? null : e; - } - - final TreeMap.Entry<K,V> absFloor(K key) { - if (tooHigh(key)) - return absHighest(); - TreeMap.Entry<K,V> e = m.getFloorEntry(key); - return (e == null || tooLow(e.key)) ? null : e; - } - - final TreeMap.Entry<K,V> absLower(K key) { - if (tooHigh(key)) - return absHighest(); - TreeMap.Entry<K,V> e = m.getLowerEntry(key); - return (e == null || tooLow(e.key)) ? null : e; - } - - /** Returns the absolute high fence for ascending traversal */ - final TreeMap.Entry<K,V> absHighFence() { - return (toEnd ? null : (hiInclusive ? - m.getHigherEntry(hi) : - m.getCeilingEntry(hi))); - } - - /** Return the absolute low fence for descending traversal */ - final TreeMap.Entry<K,V> absLowFence() { - return (fromStart ? null : (loInclusive ? - m.getLowerEntry(lo) : - m.getFloorEntry(lo))); - } - - // Abstract methods defined in ascending vs descending classes - // These relay to the appropriate absolute versions - - abstract TreeMap.Entry<K,V> subLowest(); - abstract TreeMap.Entry<K,V> subHighest(); - abstract TreeMap.Entry<K,V> subCeiling(K key); - abstract TreeMap.Entry<K,V> subHigher(K key); - abstract TreeMap.Entry<K,V> subFloor(K key); - abstract TreeMap.Entry<K,V> subLower(K key); - - /** Returns ascending iterator from the perspective of this submap */ - abstract Iterator<K> keyIterator(); - - /** Returns descending iterator from the perspective of this submap */ - abstract Iterator<K> descendingKeyIterator(); - - // public methods - - public boolean isEmpty() { - return (fromStart && toEnd) ? m.isEmpty() : entrySet().isEmpty(); - } - - public int size() { - return (fromStart && toEnd) ? m.size() : entrySet().size(); - } - - public final boolean containsKey(Object key) { - return inRange(key) && m.containsKey(key); - } - - public final V put(K key, V value) { - if (!inRange(key)) - throw new IllegalArgumentException("key out of range"); - return m.put(key, value); - } - - public final V get(Object key) { - return !inRange(key) ? null : m.get(key); - } - - public final V remove(Object key) { - return !inRange(key) ? null : m.remove(key); - } - - public final Map.Entry<K,V> ceilingEntry(K key) { - return exportEntry(subCeiling(key)); - } - - public final K ceilingKey(K key) { - return keyOrNull(subCeiling(key)); - } - - public final Map.Entry<K,V> higherEntry(K key) { - return exportEntry(subHigher(key)); - } - - public final K higherKey(K key) { - return keyOrNull(subHigher(key)); - } - - public final Map.Entry<K,V> floorEntry(K key) { - return exportEntry(subFloor(key)); - } - - public final K floorKey(K key) { - return keyOrNull(subFloor(key)); - } - - public final Map.Entry<K,V> lowerEntry(K key) { - return exportEntry(subLower(key)); - } - - public final K lowerKey(K key) { - return keyOrNull(subLower(key)); - } - - public final K firstKey() { - return key(subLowest()); - } - - public final K lastKey() { - return key(subHighest()); - } - - public final Map.Entry<K,V> firstEntry() { - return exportEntry(subLowest()); - } - - public final Map.Entry<K,V> lastEntry() { - return exportEntry(subHighest()); - } - - public final Map.Entry<K,V> pollFirstEntry() { - TreeMap.Entry<K,V> e = subLowest(); - Map.Entry<K,V> result = exportEntry(e); - if (e != null) - m.deleteEntry(e); - return result; - } - - public final Map.Entry<K,V> pollLastEntry() { - TreeMap.Entry<K,V> e = subHighest(); - Map.Entry<K,V> result = exportEntry(e); - if (e != null) - m.deleteEntry(e); - return result; - } - - // Views - transient NavigableMap<K,V> descendingMapView = null; - transient EntrySetView entrySetView = null; - transient KeySet<K> navigableKeySetView = null; - - public final NavigableSet<K> navigableKeySet() { - KeySet<K> nksv = navigableKeySetView; - return (nksv != null) ? nksv : - (navigableKeySetView = new TreeMap.KeySet(this)); - } - - public final Set<K> keySet() { - return navigableKeySet(); - } - - public NavigableSet<K> descendingKeySet() { - return descendingMap().navigableKeySet(); - } - - public final SortedMap<K,V> subMap(K fromKey, K toKey) { - return subMap(fromKey, true, toKey, false); - } - - public final SortedMap<K,V> headMap(K toKey) { - return headMap(toKey, false); - } - - public final SortedMap<K,V> tailMap(K fromKey) { - return tailMap(fromKey, true); - } - - // View classes - - abstract class EntrySetView extends AbstractSet<Map.Entry<K,V>> { - private transient int size = -1, sizeModCount; - - public int size() { - if (fromStart && toEnd) - return m.size(); - if (size == -1 || sizeModCount != m.modCount) { - sizeModCount = m.modCount; - size = 0; - Iterator i = iterator(); - while (i.hasNext()) { - size++; - i.next(); - } - } - return size; - } - - public boolean isEmpty() { - TreeMap.Entry<K,V> n = absLowest(); - return n == null || tooHigh(n.key); - } - - public boolean contains(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry<K,V> entry = (Map.Entry<K,V>) o; - K key = entry.getKey(); - if (!inRange(key)) - return false; - TreeMap.Entry node = m.getEntry(key); - return node != null && - valEquals(node.getValue(), entry.getValue()); - } - - public boolean remove(Object o) { - if (!(o instanceof Map.Entry)) - return false; - Map.Entry<K,V> entry = (Map.Entry<K,V>) o; - K key = entry.getKey(); - if (!inRange(key)) - return false; - TreeMap.Entry<K,V> node = m.getEntry(key); - if (node!=null && valEquals(node.getValue(), - entry.getValue())) { - m.deleteEntry(node); - return true; - } - return false; - } - } - - /** - * Iterators for SubMaps - */ - abstract class SubMapIterator<T> implements Iterator<T> { - TreeMap.Entry<K,V> lastReturned; - TreeMap.Entry<K,V> next; - final Object fenceKey; - int expectedModCount; - - SubMapIterator(TreeMap.Entry<K,V> first, - TreeMap.Entry<K,V> fence) { - expectedModCount = m.modCount; - lastReturned = null; - next = first; - fenceKey = fence == null ? UNBOUNDED : fence.key; - } - - public final boolean hasNext() { - return next != null && next.key != fenceKey; - } - - final TreeMap.Entry<K,V> nextEntry() { - TreeMap.Entry<K,V> e = next; - if (e == null || e.key == fenceKey) - throw new NoSuchElementException(); - if (m.modCount != expectedModCount) - throw new ConcurrentModificationException(); - next = successor(e); - lastReturned = e; - return e; - } - - final TreeMap.Entry<K,V> prevEntry() { - TreeMap.Entry<K,V> e = next; - if (e == null || e.key == fenceKey) - throw new NoSuchElementException(); - if (m.modCount != expectedModCount) - throw new ConcurrentModificationException(); - next = predecessor(e); - lastReturned = e; - return e; - } - - final void removeAscending() { - if (lastReturned == null) - throw new IllegalStateException(); - if (m.modCount != expectedModCount) - throw new ConcurrentModificationException(); - // deleted entries are replaced by their successors - if (lastReturned.left != null && lastReturned.right != null) - next = lastReturned; - m.deleteEntry(lastReturned); - lastReturned = null; - expectedModCount = m.modCount; - } - - final void removeDescending() { - if (lastReturned == null) - throw new IllegalStateException(); - if (m.modCount != expectedModCount) - throw new ConcurrentModificationException(); - m.deleteEntry(lastReturned); - lastReturned = null; - expectedModCount = m.modCount; - } - - } - - final class SubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> { - SubMapEntryIterator(TreeMap.Entry<K,V> first, - TreeMap.Entry<K,V> fence) { - super(first, fence); - } - public Map.Entry<K,V> next() { - return nextEntry(); - } - public void remove() { - removeAscending(); - } - } - - final class SubMapKeyIterator extends SubMapIterator<K> { - SubMapKeyIterator(TreeMap.Entry<K,V> first, - TreeMap.Entry<K,V> fence) { - super(first, fence); - } - public K next() { - return nextEntry().key; - } - public void remove() { - removeAscending(); - } - } - - final class DescendingSubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> { - DescendingSubMapEntryIterator(TreeMap.Entry<K,V> last, - TreeMap.Entry<K,V> fence) { - super(last, fence); - } - - public Map.Entry<K,V> next() { - return prevEntry(); - } - public void remove() { - removeDescending(); - } - } - - final class DescendingSubMapKeyIterator extends SubMapIterator<K> { - DescendingSubMapKeyIterator(TreeMap.Entry<K,V> last, - TreeMap.Entry<K,V> fence) { - super(last, fence); - } - public K next() { - return prevEntry().key; - } - public void remove() { - removeDescending(); - } - } - } - - /** - * @serial include - */ - static final class AscendingSubMap<K,V> extends NavigableSubMap<K,V> { - private static final long serialVersionUID = 912986545866124060L; - - AscendingSubMap(TreeMap<K,V> m, - boolean fromStart, K lo, boolean loInclusive, - boolean toEnd, K hi, boolean hiInclusive) { - super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); - } - - public Comparator<? super K> comparator() { - return m.comparator(); - } - - public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, - K toKey, boolean toInclusive) { - if (!inRange(fromKey, fromInclusive)) - throw new IllegalArgumentException("fromKey out of range"); - if (!inRange(toKey, toInclusive)) - throw new IllegalArgumentException("toKey out of range"); - return new AscendingSubMap(m, - false, fromKey, fromInclusive, - false, toKey, toInclusive); - } - - public NavigableMap<K,V> headMap(K toKey, boolean inclusive) { - if (!inRange(toKey, inclusive)) - throw new IllegalArgumentException("toKey out of range"); - return new AscendingSubMap(m, - fromStart, lo, loInclusive, - false, toKey, inclusive); - } - - public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) { - if (!inRange(fromKey, inclusive)) - throw new IllegalArgumentException("fromKey out of range"); - return new AscendingSubMap(m, - false, fromKey, inclusive, - toEnd, hi, hiInclusive); - } - - public NavigableMap<K,V> descendingMap() { - NavigableMap<K,V> mv = descendingMapView; - return (mv != null) ? mv : - (descendingMapView = - new DescendingSubMap(m, - fromStart, lo, loInclusive, - toEnd, hi, hiInclusive)); - } - - Iterator<K> keyIterator() { - return new SubMapKeyIterator(absLowest(), absHighFence()); - } - - Iterator<K> descendingKeyIterator() { - return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); - } - - final class AscendingEntrySetView extends EntrySetView { - public Iterator<Map.Entry<K,V>> iterator() { - return new SubMapEntryIterator(absLowest(), absHighFence()); - } - } - - public Set<Map.Entry<K,V>> entrySet() { - EntrySetView es = entrySetView; - return (es != null) ? es : new AscendingEntrySetView(); - } - - TreeMap.Entry<K,V> subLowest() { return absLowest(); } - TreeMap.Entry<K,V> subHighest() { return absHighest(); } - TreeMap.Entry<K,V> subCeiling(K key) { return absCeiling(key); } - TreeMap.Entry<K,V> subHigher(K key) { return absHigher(key); } - TreeMap.Entry<K,V> subFloor(K key) { return absFloor(key); } - TreeMap.Entry<K,V> subLower(K key) { return absLower(key); } - } - - /** - * @serial include - */ - static final class DescendingSubMap<K,V> extends NavigableSubMap<K,V> { - private static final long serialVersionUID = 912986545866120460L; - DescendingSubMap(TreeMap<K,V> m, - boolean fromStart, K lo, boolean loInclusive, - boolean toEnd, K hi, boolean hiInclusive) { - super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); - } - - private final Comparator<? super K> reverseComparator = - Collections.reverseOrder(m.comparator); - - public Comparator<? super K> comparator() { - return reverseComparator; - } - - public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, - K toKey, boolean toInclusive) { - if (!inRange(fromKey, fromInclusive)) - throw new IllegalArgumentException("fromKey out of range"); - if (!inRange(toKey, toInclusive)) - throw new IllegalArgumentException("toKey out of range"); - return new DescendingSubMap(m, - false, toKey, toInclusive, - false, fromKey, fromInclusive); - } - - public NavigableMap<K,V> headMap(K toKey, boolean inclusive) { - if (!inRange(toKey, inclusive)) - throw new IllegalArgumentException("toKey out of range"); - return new DescendingSubMap(m, - false, toKey, inclusive, - toEnd, hi, hiInclusive); - } - - public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) { - if (!inRange(fromKey, inclusive)) - throw new IllegalArgumentException("fromKey out of range"); - return new DescendingSubMap(m, - fromStart, lo, loInclusive, - false, fromKey, inclusive); - } - - public NavigableMap<K,V> descendingMap() { - NavigableMap<K,V> mv = descendingMapView; - return (mv != null) ? mv : - (descendingMapView = - new AscendingSubMap(m, - fromStart, lo, loInclusive, - toEnd, hi, hiInclusive)); - } - - Iterator<K> keyIterator() { - return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); - } - - Iterator<K> descendingKeyIterator() { - return new SubMapKeyIterator(absLowest(), absHighFence()); - } - - final class DescendingEntrySetView extends EntrySetView { - public Iterator<Map.Entry<K,V>> iterator() { - return new DescendingSubMapEntryIterator(absHighest(), absLowFence()); - } - } - - public Set<Map.Entry<K,V>> entrySet() { - EntrySetView es = entrySetView; - return (es != null) ? es : new DescendingEntrySetView(); - } - - TreeMap.Entry<K,V> subLowest() { return absHighest(); } - TreeMap.Entry<K,V> subHighest() { return absLowest(); } - TreeMap.Entry<K,V> subCeiling(K key) { return absFloor(key); } - TreeMap.Entry<K,V> subHigher(K key) { return absLower(key); } - TreeMap.Entry<K,V> subFloor(K key) { return absCeiling(key); } - TreeMap.Entry<K,V> subLower(K key) { return absHigher(key); } - } - - /** - * This class exists solely for the sake of serialization - * compatibility with previous releases of TreeMap that did not - * support NavigableMap. It translates an old-version SubMap into - * a new-version AscendingSubMap. This class is never otherwise - * used. - * - * @serial include - */ - private class SubMap extends AbstractMap<K,V> - implements SortedMap<K,V>, java.io.Serializable { - private static final long serialVersionUID = -6520786458950516097L; - private boolean fromStart = false, toEnd = false; - private K fromKey, toKey; - private Object readResolve() { - return new AscendingSubMap(TreeMap.this, - fromStart, fromKey, true, - toEnd, toKey, false); - } - public Set<Map.Entry<K,V>> entrySet() { throw new InternalError(); } - public K lastKey() { throw new InternalError(); } - public K firstKey() { throw new InternalError(); } - public SortedMap<K,V> subMap(K fromKey, K toKey) { throw new InternalError(); } - public SortedMap<K,V> headMap(K toKey) { throw new InternalError(); } - public SortedMap<K,V> tailMap(K fromKey) { throw new InternalError(); } - public Comparator<? super K> comparator() { throw new InternalError(); } - } - - - // Red-black mechanics - - private static final boolean RED = false; - private static final boolean BLACK = true; - - /** - * Node in the Tree. Doubles as a means to pass key-value pairs back to - * user (see Map.Entry). - */ - - static final class Entry<K,V> implements Map.Entry<K,V> { - K key; - V value; - Entry<K,V> left = null; - Entry<K,V> right = null; - Entry<K,V> parent; - boolean color = BLACK; - - /** - * Make a new cell with given key, value, and parent, and with - * {@code null} child links, and BLACK color. - */ - Entry(K key, V value, Entry<K,V> parent) { - this.key = key; - this.value = value; - this.parent = parent; - } - - /** - * Returns the key. - * - * @return the key - */ - public K getKey() { - return key; - } - - /** - * Returns the value associated with the key. - * - * @return the value associated with the key - */ - public V getValue() { - return value; - } - - /** - * Replaces the value currently associated with the key with the given - * value. - * - * @return the value associated with the key before this method was - * called - */ - public V setValue(V value) { - 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 valEquals(key,e.getKey()) && valEquals(value,e.getValue()); - } - - public int hashCode() { - int keyHash = (key==null ? 0 : key.hashCode()); - int valueHash = (value==null ? 0 : value.hashCode()); - return keyHash ^ valueHash; - } - - public String toString() { - return key + "=" + value; - } - } - - /** - * Returns the first Entry in the TreeMap (according to the TreeMap's - * key-sort function). Returns null if the TreeMap is empty. - */ - final Entry<K,V> getFirstEntry() { - Entry<K,V> p = root; - if (p != null) - while (p.left != null) - p = p.left; - return p; - } - - /** - * Returns the last Entry in the TreeMap (according to the TreeMap's - * key-sort function). Returns null if the TreeMap is empty. - */ - final Entry<K,V> getLastEntry() { - Entry<K,V> p = root; - if (p != null) - while (p.right != null) - p = p.right; - return p; - } - - /** - * Returns the successor of the specified Entry, or null if no such. - */ - static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) { - if (t == null) - return null; - else if (t.right != null) { - Entry<K,V> p = t.right; - while (p.left != null) - p = p.left; - return p; - } else { - Entry<K,V> p = t.parent; - Entry<K,V> ch = t; - while (p != null && ch == p.right) { - ch = p; - p = p.parent; - } - return p; - } - } - - /** - * Returns the predecessor of the specified Entry, or null if no such. - */ - static <K,V> Entry<K,V> predecessor(Entry<K,V> t) { - if (t == null) - return null; - else if (t.left != null) { - Entry<K,V> p = t.left; - while (p.right != null) - p = p.right; - return p; - } else { - Entry<K,V> p = t.parent; - Entry<K,V> ch = t; - while (p != null && ch == p.left) { - ch = p; - p = p.parent; - } - return p; - } - } - - /** - * Balancing operations. - * - * Implementations of rebalancings during insertion and deletion are - * slightly different than the CLR version. Rather than using dummy - * nilnodes, we use a set of accessors that deal properly with null. They - * are used to avoid messiness surrounding nullness checks in the main - * algorithms. - */ - - private static <K,V> boolean colorOf(Entry<K,V> p) { - return (p == null ? BLACK : p.color); - } - - private static <K,V> Entry<K,V> parentOf(Entry<K,V> p) { - return (p == null ? null: p.parent); - } - - private static <K,V> void setColor(Entry<K,V> p, boolean c) { - if (p != null) - p.color = c; - } - - private static <K,V> Entry<K,V> leftOf(Entry<K,V> p) { - return (p == null) ? null: p.left; - } - - private static <K,V> Entry<K,V> rightOf(Entry<K,V> p) { - return (p == null) ? null: p.right; - } - - /** From CLR */ - private void rotateLeft(Entry<K,V> p) { - if (p != null) { - Entry<K,V> r = p.right; - p.right = r.left; - if (r.left != null) - r.left.parent = p; - r.parent = p.parent; - if (p.parent == null) - root = r; - else if (p.parent.left == p) - p.parent.left = r; - else - p.parent.right = r; - r.left = p; - p.parent = r; - } - } - - /** From CLR */ - private void rotateRight(Entry<K,V> p) { - if (p != null) { - Entry<K,V> l = p.left; - p.left = l.right; - if (l.right != null) l.right.parent = p; - l.parent = p.parent; - if (p.parent == null) - root = l; - else if (p.parent.right == p) - p.parent.right = l; - else p.parent.left = l; - l.right = p; - p.parent = l; - } - } - - /** From CLR */ - private void fixAfterInsertion(Entry<K,V> x) { - x.color = RED; - - while (x != null && x != root && x.parent.color == RED) { - if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { - Entry<K,V> y = rightOf(parentOf(parentOf(x))); - if (colorOf(y) == RED) { - setColor(parentOf(x), BLACK); - setColor(y, BLACK); - setColor(parentOf(parentOf(x)), RED); - x = parentOf(parentOf(x)); - } else { - if (x == rightOf(parentOf(x))) { - x = parentOf(x); - rotateLeft(x); - } - setColor(parentOf(x), BLACK); - setColor(parentOf(parentOf(x)), RED); - rotateRight(parentOf(parentOf(x))); - } - } else { - Entry<K,V> y = leftOf(parentOf(parentOf(x))); - if (colorOf(y) == RED) { - setColor(parentOf(x), BLACK); - setColor(y, BLACK); - setColor(parentOf(parentOf(x)), RED); - x = parentOf(parentOf(x)); - } else { - if (x == leftOf(parentOf(x))) { - x = parentOf(x); - rotateRight(x); - } - setColor(parentOf(x), BLACK); - setColor(parentOf(parentOf(x)), RED); - rotateLeft(parentOf(parentOf(x))); - } - } - } - root.color = BLACK; - } - - /** - * Delete node p, and then rebalance the tree. - */ - private void deleteEntry(Entry<K,V> p) { - modCount++; - size--; - - // If strictly internal, copy successor's element to p and then make p - // point to successor. - if (p.left != null && p.right != null) { - Entry<K,V> s = successor(p); - p.key = s.key; - p.value = s.value; - p = s; - } // p has 2 children - - // Start fixup at replacement node, if it exists. - Entry<K,V> replacement = (p.left != null ? p.left : p.right); - - if (replacement != null) { - // Link replacement to parent - replacement.parent = p.parent; - if (p.parent == null) - root = replacement; - else if (p == p.parent.left) - p.parent.left = replacement; - else - p.parent.right = replacement; - - // Null out links so they are OK to use by fixAfterDeletion. - p.left = p.right = p.parent = null; - - // Fix replacement - if (p.color == BLACK) - fixAfterDeletion(replacement); - } else if (p.parent == null) { // return if we are the only node. - root = null; - } else { // No children. Use self as phantom replacement and unlink. - if (p.color == BLACK) - fixAfterDeletion(p); - - if (p.parent != null) { - if (p == p.parent.left) - p.parent.left = null; - else if (p == p.parent.right) - p.parent.right = null; - p.parent = null; - } - } - } - - /** From CLR */ - private void fixAfterDeletion(Entry<K,V> x) { - while (x != root && colorOf(x) == BLACK) { - if (x == leftOf(parentOf(x))) { - Entry<K,V> sib = rightOf(parentOf(x)); - - if (colorOf(sib) == RED) { - setColor(sib, BLACK); - setColor(parentOf(x), RED); - rotateLeft(parentOf(x)); - sib = rightOf(parentOf(x)); - } - - if (colorOf(leftOf(sib)) == BLACK && - colorOf(rightOf(sib)) == BLACK) { - setColor(sib, RED); - x = parentOf(x); - } else { - if (colorOf(rightOf(sib)) == BLACK) { - setColor(leftOf(sib), BLACK); - setColor(sib, RED); - rotateRight(sib); - sib = rightOf(parentOf(x)); - } - setColor(sib, colorOf(parentOf(x))); - setColor(parentOf(x), BLACK); - setColor(rightOf(sib), BLACK); - rotateLeft(parentOf(x)); - x = root; - } - } else { // symmetric - Entry<K,V> sib = leftOf(parentOf(x)); - - if (colorOf(sib) == RED) { - setColor(sib, BLACK); - setColor(parentOf(x), RED); - rotateRight(parentOf(x)); - sib = leftOf(parentOf(x)); - } - - if (colorOf(rightOf(sib)) == BLACK && - colorOf(leftOf(sib)) == BLACK) { - setColor(sib, RED); - x = parentOf(x); - } else { - if (colorOf(leftOf(sib)) == BLACK) { - setColor(rightOf(sib), BLACK); - setColor(sib, RED); - rotateLeft(sib); - sib = leftOf(parentOf(x)); - } - setColor(sib, colorOf(parentOf(x))); - setColor(parentOf(x), BLACK); - setColor(leftOf(sib), BLACK); - rotateRight(parentOf(x)); - x = root; - } - } - } - - setColor(x, BLACK); - } - - private static final long serialVersionUID = 919286545866124006L; - - /** - * Save the state of the {@code TreeMap} instance to a stream (i.e., - * serialize it). - * - * @serialData The <em>size</em> of the TreeMap (the number of key-value - * mappings) is emitted (int), followed by the key (Object) - * and value (Object) for each key-value mapping represented - * by the TreeMap. The key-value mappings are emitted in - * key-order (as determined by the TreeMap's Comparator, - * or by the keys' natural ordering if the TreeMap has no - * Comparator). - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - // Write out the Comparator and any hidden stuff - s.defaultWriteObject(); - - // Write out size (number of Mappings) - s.writeInt(size); - - // Write out keys and values (alternating) - for (Iterator<Map.Entry<K,V>> i = entrySet().iterator(); i.hasNext(); ) { - Map.Entry<K,V> e = i.next(); - s.writeObject(e.getKey()); - s.writeObject(e.getValue()); - } - } - - /** - * Reconstitute the {@code TreeMap} instance from a stream (i.e., - * deserialize it). - */ - private void readObject(final java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - // Read in the Comparator and any hidden stuff - s.defaultReadObject(); - - // Read in size - int size = s.readInt(); - - buildFromSorted(size, null, s, null); - } - - /** Intended to be called only from TreeSet.readObject */ - void readTreeSet(int size, java.io.ObjectInputStream s, V defaultVal) - throws java.io.IOException, ClassNotFoundException { - buildFromSorted(size, null, s, defaultVal); - } - - /** Intended to be called only from TreeSet.addAll */ - void addAllForTreeSet(SortedSet<? extends K> set, V defaultVal) { - try { - buildFromSorted(set.size(), set.iterator(), null, defaultVal); - } catch (java.io.IOException cannotHappen) { - } catch (ClassNotFoundException cannotHappen) { - } - } - - - /** - * Linear time tree building algorithm from sorted data. Can accept keys - * and/or values from iterator or stream. This leads to too many - * parameters, but seems better than alternatives. The four formats - * that this method accepts are: - * - * 1) An iterator of Map.Entries. (it != null, defaultVal == null). - * 2) An iterator of keys. (it != null, defaultVal != null). - * 3) A stream of alternating serialized keys and values. - * (it == null, defaultVal == null). - * 4) A stream of serialized keys. (it == null, defaultVal != null). - * - * It is assumed that the comparator of the TreeMap is already set prior - * to calling this method. - * - * @param size the number of keys (or key-value pairs) to be read from - * the iterator or stream - * @param it If non-null, new entries are created from entries - * or keys read from this iterator. - * @param str If non-null, new entries are created from keys and - * possibly values read from this stream in serialized form. - * Exactly one of it and str should be non-null. - * @param defaultVal if non-null, this default value is used for - * each value in the map. If null, each value is read from - * iterator or stream, as described above. - * @throws IOException propagated from stream reads. This cannot - * occur if str is null. - * @throws ClassNotFoundException propagated from readObject. - * This cannot occur if str is null. - */ - private void buildFromSorted(int size, Iterator it, - java.io.ObjectInputStream str, - V defaultVal) - throws java.io.IOException, ClassNotFoundException { - this.size = size; - root = buildFromSorted(0, 0, size-1, computeRedLevel(size), - it, str, defaultVal); - } - - /** - * Recursive "helper method" that does the real work of the - * previous method. Identically named parameters have - * identical definitions. Additional parameters are documented below. - * It is assumed that the comparator and size fields of the TreeMap are - * already set prior to calling this method. (It ignores both fields.) - * - * @param level the current level of tree. Initial call should be 0. - * @param lo the first element index of this subtree. Initial should be 0. - * @param hi the last element index of this subtree. Initial should be - * size-1. - * @param redLevel the level at which nodes should be red. - * Must be equal to computeRedLevel for tree of this size. - */ - private final Entry<K,V> buildFromSorted(int level, int lo, int hi, - int redLevel, - Iterator it, - java.io.ObjectInputStream str, - V defaultVal) - throws java.io.IOException, ClassNotFoundException { - /* - * Strategy: The root is the middlemost element. To get to it, we - * have to first recursively construct the entire left subtree, - * so as to grab all of its elements. We can then proceed with right - * subtree. - * - * The lo and hi arguments are the minimum and maximum - * indices to pull out of the iterator or stream for current subtree. - * They are not actually indexed, we just proceed sequentially, - * ensuring that items are extracted in corresponding order. - */ - - if (hi < lo) return null; - - int mid = (lo + hi) >>> 1; - - Entry<K,V> left = null; - if (lo < mid) - left = buildFromSorted(level+1, lo, mid - 1, redLevel, - it, str, defaultVal); - - // extract key and/or value from iterator or stream - K key; - V value; - if (it != null) { - if (defaultVal==null) { - Map.Entry<K,V> entry = (Map.Entry<K,V>)it.next(); - key = entry.getKey(); - value = entry.getValue(); - } else { - key = (K)it.next(); - value = defaultVal; - } - } else { // use stream - key = (K) str.readObject(); - value = (defaultVal != null ? defaultVal : (V) str.readObject()); - } - - Entry<K,V> middle = new Entry<>(key, value, null); - - // color nodes in non-full bottommost level red - if (level == redLevel) - middle.color = RED; - - if (left != null) { - middle.left = left; - left.parent = middle; - } - - if (mid < hi) { - Entry<K,V> right = buildFromSorted(level+1, mid+1, hi, redLevel, - it, str, defaultVal); - middle.right = right; - right.parent = middle; - } - - return middle; - } - - /** - * Find the level down to which to assign all nodes BLACK. This is the - * last `full' level of the complete binary tree produced by - * buildTree. The remaining nodes are colored RED. (This makes a `nice' - * set of color assignments wrt future insertions.) This level number is - * computed by finding the number of splits needed to reach the zeroeth - * node. (The answer is ~lg(N), but in any case must be computed by same - * quick O(lg(N)) loop.) - */ - private static int computeRedLevel(int sz) { - int level = 0; - for (int m = sz - 1; m >= 0; m = m / 2 - 1) - level++; - return level; - } -} diff --git a/notes/src/TreeSet.java b/notes/src/TreeSet.java deleted file mode 100644 index 1f0d9490..00000000 --- a/notes/src/TreeSet.java +++ /dev/null @@ -1,451 +0,0 @@ - -package java.util; - -public class TreeSet<E> extends AbstractSet<E> - implements NavigableSet<E>, Cloneable, java.io.Serializable -{ - /** - * The backing map. - */ - private transient NavigableMap<E,Object> m; - - // Dummy value to associate with an Object in the backing Map - private static final Object PRESENT = new Object(); - - /** - * Constructs a set backed by the specified navigable map. - */ - TreeSet(NavigableMap<E,Object> m) { - this.m = m; - } - - /** - * Constructs a new, empty tree set, sorted according to the - * natural ordering of its elements. All elements inserted into - * the set must implement the {@link Comparable} interface. - * Furthermore, all such elements must be <i>mutually - * comparable</i>: {@code e1.compareTo(e2)} must not throw a - * {@code ClassCastException} for any elements {@code e1} and - * {@code e2} in the set. If the user attempts to add an element - * to the set that violates this constraint (for example, the user - * attempts to add a string element to a set whose elements are - * integers), the {@code add} call will throw a - * {@code ClassCastException}. - */ - public TreeSet() { - this(new TreeMap<E,Object>()); - } - - /** - * Constructs a new, empty tree set, sorted according to the specified - * comparator. All elements inserted into the set must be <i>mutually - * comparable</i> by the specified comparator: {@code comparator.compare(e1, - * e2)} must not throw a {@code ClassCastException} for any elements - * {@code e1} and {@code e2} in the set. If the user attempts to add - * an element to the set that violates this constraint, the - * {@code add} call will throw a {@code ClassCastException}. - * - * @param comparator the comparator that will be used to order this set. - * If {@code null}, the {@linkplain Comparable natural - * ordering} of the elements will be used. - */ - public TreeSet(Comparator<? super E> comparator) { - this(new TreeMap<>(comparator)); - } - - /** - * Constructs a new tree set containing the elements in the specified - * collection, sorted according to the <i>natural ordering</i> of its - * elements. All elements inserted into the set must implement the - * {@link Comparable} interface. Furthermore, all such elements must be - * <i>mutually comparable</i>: {@code e1.compareTo(e2)} must not throw a - * {@code ClassCastException} for any elements {@code e1} and - * {@code e2} in the set. - * - * @param c collection whose elements will comprise the new set - * @throws ClassCastException if the elements in {@code c} are - * not {@link Comparable}, or are not mutually comparable - * @throws NullPointerException if the specified collection is null - */ - public TreeSet(Collection<? extends E> c) { - this(); - addAll(c); - } - - /** - * Constructs a new tree set containing the same elements and - * using the same ordering as the specified sorted set. - * - * @param s sorted set whose elements will comprise the new set - * @throws NullPointerException if the specified sorted set is null - */ - public TreeSet(SortedSet<E> s) { - this(s.comparator()); - addAll(s); - } - - /** - * Returns an iterator over the elements in this set in ascending order. - * - * @return an iterator over the elements in this set in ascending order - */ - public Iterator<E> iterator() { - return m.navigableKeySet().iterator(); - } - - /** - * Returns an iterator over the elements in this set in descending order. - * - * @return an iterator over the elements in this set in descending order - * @since 1.6 - */ - public Iterator<E> descendingIterator() { - return m.descendingKeySet().iterator(); - } - - /** - * @since 1.6 - */ - public NavigableSet<E> descendingSet() { - return new TreeSet<>(m.descendingMap()); - } - - /** - * Returns the number of elements in this set (its cardinality). - * - * @return the number of elements in this set (its cardinality) - */ - public int size() { - return m.size(); - } - - /** - * Returns {@code true} if this set contains no elements. - * - * @return {@code true} if this set contains no elements - */ - public boolean isEmpty() { - return m.isEmpty(); - } - - /** - * Returns {@code true} if this set contains the specified element. - * More formally, returns {@code true} if and only if this set - * contains an element {@code e} such that - * <tt>(o==null ? e==null : o.equals(e))</tt>. - * - * @param o object to be checked for containment in this set - * @return {@code true} if this set contains the specified element - * @throws ClassCastException if the specified object cannot be compared - * with the elements currently in the set - * @throws NullPointerException if the specified element is null - * and this set uses natural ordering, or its comparator - * does not permit null elements - */ - public boolean contains(Object o) { - return m.containsKey(o); - } - - /** - * Adds the specified element to this set if it is not already present. - * More formally, adds the specified element {@code e} to this set if - * the set contains no element {@code e2} such that - * <tt>(e==null ? e2==null : e.equals(e2))</tt>. - * If this set already contains the element, the call leaves the set - * unchanged and returns {@code false}. - * - * @param e element to be added to this set - * @return {@code true} if this set did not already contain the specified - * element - * @throws ClassCastException if the specified object cannot be compared - * with the elements currently in this set - * @throws NullPointerException if the specified element is null - * and this set uses natural ordering, or its comparator - * does not permit null elements - */ - public boolean add(E e) { - return m.put(e, PRESENT)==null; - } - - /** - * Removes the specified element from this set if it is present. - * More formally, removes an element {@code e} such that - * <tt>(o==null ? e==null : o.equals(e))</tt>, - * if this set contains such an element. Returns {@code true} if - * this set contained the element (or equivalently, if this set - * changed as a result of the call). (This set will not contain the - * element once the call returns.) - * - * @param o object to be removed from this set, if present - * @return {@code true} if this set contained the specified element - * @throws ClassCastException if the specified object cannot be compared - * with the elements currently in this set - * @throws NullPointerException if the specified element is null - * and this set uses natural ordering, or its comparator - * does not permit null elements - */ - public boolean remove(Object o) { - return m.remove(o)==PRESENT; - } - - /** - * Removes all of the elements from this set. - * The set will be empty after this call returns. - */ - public void clear() { - m.clear(); - } - - /** - * Adds all of the elements in the specified collection to this set. - * - * @param c collection containing elements to be added to this set - * @return {@code true} if this set changed as a result of the call - * @throws ClassCastException if the elements provided cannot be compared - * with the elements currently in the set - * @throws NullPointerException if the specified collection is null or - * if any element is null and this set uses natural ordering, or - * its comparator does not permit null elements - */ - public boolean addAll(Collection<? extends E> c) { - // Use linear-time version if applicable - if (m.size()==0 && c.size() > 0 && - c instanceof SortedSet && - m instanceof TreeMap) { - SortedSet<? extends E> set = (SortedSet<? extends E>) c; - TreeMap<E,Object> map = (TreeMap<E, Object>) m; - Comparator<? super E> cc = (Comparator<? super E>) set.comparator(); - Comparator<? super E> mc = map.comparator(); - if (cc==mc || (cc != null && cc.equals(mc))) { - map.addAllForTreeSet(set, PRESENT); - return true; - } - } - return super.addAll(c); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code fromElement} or {@code toElement} - * is null and this set uses natural ordering, or its comparator - * does not permit null elements - * @throws IllegalArgumentException {@inheritDoc} - * @since 1.6 - */ - public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, - E toElement, boolean toInclusive) { - return new TreeSet<>(m.subMap(fromElement, fromInclusive, - toElement, toInclusive)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code toElement} is null and - * this set uses natural ordering, or its comparator does - * not permit null elements - * @throws IllegalArgumentException {@inheritDoc} - * @since 1.6 - */ - public NavigableSet<E> headSet(E toElement, boolean inclusive) { - return new TreeSet<>(m.headMap(toElement, inclusive)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code fromElement} is null and - * this set uses natural ordering, or its comparator does - * not permit null elements - * @throws IllegalArgumentException {@inheritDoc} - * @since 1.6 - */ - public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { - return new TreeSet<>(m.tailMap(fromElement, inclusive)); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code fromElement} or - * {@code toElement} is null and this set uses natural ordering, - * or its comparator does not permit null elements - * @throws IllegalArgumentException {@inheritDoc} - */ - public SortedSet<E> subSet(E fromElement, E toElement) { - return subSet(fromElement, true, toElement, false); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code toElement} is null - * and this set uses natural ordering, or its comparator does - * not permit null elements - * @throws IllegalArgumentException {@inheritDoc} - */ - public SortedSet<E> headSet(E toElement) { - return headSet(toElement, false); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if {@code fromElement} is null - * and this set uses natural ordering, or its comparator does - * not permit null elements - * @throws IllegalArgumentException {@inheritDoc} - */ - public SortedSet<E> tailSet(E fromElement) { - return tailSet(fromElement, true); - } - - public Comparator<? super E> comparator() { - return m.comparator(); - } - - /** - * @throws NoSuchElementException {@inheritDoc} - */ - public E first() { - return m.firstKey(); - } - - /** - * @throws NoSuchElementException {@inheritDoc} - */ - public E last() { - return m.lastKey(); - } - - // NavigableSet API methods - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified element is null - * and this set uses natural ordering, or its comparator - * does not permit null elements - * @since 1.6 - */ - public E lower(E e) { - return m.lowerKey(e); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified element is null - * and this set uses natural ordering, or its comparator - * does not permit null elements - * @since 1.6 - */ - public E floor(E e) { - return m.floorKey(e); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified element is null - * and this set uses natural ordering, or its comparator - * does not permit null elements - * @since 1.6 - */ - public E ceiling(E e) { - return m.ceilingKey(e); - } - - /** - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException if the specified element is null - * and this set uses natural ordering, or its comparator - * does not permit null elements - * @since 1.6 - */ - public E higher(E e) { - return m.higherKey(e); - } - - /** - * @since 1.6 - */ - public E pollFirst() { - Map.Entry<E,?> e = m.pollFirstEntry(); - return (e == null) ? null : e.getKey(); - } - - /** - * @since 1.6 - */ - public E pollLast() { - Map.Entry<E,?> e = m.pollLastEntry(); - return (e == null) ? null : e.getKey(); - } - - /** - * Returns a shallow copy of this {@code TreeSet} instance. (The elements - * themselves are not cloned.) - * - * @return a shallow copy of this set - */ - public Object clone() { - TreeSet<E> clone = null; - try { - clone = (TreeSet<E>) super.clone(); - } catch (CloneNotSupportedException e) { - throw new InternalError(); - } - - clone.m = new TreeMap<>(m); - return clone; - } - - /** - * Save the state of the {@code TreeSet} instance to a stream (that is, - * serialize it). - * - * @serialData Emits the comparator used to order this set, or - * {@code null} if it obeys its elements' natural ordering - * (Object), followed by the size of the set (the number of - * elements it contains) (int), followed by all of its - * elements (each an Object) in order (as determined by the - * set's Comparator, or by the elements' natural ordering if - * the set has no Comparator). - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - // Write out any hidden stuff - s.defaultWriteObject(); - - // Write out Comparator - s.writeObject(m.comparator()); - - // Write out size - s.writeInt(m.size()); - - // Write out all elements in the proper order. - for (E e : m.keySet()) - s.writeObject(e); - } - - /** - * Reconstitute the {@code TreeSet} instance from a stream (that is, - * deserialize it). - */ - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - // Read in any hidden stuff - s.defaultReadObject(); - - // Read in Comparator - Comparator<? super E> c = (Comparator<? super E>) s.readObject(); - - // Create backing TreeMap - TreeMap<E,Object> tm; - if (c==null) - tm = new TreeMap<>(); - else - tm = new TreeMap<>(c); - m = tm; - - // Read in size - int size = s.readInt(); - - tm.readTreeSet(size, s, PRESENT); - } - - private static final long serialVersionUID = -2479143000061671589L; -} diff --git a/notes/src/Vector.java b/notes/src/Vector.java deleted file mode 100644 index 41cc0277..00000000 --- a/notes/src/Vector.java +++ /dev/null @@ -1,1136 +0,0 @@ -package java.util; - -public class Vector<E> - extends AbstractList<E> - implements List<E>, 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. - * - * <p>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<? extends E> 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. - * - * <p>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<E> elements() { - return new Enumeration<E>() { - 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 - * <tt>(o==null ? e==null : o.equals(e))</tt>. - * - * @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 - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, - * or -1 if there is no such index. - * - * @param o element to search for - * @return the index of the first occurrence of the specified element in - * this 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 - * <tt>(i >= index && (o==null ? get(i)==null : o.equals(get(i))))</tt>, - * 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 - * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, - * or -1 if there is no such index. - * - * @param o element to search for - * @return the index of the last occurrence of the specified element in - * this 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 - * <tt>(i <= index && (o==null ? get(i)==null : o.equals(get(i))))</tt>, - * 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. - * - * <p>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 - * <code>size() - 1</code>. - * @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. - * - * <p>The index must be a value greater than or equal to {@code 0} - * and less than the current size of the vector. - * - * <p>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}. - * - * <p>The index must be a value greater than or equal to {@code 0} - * and less than the current size of the vector. - * - * <p>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. - * - * <p>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.) - * - * <p>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. - * - * <p>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. - * - * <p>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. - * - * <p>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<E> v = (Vector<E>) 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. - * - * <p>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 <em>only</em> 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> 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<? extends E> 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 - * (<a href="Collection.html#optional-restrictions">optional</a>) - * @throws NullPointerException if this vector contains one or more null - * elements and the specified collection does not support null - * elements - * (<a href="Collection.html#optional-restrictions">optional</a>), - * 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 - * (<a href="Collection.html#optional-restrictions">optional</a>) - * @throws NullPointerException if this vector contains one or more null - * elements and the specified collection does not support null - * elements - * (<a href="Collection.html#optional-restrictions">optional</a>), - * 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<? extends E> 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 <em>equal</em>. (Two elements {@code e1} and - * {@code e2} are <em>equal</em> 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. - * - * <p>This method eliminates the need for explicit range operations (of - * the sort that commonly exist for arrays). Any operation that expects - * a List can be used as a range operation by operating on a subList view - * instead of a whole List. For example, the following idiom - * removes a range of elements from a List: - * <pre> - * list.subList(from, to).clear(); - * </pre> - * Similar idioms may be constructed for indexOf and lastIndexOf, - * and all of the algorithms in the Collections class can be applied to - * a subList. - * - * <p>The semantics of the List returned by this method become undefined if - * the backing list (i.e., this List) is <i>structurally modified</i> in - * any way other than via the returned List. (Structural modifications are - * those that change the size of 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<E> 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. - * - * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>. - * - * @throws IndexOutOfBoundsException {@inheritDoc} - */ - public synchronized ListIterator<E> 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). - * - * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>. - * - * @see #listIterator(int) - */ - public synchronized ListIterator<E> listIterator() { - return new ListItr(0); - } - - /** - * Returns an iterator over the elements in this list in proper sequence. - * - * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>. - * - * @return an iterator over the elements in this list in proper sequence - */ - public synchronized Iterator<E> iterator() { - return new Itr(); - } - - /** - * An optimized version of AbstractList.Itr - */ - private class Itr implements Iterator<E> { - 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<E> { - 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; - } - } -}