2000-08-28 06:06:44 +08:00
|
|
|
/* ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed
|
|
|
|
implementation of the List interface
|
|
|
|
Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
This file is part of GNU Classpath.
|
|
|
|
|
|
|
|
GNU Classpath is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
any later version.
|
2000-10-29 13:06:10 +08:00
|
|
|
|
2000-08-28 06:06:44 +08:00
|
|
|
GNU Classpath is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with GNU Classpath; see the file COPYING. If not, write to the
|
|
|
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
|
02111-1307 USA.
|
|
|
|
|
|
|
|
As a special exception, if you link this library with other files to
|
|
|
|
produce an executable, this library does not by itself cause the
|
|
|
|
resulting executable to be covered by the GNU General Public License.
|
|
|
|
This exception does not however invalidate any other reasons why the
|
|
|
|
executable file might be covered by the GNU General Public License. */
|
|
|
|
|
|
|
|
|
|
|
|
package java.util;
|
|
|
|
|
|
|
|
import java.lang.reflect.Array;
|
|
|
|
import java.io.Serializable;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.ObjectInputStream;
|
|
|
|
import java.io.ObjectOutputStream;
|
2000-10-29 13:06:10 +08:00
|
|
|
import java.io.ObjectInputStream.GetField;
|
|
|
|
import java.io.ObjectOutputStream.PutField;
|
2000-08-28 06:06:44 +08:00
|
|
|
import java.io.ObjectStreamField;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An array-backed implementation of the List interface. ArrayList
|
|
|
|
* performs well on simple tasks: random access into a list, appending
|
|
|
|
* to or removing from the end of a list, checking the size, &c.
|
|
|
|
*
|
|
|
|
* @author Jon A. Zeppieri
|
2000-11-27 16:30:26 +08:00
|
|
|
* @version $Id: ArrayList.java,v 1.4 2000/11/22 11:59:59 bryce Exp $
|
2000-08-28 06:06:44 +08:00
|
|
|
* @see java.util.AbstractList
|
|
|
|
* @see java.util.List
|
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public class ArrayList extends AbstractList
|
2000-08-28 06:06:44 +08:00
|
|
|
implements List, Cloneable, Serializable
|
|
|
|
{
|
|
|
|
/** the default capacity for new ArrayLists */
|
|
|
|
private static final int DEFAULT_CAPACITY = 16;
|
|
|
|
|
|
|
|
/** the number of elements in this list */
|
2000-10-29 13:06:10 +08:00
|
|
|
int size;
|
2000-08-28 06:06:44 +08:00
|
|
|
|
|
|
|
/** where the data is stored */
|
2000-10-29 13:06:10 +08:00
|
|
|
Object[] data;
|
2000-08-28 06:06:44 +08:00
|
|
|
|
|
|
|
/** used for serialization -- denotes which fields are serialized */
|
|
|
|
private static final ObjectStreamField[] serialPersistentFields =
|
2000-10-29 13:06:10 +08:00
|
|
|
{ new ObjectStreamField("size", int.class) };
|
2000-08-28 06:06:44 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct a new ArrayList with the supplied initial capacity.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param capacity Initial capacity of this ArrayList
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public ArrayList(int capacity)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
data = new Object[capacity];
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct a new ArrayList with the default capcity
|
|
|
|
*/
|
|
|
|
public ArrayList()
|
|
|
|
{
|
|
|
|
this(DEFAULT_CAPACITY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct a new ArrayList, and initialize it with the elements
|
|
|
|
* in the supplied Collection; Sun specs say that the initial
|
|
|
|
* capacity is 110% of the Collection's size.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param c the collection whose elements will initialize this list
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public ArrayList(Collection c)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
this((int) (c.size() * 1.1));
|
|
|
|
addAll(c);
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Guarantees that this list will have at least enough capacity to
|
2000-10-29 13:06:10 +08:00
|
|
|
* hold minCapacity elements.
|
2000-08-28 06:06:44 +08:00
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @specnote This implementation will grow the list to
|
|
|
|
* max(current * 2, minCapacity) if (minCapacity > current). The JCL says
|
|
|
|
* explictly that "this method increases its capacity to minCap", while
|
|
|
|
* the JDK 1.3 online docs specify that the list will grow to at least the
|
|
|
|
* size specified.
|
|
|
|
* @param minCapacity the minimum guaranteed capacity
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public void ensureCapacity(int minCapacity)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
Object[] newData;
|
|
|
|
int current = data.length;
|
|
|
|
|
|
|
|
if (minCapacity > current)
|
|
|
|
{
|
|
|
|
newData = new Object[Math.max((current * 2), minCapacity)];
|
|
|
|
System.arraycopy(data, 0, newData, 0, size);
|
|
|
|
data = newData;
|
|
|
|
}
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Appends the supplied element to the end of this list.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param e the element to be appended to this list
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public boolean add(Object e)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
|
|
|
modCount++;
|
2000-11-27 16:30:26 +08:00
|
|
|
if (size == data.length)
|
|
|
|
ensureCapacity(size + 1);
|
2000-10-29 13:06:10 +08:00
|
|
|
data[size++] = e;
|
2000-08-28 06:06:44 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieves the element at the user-supplied index.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param index the index of the element we are fetching
|
2000-08-28 06:06:44 +08:00
|
|
|
* @throws IndexOutOfBoundsException (iIndex < 0) || (iIndex >= size())
|
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public Object get(int index)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
if (index < 0 || index >= size)
|
|
|
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
|
|
size);
|
|
|
|
return data[index];
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the number of elements in this list
|
|
|
|
*/
|
|
|
|
public int size()
|
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
return size;
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes the element at the user-supplied index
|
|
|
|
*
|
|
|
|
* @param iIndex the index of the element to be removed
|
|
|
|
* @return the removed Object
|
|
|
|
* @throws IndexOutOfBoundsException (iIndex < 0) || (iIndex >= size())
|
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public Object remove(int index)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
|
|
|
modCount++;
|
2000-10-29 13:06:10 +08:00
|
|
|
if (index < 0 || index > size)
|
|
|
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
|
|
size);
|
|
|
|
Object r = data[index];
|
|
|
|
if (index != --size)
|
|
|
|
System.arraycopy(data, (index + 1), data, index, (size - index));
|
|
|
|
data[size] = null;
|
|
|
|
return r;
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes all elements in the half-open interval [iFromIndex, iToIndex).
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param fromIndex the first index which will be removed
|
|
|
|
* @param toIndex one greater than the last index which will be
|
2000-08-28 06:06:44 +08:00
|
|
|
* removed
|
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
protected void removeRange(int fromIndex, int toIndex)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
modCount++;
|
|
|
|
if (fromIndex != toIndex)
|
|
|
|
{
|
|
|
|
System.arraycopy(data, toIndex, data, fromIndex, size - toIndex);
|
2000-11-02 18:08:03 +08:00
|
|
|
size -= (toIndex - fromIndex);
|
2000-10-29 13:06:10 +08:00
|
|
|
}
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds the supplied element at the specified index, shifting all
|
|
|
|
* elements currently at that index or higher one to the right.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param index the index at which the element is being added
|
|
|
|
* @param e the item being added
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public void add(int index, Object e)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
|
|
|
modCount++;
|
2000-10-29 13:06:10 +08:00
|
|
|
if (index < 0 || index > size)
|
|
|
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
|
|
size);
|
2000-11-27 16:30:26 +08:00
|
|
|
if (size == data.length)
|
|
|
|
ensureCapacity(size + 1);
|
2000-10-29 13:06:10 +08:00
|
|
|
if (index != size)
|
|
|
|
System.arraycopy(data, index, data, index + 1, size - index);
|
|
|
|
data[index] = e;
|
|
|
|
size++;
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add each element in the supplied Collection to this List.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param c a Collection containing elements to be
|
|
|
|
* added to this List
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public boolean addAll(Collection c)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-11-22 19:59:59 +08:00
|
|
|
return addAll(size, c);
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add all elements in the supplied collection, inserting them beginning
|
|
|
|
* at the specified index.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param index the index at which the elements will be inserted
|
|
|
|
* @param c the Collection containing the elements to be
|
|
|
|
* inserted
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public boolean addAll(int index, Collection c)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
if (index < 0 || index > size)
|
|
|
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
|
|
size);
|
2000-11-02 18:08:03 +08:00
|
|
|
modCount++;
|
|
|
|
Iterator itr = c.iterator();
|
|
|
|
int csize = c.size();
|
|
|
|
|
2000-11-27 16:30:26 +08:00
|
|
|
if (csize + size > data.length)
|
|
|
|
ensureCapacity(size + csize);
|
2000-10-29 13:06:10 +08:00
|
|
|
int end = index + csize;
|
|
|
|
if (size > 0 && index != size)
|
|
|
|
System.arraycopy(data, index, data, end, csize);
|
|
|
|
size += csize;
|
|
|
|
for (; index < end; index++)
|
|
|
|
{
|
|
|
|
data[index] = itr.next();
|
|
|
|
}
|
|
|
|
return (csize > 0);
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a shallow copy of this ArrayList
|
|
|
|
*/
|
|
|
|
public Object clone()
|
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
ArrayList clone = null;
|
2000-08-28 06:06:44 +08:00
|
|
|
try
|
2000-10-29 13:06:10 +08:00
|
|
|
{
|
|
|
|
clone = (ArrayList) super.clone();
|
|
|
|
clone.data = new Object[data.length];
|
|
|
|
System.arraycopy(data, 0, clone.data, 0, size);
|
|
|
|
}
|
|
|
|
catch (CloneNotSupportedException e) {}
|
|
|
|
return clone;
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true iff oElement is in this ArrayList.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param e the element whose inclusion in the List is being
|
|
|
|
* tested
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public boolean contains(Object e)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
return (indexOf(e) != -1);
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the lowest index at which oElement appears in this List, or
|
|
|
|
* -1 if it does not appear.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param e the element whose inclusion in the List is being
|
|
|
|
* tested
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public int indexOf(Object e)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-11-22 19:59:59 +08:00
|
|
|
for (int i = 0; i < size; i++)
|
2000-10-29 13:06:10 +08:00
|
|
|
{
|
|
|
|
if (e == null ? data[i] == null : e.equals(data[i]))
|
|
|
|
return i;
|
|
|
|
}
|
2000-08-28 06:06:44 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the highest index at which oElement appears in this List, or
|
|
|
|
* -1 if it does not appear.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param e the element whose inclusion in the List is being
|
|
|
|
* tested
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public int lastIndexOf(Object e)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2000-10-29 13:06:10 +08:00
|
|
|
for (i = size - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if (e == null ? data[i] == null : e.equals(data[i]))
|
|
|
|
return i;
|
|
|
|
}
|
2000-08-28 06:06:44 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes all elements from this List
|
|
|
|
*/
|
|
|
|
public void clear()
|
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
modCount++;
|
2000-11-22 19:59:59 +08:00
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
data[i] = null;
|
|
|
|
}
|
2000-10-29 13:06:10 +08:00
|
|
|
size = 0;
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the element at the specified index.
|
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param index the index at which the element is being set
|
|
|
|
* @param e the element to be set
|
2000-08-28 06:06:44 +08:00
|
|
|
* @return the element previously at the specified index, or null if
|
|
|
|
* none was there
|
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public Object set(int index, Object e)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
Object result;
|
|
|
|
if (index < 0 || index >= size)
|
|
|
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
|
|
size);
|
|
|
|
result = data[index];
|
2000-08-28 06:06:44 +08:00
|
|
|
// SEH: no structural change, so don't update modCount
|
2000-10-29 13:06:10 +08:00
|
|
|
data[index] = e;
|
|
|
|
return result;
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an Object Array containing all of the elements in this ArrayList
|
|
|
|
*/
|
|
|
|
public Object[] toArray()
|
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
Object[] array = new Object[size];
|
|
|
|
System.arraycopy(data, 0, array, 0, size);
|
|
|
|
return array;
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2000-11-22 19:59:59 +08:00
|
|
|
* Returns an Array whose component type is the runtime component type of
|
|
|
|
* the passed-in Array. The returned Array is populated with all of the
|
2000-08-28 06:06:44 +08:00
|
|
|
* elements in this ArrayList. If the passed-in Array is not large enough
|
|
|
|
* to store all of the elements in this List, a new Array will be created
|
|
|
|
* and returned; if the passed-in Array is <i>larger</i> than the size
|
2000-10-29 13:06:10 +08:00
|
|
|
* of this List, then size() index will be set to null.
|
2000-08-28 06:06:44 +08:00
|
|
|
*
|
2000-10-29 13:06:10 +08:00
|
|
|
* @param array the passed-in Array
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
2000-10-29 13:06:10 +08:00
|
|
|
public Object[] toArray(Object[] array)
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
if (array.length < size)
|
|
|
|
array = (Object[]) Array.newInstance(array.getClass().getComponentType(),
|
|
|
|
size);
|
|
|
|
else if (array.length > size)
|
|
|
|
array[size] = null;
|
|
|
|
System.arraycopy(data, 0, array, 0, size);
|
|
|
|
return array;
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2000-10-29 13:06:10 +08:00
|
|
|
* Trims the capacity of this List to be equal to its size;
|
|
|
|
* a memory saver.
|
2000-08-28 06:06:44 +08:00
|
|
|
*/
|
|
|
|
public void trimToSize()
|
|
|
|
{
|
2000-10-29 13:06:10 +08:00
|
|
|
// not a structural change from the perspective of iterators on this list,
|
|
|
|
// so don't update modCount
|
|
|
|
Object[] newData = new Object[size];
|
|
|
|
System.arraycopy(data, 0, newData, 0, size);
|
|
|
|
data = newData;
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
2000-10-29 13:06:10 +08:00
|
|
|
private void writeObject(ObjectOutputStream out) throws IOException
|
2000-08-28 06:06:44 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2000-10-29 13:06:10 +08:00
|
|
|
ObjectOutputStream.PutField fields = out.putFields();
|
|
|
|
fields.put("size", size);
|
|
|
|
out.writeFields();
|
2000-08-28 06:06:44 +08:00
|
|
|
|
2000-10-29 13:06:10 +08:00
|
|
|
// FIXME: Do we really want to serialize unused list entries??
|
|
|
|
out.writeInt(data.length);
|
|
|
|
for (i = 0; i < data.length; i++)
|
|
|
|
out.writeObject(data[i]);
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
|
2000-10-29 13:06:10 +08:00
|
|
|
private void readObject(ObjectInputStream in)
|
2000-08-28 06:06:44 +08:00
|
|
|
throws IOException, ClassNotFoundException
|
|
|
|
{
|
|
|
|
int i;
|
2000-10-29 13:06:10 +08:00
|
|
|
int capacity;
|
2000-08-28 06:06:44 +08:00
|
|
|
|
2000-10-29 13:06:10 +08:00
|
|
|
ObjectInputStream.GetField fields = in.readFields();
|
|
|
|
size = fields.get("size", 0);
|
2000-08-28 06:06:44 +08:00
|
|
|
|
2000-10-29 13:06:10 +08:00
|
|
|
capacity = in.readInt();
|
|
|
|
data = new Object[capacity];
|
2000-08-28 06:06:44 +08:00
|
|
|
|
2000-10-29 13:06:10 +08:00
|
|
|
for (i = 0; i < capacity; i++)
|
|
|
|
data[i] = in.readObject();
|
2000-08-28 06:06:44 +08:00
|
|
|
}
|
|
|
|
}
|