/[classpath]/classpath/java/util/ArrayList.java
ViewVC logotype

Diff of /classpath/java/util/ArrayList.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.15 by mark, Sun Feb 18 15:39:58 2001 UTC revision 1.16 by ericb, Mon Oct 22 03:46:07 2001 UTC
# Line 1  Line 1 
1  /* ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed  /* ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed
2     implementation of the List interface     implementation of the List interface
3     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4    
5  This file is part of GNU Classpath.  This file is part of GNU Classpath.
6    
# Line 35  import java.io.ObjectInputStream; Line 35  import java.io.ObjectInputStream;
35  import java.io.ObjectOutputStream;  import java.io.ObjectOutputStream;
36    
37  /**  /**
38   * An array-backed implementation of the List interface.  ArrayList   * An array-backed implementation of the List interface.  This implements
39   * performs well on simple tasks:  random access into a list, appending   * all optional list operations, and permits null elements, so that it is
40   * to or removing from the end of a list, checking the size, &c.   * better than Vector, which it replaces. Random access is roughly constant
41     * time, and iteration is roughly linear time, so it is nice and fast, with
42     * less overhead than a LinkedList.
43     * <p>
44   *   *
45   * @author        Jon A. Zeppieri   * Each list has a capacity, and as the array reaches that capacity it
46   * @see           java.util.AbstractList   * is automatically transferred to a larger array. You also have access to
47   * @see           java.util.List   * ensureCapacity and trimToSize to control the backing array's size, avoiding
48     * reallocation or wasted memory.
49     * <p>
50     *
51     * ArrayList is not synchronized, so if you need multi-threaded access,
52     * consider using:<br>
53     * <code>List l = Collections.synchronizedList(new ArrayList(...));</code>
54     * <p>
55     *
56     * The iterators are <i>fail-fast</i>, meaning that any structural
57     * modification, except for <code>remove()</code> called on the iterator
58     * itself, cause the iterator to throw a
59     * {@link ConcurrentModificationException} rather than exhibit
60     * non-deterministic behavior.
61     *
62     * @author Jon A. Zeppieri
63     * @author Eric Blake <ebb9@email.byu.edu>
64     * @see Collection
65     * @see List
66     * @see LinkedList
67     * @see Vector
68     * @see Collections#synchronizedList(List)
69     * @see AbstractList
70     * @status updated to 1.4
71   */   */
72  public class ArrayList extends AbstractList  public class ArrayList extends AbstractList
73    implements List, Cloneable, Serializable    implements List, RandomAccess, Cloneable, Serializable
74  {  {
75    /** the default capacity for new ArrayLists */    /**
76       * Compatible with JDK 1.2
77       */
78      private static final long serialVersionUID = 8683452581122892189L;
79    
80      /**
81       * The default capacity for new ArrayLists.
82       */
83    private static final int DEFAULT_CAPACITY = 16;    private static final int DEFAULT_CAPACITY = 16;
84    
85    /** the number of elements in this list */    /**
86    int size;     * The number of elements in this list.
87       * @serial the list size
88       */
89      private int size;
90    
91    /** where the data is stored */    /**
92    transient Object[] data;     * Where the data is stored.
93       */
94      private transient Object[] data;
95    
96    /**    /**
97     * Construct a new ArrayList with the supplied initial capacity.     * Construct a new ArrayList with the supplied initial capacity.
98     *     *
99     * @param capacity Initial capacity of this ArrayList     * @param capacity initial capacity of this ArrayList
100       * @throws IllegalArgumentException if capacity is negative
101     */     */
102    public ArrayList(int capacity)    public ArrayList(int capacity)
103    {    {
104        // Must explicitly check, to get correct exception.
105        if (capacity < 0)
106          throw new IllegalArgumentException();
107      data = new Object[capacity];      data = new Object[capacity];
108    }    }
109    
   
110    /**    /**
111     * Construct a new ArrayList with the default capcity     * Construct a new ArrayList with the default capcity (16).
112     */     */
113    public ArrayList()    public ArrayList()
114    {    {
115      this(DEFAULT_CAPACITY);      this(DEFAULT_CAPACITY);
116    }    }
117    
118    /**    /**
119     * Construct a new ArrayList, and initialize it with the elements     * Construct a new ArrayList, and initialize it with the elements
120     * in the supplied Collection; Sun specs say that the initial     * in the supplied Collection. The initial capacity is 110% of the
121     * capacity is 110% of the Collection's size.     * Collection's size.
122     *     *
123     * @param c the collection whose elements will initialize this list     * @param c the collection whose elements will initialize this list
124       * @throws NullPointerException if c is null
125     */     */
126    public ArrayList(Collection c)    public ArrayList(Collection c)
127    {    {
128      this((int) (c.size() * 1.1));      this((int) (c.size() * 1.1f));
129      addAll(c);      addAll(c);
130    }    }
131    
132    /**    /**
133       * Trims the capacity of this List to be equal to its size;
134       * a memory saver.
135       */
136      public void trimToSize()
137      {
138        // Not a structural change from the perspective of iterators on this list,
139        // so don't update modCount.
140        if (size != data.length)
141          {
142            Object[] newData = new Object[size];
143            System.arraycopy(data, 0, newData, 0, size);
144            data = newData;
145          }
146      }
147    
148      /**
149     * Guarantees that this list will have at least enough capacity to     * Guarantees that this list will have at least enough capacity to
150     * hold minCapacity elements.     * hold minCapacity elements. This implementation will grow the list to
151       * max(current * 2, minCapacity) if (minCapacity > current). The JCL says
152       * explictly that "this method increases its capacity to minCap", while
153       * the JDK 1.3 online docs specify that the list will grow to at least the
154       * size specified.
155     *     *
    * @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.  
156     * @param minCapacity the minimum guaranteed capacity     * @param minCapacity the minimum guaranteed capacity
157     */     */
158    public void ensureCapacity(int minCapacity)    public void ensureCapacity(int minCapacity)
159    {    {
     Object[] newData;  
160      int current = data.length;      int current = data.length;
161    
162      if (minCapacity > current)      if (minCapacity > current)
163        {        {
164          newData = new Object[Math.max((current * 2), minCapacity)];          Object[] newData = new Object[Math.max(current * 2, minCapacity)];
165          System.arraycopy(data, 0, newData, 0, size);          System.arraycopy(data, 0, newData, 0, size);
166          data = newData;          data = newData;
167        }        }
168    }    }
169    
170    /**    /**
171     * Appends the supplied element to the end of this list.     * Returns the number of elements in this list.
172     *     *
173     * @param       e      the element to be appended to this list     * @return the list size
174     */     */
175    public boolean add(Object e)    public int size()
176    {    {
177      modCount++;      return size;
     if (size == data.length)  
       ensureCapacity(size + 1);  
     data[size++] = e;  
     return true;  
178    }    }
179    
180    /**    /**
181     * Retrieves the element at the user-supplied index.     * Checks if the list is empty.
182     *     *
183     * @param    index        the index of the element we are fetching     * @return true if there are no elements
    * @throws   IndexOutOfBoundsException  (iIndex < 0) || (iIndex >= size())  
184     */     */
185    public Object get(int index)    public boolean isEmpty()
186    {    {
187      if (index < 0 || index >= size)      return size == 0;
       throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +  
                                           size);  
     return data[index];  
188    }    }
189    
190    /**    /**
191     * Returns the number of elements in this list     * Returns true iff element is in this ArrayList.
192       *
193       * @param e the element whose inclusion in the List is being tested
194       * @return true if the list contains e
195     */     */
196    public int size()    public boolean contains(Object e)
197    {    {
198      return size;      return indexOf(e) != -1;
199    }    }
200    
201    /**    /**
202     * Removes the element at the user-supplied index     * Returns the lowest index at which element appears in this List, or
203       * -1 if it does not appear.
204     *     *
205     * @param     iIndex      the index of the element to be removed     * @param e the element whose inclusion in the List is being tested
206     * @return    the removed Object     * @return the index where e was found
    * @throws    IndexOutOfBoundsException  (iIndex < 0) || (iIndex >= size())  
207     */     */
208    public Object remove(int index)    public int indexOf(Object e)
209    {    {
210      modCount++;      for (int i = 0; i < size; i++)
211      if (index < 0 || index > size)        if (equals(e, data[i]))
212        throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +          return i;
213                                            size);      return -1;
     Object r = data[index];  
     if (index != --size)  
       System.arraycopy(data, (index + 1), data, index, (size - index));  
     data[size] = null;  
     return r;  
214    }    }
215    
216    /**    /**
217     * Removes all elements in the half-open interval [iFromIndex, iToIndex).     * Returns the highest index at which element appears in this List, or
218       * -1 if it does not appear.
219     *     *
220     * @param     fromIndex   the first index which will be removed     * @param e the element whose inclusion in the List is being tested
221     * @param     toIndex     one greater than the last index which will be     * @return the index where e was found
    *                         removed  
222     */     */
223    protected void removeRange(int fromIndex, int toIndex)    public int lastIndexOf(Object e)
224    {    {
225      modCount++;      for (int i = size - 1; i >= 0; i--)
226      if (fromIndex != toIndex)        if (equals(e, data[i]))
227        {          return i;
228          System.arraycopy(data, toIndex, data, fromIndex, size - toIndex);      return -1;
         size -= (toIndex - fromIndex);  
       }  
229    }    }
230    
231    /**    /**
232     * Adds the supplied element at the specified index, shifting all     * Creates a shallow copy of this ArrayList (elements are not cloned).
    * elements currently at that index or higher one to the right.  
233     *     *
234     * @param     index      the index at which the element is being added     * @return the cloned object
    * @param     e          the item being added  
235     */     */
236    public void add(int index, Object e)    public Object clone()
237    {    {
238      modCount++;      ArrayList clone = null;
239      if (index < 0 || index > size)      try
240        throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +        {
241                                            size);          clone = (ArrayList) super.clone();
242      if (size == data.length)          clone.data = (Object[]) data.clone();
243        ensureCapacity(size + 1);        }
244      if (index != size)      catch (CloneNotSupportedException e)
245        System.arraycopy(data, index, data, index + 1, size - index);            {
246      data[index] = e;          // Impossible to get here.
247      size++;        }
248        return clone;
249    }    }
250    
251    /**    /**
252     * Add each element in the supplied Collection to this List.     * Returns an Object array containing all of the elements in this ArrayList.
253       * The array is independent of this list.
254     *     *
255     * @param        c          a Collection containing elements to be     * @return an array representation of this list
    *                          added to this List  
256     */     */
257    public boolean addAll(Collection c)    public Object[] toArray()
258    {    {
259      return addAll(size, c);      Object[] array = new Object[size];
260        System.arraycopy(data, 0, array, 0, size);
261        return array;
262    }    }
263    
264    /**    /**
265     * Add all elements in the supplied collection, inserting them beginning     * Returns an Array whose component type is the runtime component type of
266     * at the specified index.     * the passed-in Array.  The returned Array is populated with all of the
267       * elements in this ArrayList.  If the passed-in Array is not large enough
268       * to store all of the elements in this List, a new Array will be created
269       * and returned; if the passed-in Array is <i>larger</i> than the size
270       * of this List, then size() index will be set to null.
271       *
272       * @param a the passed-in Array
273       * @return an array representation of this list
274       * @throws ArrayStoreException if the runtime type of a does not allow
275       *         an element in this list
276       * @throws NullPointerException if a is null
277       */
278      public Object[] toArray(Object[] a)
279      {
280        if (a.length < size)
281          a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
282                                           size);
283        else if (a.length > size)
284          a[size] = null;
285        System.arraycopy(data, 0, a, 0, size);
286        return a;
287      }
288    
289      /**
290       * Retrieves the element at the user-supplied index.
291     *     *
292     * @param     index       the index at which the elements will be inserted     * @param index the index of the element we are fetching
293     * @param     c           the Collection containing the elements to be     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
    *                        inserted  
294     */     */
295    public boolean addAll(int index, Collection c)    public Object get(int index)
296    {    {
297      if (index < 0 || index > size)      rangeExclusive(index);
298        throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +      return data[index];
                                           size);  
     modCount++;  
     Iterator itr = c.iterator();  
     int csize = c.size();  
   
     if (csize + size > data.length)  
       ensureCapacity(size + csize);  
     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);  
299    }    }
300    
301    /**    /**
302     * Creates a shallow copy of this ArrayList     * Sets the element at the specified index.
303       *
304       * @param index the index at which the element is being set
305       * @param e the element to be set
306       * @return the element previously at the specified index
307       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= 0
308     */     */
309    public Object clone()    public Object set(int index, Object e)
310    {    {
311      ArrayList clone = null;      rangeExclusive(index);
312      try      Object result = data[index];
313        {      data[index] = e;
314          clone = (ArrayList) super.clone();      return result;
         clone.data = new Object[data.length];  
         System.arraycopy(data, 0, clone.data, 0, size);  
       }  
     catch (CloneNotSupportedException e) {}  
     return clone;  
315    }    }
316    
317    /**    /**
318     * Returns true iff oElement is in this ArrayList.     * Appends the supplied element to the end of this list.
319     *     *
320     * @param     e     the element whose inclusion in the List is being     * @param e the element to be appended to this list
321     *                  tested     * @return true, the add will always succeed
322     */     */
323    public boolean contains(Object e)    public boolean add(Object e)
324    {    {
325      return (indexOf(e) != -1);      modCount++;
326        if (size == data.length)
327          ensureCapacity(size + 1);
328        data[size++] = e;
329        return true;
330    }    }
331    
332    /**    /**
333     * Returns the lowest index at which oElement appears in this List, or     * Adds the supplied element at the specified index, shifting all
334     * -1 if it does not appear.     * elements currently at that index or higher one to the right.
335     *     *
336     * @param    e       the element whose inclusion in the List is being     * @param index the index at which the element is being added
337     *                   tested     * @param e the item being added
338       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
339     */     */
340    public int indexOf(Object e)    public void add(int index, Object e)
341    {    {
342      for (int i = 0; i < size; i++)      rangeInclusive(index);
343        {      modCount++;
344          if (e == null ? data[i] == null : e.equals(data[i]))      if (size == data.length)
345            return i;        ensureCapacity(size + 1);
346        }      if (index != size)
347      return -1;        System.arraycopy(data, index, data, index + 1, size - index);
348        data[index] = e;
349        size++;
350    }    }
351    
352    /**    /**
353     * Returns the highest index at which oElement appears in this List, or     * Removes the element at the user-supplied index.
    * -1 if it does not appear.  
354     *     *
355     * @param    e       the element whose inclusion in the List is being     * @param index the index of the element to be removed
356     *                   tested     * @return the removed Object
357       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
358     */     */
359    public int lastIndexOf(Object e)    public Object remove(int index)
360    {    {
361      int i;      rangeExclusive(index);
362        Object r = data[index];
363      for (i = size - 1; i >= 0; i--)      modCount++;
364        {      if (index != --size)
365          if (e == null ? data[i] == null : e.equals(data[i]))        System.arraycopy(data, index + 1, data, index, size - index);
366            return i;      // Aid for garbage collection by releasing this pointer.
367        }      data[size] = null;
368      return -1;      return r;
369    }    }
370    
371    /**    /**
# Line 314  public class ArrayList extends AbstractL Line 373  public class ArrayList extends AbstractL
373     */     */
374    public void clear()    public void clear()
375    {    {
376      modCount++;      if (size > 0)
     for (int i = 0; i < size; i++)  
377        {        {
378          data[i] = null;          modCount++;
379        }              // Allow for garbage collection.
380      size = 0;          Arrays.fill(data, 0, size, null);
381            size = 0;
382          }
383    }    }
384    
385    /**    /**
386     * Sets the element at the specified index.     * Add each element in the supplied Collection to this List. It is undefined
387       * what happens if you modify the list while this is taking place; for
388       * example, if the collection contains this list.
389       *
390       * @param c a Collection containing elements to be added to this List
391       * @return true if the list was modified, in other words c is not empty
392       * @throws NullPointerException if c is null
393       */
394      public boolean addAll(Collection c)
395      {
396        return addAll(size, c);
397      }
398    
399      /**
400       * Add all elements in the supplied collection, inserting them beginning
401       * at the specified index.
402     *     *
403     * @param     index   the index at which the element is being set     * @param index the index at which the elements will be inserted
404     * @param     e       the element to be set     * @param c the Collection containing the elements to be inserted
405     * @return    the element previously at the specified index, or null if     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; 0
406     *            none was there     * @throws NullPointerException if c is null
407     */     */
408    public Object set(int index, Object e)    public boolean addAll(int index, Collection c)
409    {    {
410      Object result;      rangeInclusive(index);
411      if (index < 0 || index >= size)      Iterator itr = c.iterator();
412        throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +      int csize = c.size();
413                                            size);  
414      result = data[index];      modCount++;
415      // SEH: no structural change, so don't update modCount      if (csize + size > data.length)
416      data[index] = e;        ensureCapacity(size + csize);
417      return result;      int end = index + csize;
418        if (index != size)
419          System.arraycopy(data, index, data, end, csize);
420        size += csize;
421        for ( ; index < end; index++)
422          data[index] = itr.next();
423        return csize > 0;
424    }    }
425    
426    /**    /**
427     * Returns an Object Array containing all of the elements in this ArrayList     * Removes all elements in the half-open interval [fromIndex, toIndex).
428       * You asked for it if you call this with invalid arguments.
429       *
430       * @param fromIndex the first index which will be removed
431       * @param toIndex one greater than the last index which will be removed
432     */     */
433    public Object[] toArray()    protected void removeRange(int fromIndex, int toIndex)
434    {    {
435      Object[] array = new Object[size];      if (fromIndex != toIndex)
436      System.arraycopy(data, 0, array, 0, size);        {
437      return array;          modCount++;
438            System.arraycopy(data, toIndex, data, fromIndex, size - toIndex);
439            size -= toIndex - fromIndex;
440          }
441    }    }
442    
443    /**    /**
444     * Returns an Array whose component type is the runtime component type of     * Checks that the index is in the range of possible elements (inclusive).
    * the passed-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() index will be set to null.  
445     *     *
446     * @param      array      the passed-in Array     * @param index the index to check
447       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size
448     */     */
449    public Object[] toArray(Object[] array)    private void rangeInclusive(int index)
450    {    {
451      if (array.length < size)      // Implementation note: we do not check for negative ranges here, since
452        array = (Object[]) Array.newInstance(array.getClass().getComponentType(),      // that will cause an ArrayIndexOutOfBoundsException, a subclass of
453                                             size);      // the required exception, with no effort on our part.
454      else if (array.length > size)      if (index > size)
455        array[size] = null;        throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
456      System.arraycopy(data, 0, array, 0, size);                                            + size);
     return array;  
457    }    }
458    
459    /**    /**
460     * Trims the capacity of this List to be equal to its size;     * Checks that the index is in the range of existing elements (exclusive).
461     * a memory saver.       *
462       * @param index the index to check
463       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size
464     */     */
465    public void trimToSize()    private void rangeExclusive(int index)
466    {    {
467      // not a structural change from the perspective of iterators on this list,      // Implementation note: we do not check for negative ranges here, since
468      // so don't update modCount      // that will cause an ArrayIndexOutOfBoundsException, a subclass of
469      Object[] newData = new Object[size];      // the required exception, with no effort on our part.
470      System.arraycopy(data, 0, newData, 0, size);      if (index >= size)
471      data = newData;        throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
472                                              + size);
473    }    }
474    
475      /**
476       * Serializes this object to the given stream.
477       *
478       * @param out the stream to write to
479       * @throws IOException if the underlying stream fails
480       * @serialData the size field (int), the length of the backing array
481       *             (int), followed by its elements (Objects) in proper order.
482       */
483    private void writeObject(ObjectOutputStream out) throws IOException    private void writeObject(ObjectOutputStream out) throws IOException
484    {    {
485      int i;      int len = data.length;
486    
487      // The 'size' field.      // The 'size' field.
488      out.defaultWriteObject();      out.defaultWriteObject();
489    
490      // FIXME: Do we really want to serialize unused list entries??      // We serialize unused list entries to preserve capacity.
491      out.writeInt(data.length);      out.writeInt(len);
492      for (i = 0; i < data.length; i++)      for (int i = 0; i < len; i++)
493        out.writeObject(data[i]);        out.writeObject(data[i]);
494    }    }
495    
496      /**
497       * Deserializes this object from the given stream.
498       *
499       * @param in the stream to read from
500       * @throws ClassNotFoundException if the underlying stream fails
501       * @throws IOException if the underlying stream fails
502       * @serialData the size field (int), the length of the backing array
503       *             (int), followed by its elements (Objects) in proper order.
504       */
505    private void readObject(ObjectInputStream in)    private void readObject(ObjectInputStream in)
506      throws IOException, ClassNotFoundException      throws IOException, ClassNotFoundException
507    {    {
     int i;  
     int capacity;  
   
508      // the `size' field.      // the `size' field.
509      in.defaultReadObject();      in.defaultReadObject();
510    
511      capacity = in.readInt();      int capacity = in.readInt();
512      data = new Object[capacity];      data = new Object[capacity];
513    
514      for (i = 0; i < capacity; i++)      for (int i = 0; i < capacity; i++)
515        data[i] = in.readObject();        data[i] = in.readObject();
516    }    }
517  }  }

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.16

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26