gcc/libjava/java/util/ArrayList.java

498 lines
14 KiB
Java
Raw Normal View History

/* 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.
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;
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
* @version $Id: ArrayList.java,v 1.4 2000/03/15 21:59:06 rao Exp $
* @see java.util.AbstractList
* @see java.util.List
*/
public class ArrayList extends AbstractList
implements List, Cloneable, Serializable
{
/** the default capacity for new ArrayLists */
private static final int DEFAULT_CAPACITY = 16;
/** the number of elements in this list */
int _iSize;
/** where the data is stored */
Object[] _arData;
/** used for serialization -- denotes which fields are serialized */
private static final ObjectStreamField[] serialPersistentFields =
{new ObjectStreamField("size", int.class)};
/**
* Construct a new ArrayList with the supplied initial capacity.
*
* @param iCapacity
*/
public ArrayList(int iCapacity)
{
_arData = new Object[iCapacity];
}
/**
* 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.
*
* @param oCollection the collection whose elements will
* initialize this list
*/
public ArrayList(Collection oCollection)
{
this((int) (oCollection.size() * 1.1));
addAll(oCollection);
}
/**
* Guarantees that this list will have at least enough capacity to
* hold iMinCapacity elements.
*
* @param iMinCapacity the minimum guaranteed capacity
*/
public void ensureCapacity(int iMinCapacity)
{
Object[] arNewData;
int iCapacity = _arData.length;
if (iMinCapacity > iCapacity)
{
arNewData = new Object[Math.max((iCapacity * 2), iMinCapacity)];
System.arraycopy(_arData, 0, arNewData, 0, iCapacity);
_arData = arNewData;
}
}
/**
* Appends the supplied element to the end of this list.
*
* @param oElement the element to be appended to this list
*/
public boolean add(Object oElement)
{
ensureCapacity(_iSize + 1);
_arData[_iSize++] = oElement;
modCount++;
return true;
}
/**
* Retrieves the element at the user-supplied index.
*
* @param iIndex the index of the element we are fetching
* @throws IndexOutOfBoundsException (iIndex < 0) || (iIndex >= size())
*/
public Object get(int iIndex)
{
if (iIndex >= _iSize)
throw new IndexOutOfBoundsException("ArrayList size=" +
String.valueOf(_iSize) + "; " +
"index=" + String.valueOf(iIndex));
return _arData[iIndex];
}
/**
* Returns the number of elements in this list
*/
public int size()
{
return _iSize;
}
/**
* 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())
*/
public Object remove(int iIndex)
{
Object oResult;
if (iIndex >= _iSize)
throw new IndexOutOfBoundsException("ArrayList size=" +
String.valueOf(_iSize) + "; " +
"index=" + String.valueOf(iIndex));
oResult = _arData[iIndex];
if (iIndex != --_iSize)
System.arraycopy(_arData, (iIndex + 1), _arData, iIndex,
(_iSize - iIndex));
modCount++;
_arData[_iSize] = null;
return oResult;
}
/**
* Removes all elements in the half-open interval [iFromIndex, iToIndex).
*
* @param iFromIndex the first index which will be removed
* @param iToIndex one greater than the last index which will be
* removed
*/
public void removeRange(int iFromIndex, int iToIndex)
{
int iReduction;
int i;
if ((iFromIndex >= _iSize) || (iToIndex >= _iSize))
{
throw new IndexOutOfBoundsException("ArrayList size=" +
String.valueOf(_iSize) + "; " +
"indices=" +
String.valueOf(iFromIndex) + "," +
String.valueOf(iToIndex));
}
else if (iFromIndex > iToIndex)
{
throw new IllegalArgumentException("fromIndex(" +
String.valueOf(iFromIndex) +
") > toIndex(" +
String.valueOf(iToIndex) + ")");
}
else if (iFromIndex != iToIndex)
{
iReduction = iToIndex - iFromIndex;
System.arraycopy(_arData, (iFromIndex + iReduction), _arData,
iFromIndex, (_iSize - iFromIndex - iReduction));
modCount++;
for (i = (iFromIndex + iReduction); i < _iSize; i++)
_arData[i] = null;
_iSize -= iReduction;
}
}
/**
* Adds the supplied element at the specified index, shifting all
* elements currently at that index or higher one to the right.
*
* @param iIndex the index at which the element is being added
* @param oElement the element being added
*/
public void add(int iIndex, Object oElement)
{
if (iIndex > _iSize)
throw new IndexOutOfBoundsException("ArrayList size=" +
String.valueOf(_iSize) + "; " +
"index=" + String.valueOf(iIndex));
ensureCapacity(_iSize + 1);
System.arraycopy(_arData, iIndex, _arData,
(iIndex + 1), (_iSize - iIndex));
_arData[iIndex] = oElement;
_iSize++;
modCount++;
}
/**
* Add each element in the supplied Collection to this List.
*
* @param oCollection a Collection containing elements to be
* added to this List
*/
public boolean addAll(Collection oCollection)
{
Iterator itElements;
int iLen = oCollection.size();
if (iLen > 0)
{
ensureCapacity(_iSize + iLen);
modCount++;
itElements = oCollection.iterator();
while (itElements.hasNext())
_arData[_iSize++] = itElements.next();
return true;
}
return false;
}
/**
* Add all elements in the supplied collection, inserting them beginning
* at the specified index.
*
* @param iIndex the index at which the elements will be inserted
* @param oCollection the Collection containing the elements to be
* inserted
*/
public boolean addAll(int iIndex, Collection oCollection)
{
Iterator itElements;
int iLen;
if (iIndex > _iSize)
throw new IndexOutOfBoundsException("ArrayList size=" +
String.valueOf(_iSize) + "; " +
"index=" + String.valueOf(iIndex));
iLen = oCollection.size();
if (iLen > 0)
{
ensureCapacity(_iSize + iLen);
System.arraycopy(_arData, iIndex, _arData,
(iIndex + iLen), (_iSize - iIndex));
modCount++;
_iSize += iLen;
itElements = oCollection.iterator();
while (itElements.hasNext())
_arData[iIndex++] = itElements.next();
return true;
}
return false;
}
/**
* Creates a shallow copy of this ArrayList
*/
public Object clone()
{
ArrayList oClone;
try
{
oClone = (ArrayList) super.clone();
oClone._arData = _arData;
oClone._iSize = _iSize;
}
catch(CloneNotSupportedException e)
{
oClone = null;
}
return oClone;
}
/**
* Returns true iff oElement is in this ArrayList.
*
* @param oElement the element whose inclusion in the List is being
* tested
*/
public boolean contains(Object oElement)
{
return (indexOf(oElement) != -1);
}
/**
* Returns the lowest index at which oElement appears in this List, or
* -1 if it does not appear.
*
* @param oElement the element whose inclusion in the List is being
* tested
*/
public int indexOf(Object oElement)
{
int i;
for (i = 0; i < _iSize; i++)
{
if (doesEqual(oElement, _arData[i]))
return i;
}
return -1;
}
/**
* Returns the highest index at which oElement appears in this List, or
* -1 if it does not appear.
*
* @param oElement the element whose inclusion in the List is being
* tested
*/
public int lastIndexOf(Object oElement)
{
int i;
for (i = _iSize - 1; i >= 0; i--)
{
if (doesEqual(oElement, _arData[i]))
return i;
}
return -1;
}
/**
* Removes all elements from this List
*/
public void clear()
{
int i;
if (_iSize > 0)
{
modCount++;
_iSize = 0;
for (i = 0; i < _iSize; i++)
_arData[i] = null;
}
}
/**
* Sets the element at the specified index.
*
* @param iIndex the index at which the element is being set
* @param oElement the element to be set
* @return the element previously at the specified index, or null if
* none was there
*/
public Object set(int iIndex, Object oElement)
{
Object oResult;
if (iIndex >= _iSize)
throw new IndexOutOfBoundsException("ArrayList size=" +
String.valueOf(_iSize) + "; " +
"index=" + String.valueOf(iIndex));
oResult = _arData[iIndex];
// SEH: no structural change, so don't update modCount
_arData[iIndex] = oElement;
return oResult;
}
/**
* Returns an Object Array containing all of the elements in this ArrayList
*/
public Object[] toArray()
{
Object[] arObjects = new Object[_iSize];
System.arraycopy(_arData, 0, arObjects, 0, _iSize);
return arObjects;
}
/**
* Returns an Array whse component type is the runtime component type of
* the passes-in Array. The returned Array is populated with all of the
* 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
* of this List, then size() + 1 index will be set to null.
*
* @param arObjects the passed-in Array
*/
public Object[] toArray(Object[] arObjects)
{
Object[] arReturn = (arObjects.length >= _iSize)
? arObjects
: (Object[])
Array.newInstance(arObjects.getClass().getComponentType(), _iSize);
System.arraycopy(_arData, 0, arReturn, 0, _iSize);
if (arReturn.length > _iSize)
arReturn[_iSize] = null;
return arReturn;
}
/**
* Trims the capacity of tjis List to be equal to its size;
* a memory saver.
*/
public void trimToSize()
{
Object[] arNewData = new Object[_iSize];
System.arraycopy(_arData, 0, arNewData, 0, _iSize);
modCount++;
_arData = arNewData;
}
private void writeObject(ObjectOutputStream oOut)
throws IOException
{
int i;
ObjectOutputStream.PutField oFields = oOut.putFields();
oFields.put("size", _iSize);
oOut.writeFields();
oOut.writeInt(_arData.length);
for (i = 0; i < _arData.length; i++)
oOut.writeObject(_arData[i]);
}
private void readObject(ObjectInputStream oIn)
throws IOException, ClassNotFoundException
{
int i;
int iCapacity;
ObjectInputStream.GetField oFields = oIn.readFields();
_iSize = oFields.get("size", 0);
iCapacity = oIn.readInt();
_arData = new Object[iCapacity];
for (i = 0; i < iCapacity; i++)
_arData[i] = oIn.readObject();
}
private static final boolean doesEqual(Object oOne, Object oTwo)
{
return ((oOne == null) ? (oTwo == null) : oOne.equals(oTwo));
}
}