1. /*
  2. * @(#)ArrayList.java 1.20 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util;
  8. /**
  9. * Resizable-array implementation of the <tt>List</tt> interface. Implements
  10. * all optional list operations, and permits all elements, including
  11. * <tt>null</tt>. In addition to implementing the <tt>List</tt> interface,
  12. * this class provides methods to manipulate the size of the array that is
  13. * used internally to store the list. (This class is roughly equivalent to
  14. * <tt>Vector</tt>, except that it is unsynchronized.)<p>
  15. *
  16. * The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>,
  17. * <tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant
  18. * time. The <tt>add</tt> operation runs in <i>amortized constant time</i>,
  19. * that is, adding n elements requires O(n) time. All of the other operations
  20. * run in linear time (roughly speaking). The constant factor is low compared
  21. * to that for the <tt>LinkedList</tt> implementation.<p>
  22. *
  23. * Each <tt>ArrayList</tt> instance has a <i>capacity</i>. The capacity is
  24. * the size of the array used to store the elements in the list. It is always
  25. * at least as large as the list size. As elements are added an ArrayList,
  26. * its capacity grows automatically. The details of the growth policy are not
  27. * specified beyond the fact that adding an element has constant amortized
  28. * time cost.<p>
  29. *
  30. * An application can increase the capacity of an <tt>ArrayList</tt> instance
  31. * before adding a large number of elements using the <tt>ensureCapacity</tt>
  32. * operation. This may reduce the amount of incremental reallocation.<p>
  33. *
  34. * <strong>Note that this implementation is not synchronized.</strong> If
  35. * multiple threads access an <tt>ArrayList</tt> instance concurrently, and at
  36. * least one of the threads modifies the list structurally, it <i>must</i> be
  37. * synchronized externally. (A structural modification is any operation that
  38. * adds or deletes one or more elements, or explicitly resizes the backing
  39. * array; merely setting the value of an element is not a structural
  40. * modification.) This is typically accomplished by synchronizing on some
  41. * object that naturally encapsulates the list. If no such object exists, the
  42. * list should be "wrapped" using the <tt>Collections.synchronizedList</tt>
  43. * method. This is best done at creation time, to prevent accidental
  44. * unsynchronized access to the list:
  45. * <pre>
  46. * List list = Collections.synchronizedList(new ArrayList(...));
  47. * </pre><p>
  48. *
  49. * The iterators returned by this class's <tt>iterator</tt> and
  50. * <tt>listIterator</tt> methods are <i>fail-fast</i>: if list is structurally
  51. * modified at any time after the iterator is created, in any way except
  52. * through the iterator's own remove or add methods, the iterator will throw a
  53. * ConcurrentModificationException. Thus, in the face of concurrent
  54. * modification, the iterator fails quickly and cleanly, rather than risking
  55. * arbitrary, non-deterministic behavior at an undetermined time in the
  56. * future.
  57. *
  58. * @author Josh Bloch
  59. * @version 1.20 11/29/01
  60. * @see Collection
  61. * @see List
  62. * @see LinkedList
  63. * @see Vector
  64. * @see Collections#synchronizedList(List)
  65. * @since JDK1.2
  66. */
  67. public class ArrayList extends AbstractList implements List, Cloneable,
  68. java.io.Serializable {
  69. /**
  70. * The array buffer into which the elements of the ArrayList are stored.
  71. * The capacity of the ArrayList is the length of this array buffer.
  72. */
  73. private transient Object elementData[];
  74. /**
  75. * The size of the ArrayList (the number of elements it contains).
  76. *
  77. * @serial
  78. */
  79. private int size;
  80. /**
  81. * Constructs an empty list with the specified initial capacity.
  82. *
  83. * @param initialCapacity the initial capacity of the list.
  84. */
  85. public ArrayList(int initialCapacity) {
  86. super();
  87. this.elementData = new Object[initialCapacity];
  88. }
  89. /**
  90. * Constructs an empty list.
  91. */
  92. public ArrayList() {
  93. this(10);
  94. }
  95. /**
  96. * Constructs a list containing the elements of the specified
  97. * collection, in the order they are returned by the collection's
  98. * iterator. The <tt>ArrayList</tt> instance has an initial capacity of
  99. * 110% the size of the specified collection.
  100. */
  101. public ArrayList(Collection c) {
  102. size = c.size();
  103. elementData = new Object[(size*110)/100]; // Allow 10% room for growth
  104. c.toArray(elementData);
  105. }
  106. /**
  107. * Trims the capacity of this <tt>ArrayList</tt> instance to be the
  108. * list's current size. An application can use this operation to minimize
  109. * the storage of an <tt>ArrayList</tt> instance.
  110. */
  111. public void trimToSize() {
  112. modCount++;
  113. int oldCapacity = elementData.length;
  114. if (size < oldCapacity) {
  115. Object oldData[] = elementData;
  116. elementData = new Object[size];
  117. System.arraycopy(oldData, 0, elementData, 0, size);
  118. }
  119. }
  120. /**
  121. * Increases the capacity of this <tt>ArrayList</tt> instance, if
  122. * necessary, to ensure that it can hold at least the number of elements
  123. * specified by the minimum capacity argument.
  124. *
  125. * @param minCapacity the desired minimum capacity.
  126. */
  127. public void ensureCapacity(int minCapacity) {
  128. modCount++;
  129. int oldCapacity = elementData.length;
  130. if (minCapacity > oldCapacity) {
  131. Object oldData[] = elementData;
  132. int newCapacity = (oldCapacity * 3)/2 + 1;
  133. if (newCapacity < minCapacity)
  134. newCapacity = minCapacity;
  135. elementData = new Object[newCapacity];
  136. System.arraycopy(oldData, 0, elementData, 0, size);
  137. }
  138. }
  139. /**
  140. * Returns the number of elements in this list.
  141. *
  142. * @return the number of elements in this list.
  143. */
  144. public int size() {
  145. return size;
  146. }
  147. /**
  148. * Tests if this list has no elements.
  149. *
  150. * @return <tt>true</tt> if this list has no elements;
  151. * <tt>false</tt> otherwise.
  152. */
  153. public boolean isEmpty() {
  154. return size == 0;
  155. }
  156. /**
  157. * Returns <tt>true</tt> if this list contains the specified element.
  158. *
  159. * @param o element whose presence in this List is to be tested.
  160. */
  161. public boolean contains(Object elem) {
  162. return indexOf(elem) >= 0;
  163. }
  164. /**
  165. * Searches for the first occurence of the given argument, testing
  166. * for equality using the <tt>equals</tt> method.
  167. *
  168. * @param elem an object.
  169. * @return the index of the first occurrence of the argument in this
  170. * list; returns <tt>-1</tt> if the object is not found.
  171. * @see Object#equals(Object)
  172. */
  173. public int indexOf(Object elem) {
  174. if (elem == null) {
  175. for (int i = 0; i < size; i++)
  176. if (elementData[i]==null)
  177. return i;
  178. } else {
  179. for (int i = 0; i < size; i++)
  180. if (elem.equals(elementData[i]))
  181. return i;
  182. }
  183. return -1;
  184. }
  185. /**
  186. * Returns the index of the last occurrence of the specified object in
  187. * this list.
  188. *
  189. * @param elem the desired element.
  190. * @return the index of the last occurrence of the specified object in
  191. * this list; returns -1 if the object is not found.
  192. */
  193. public int lastIndexOf(Object elem) {
  194. if (elem == null) {
  195. for (int i = size-1; i >= 0; i--)
  196. if (elementData[i]==null)
  197. return i;
  198. } else {
  199. for (int i = size-1; i >= 0; i--)
  200. if (elem.equals(elementData[i]))
  201. return i;
  202. }
  203. return -1;
  204. }
  205. /**
  206. * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The
  207. * elements themselves are not copied.)
  208. *
  209. * @return a clone of this <tt>ArrayList</tt> instance.
  210. */
  211. public Object clone() {
  212. try {
  213. ArrayList v = (ArrayList)super.clone();
  214. v.elementData = new Object[size];
  215. System.arraycopy(elementData, 0, v.elementData, 0, size);
  216. v.modCount = 0;
  217. return v;
  218. } catch (CloneNotSupportedException e) {
  219. // this shouldn't happen, since we are Cloneable
  220. throw new InternalError();
  221. }
  222. }
  223. /**
  224. * Returns an array containing all of the elements in this list
  225. * in the correct order.
  226. *
  227. * @return an array containing all of the elements in this list
  228. * in the correct order.
  229. */
  230. public Object[] toArray() {
  231. Object[] result = new Object[size];
  232. System.arraycopy(elementData, 0, result, 0, size);
  233. return result;
  234. }
  235. /**
  236. * Returns an array containing all of the elements in this list in the
  237. * correct order. The runtime type of the returned array is that of the
  238. * specified array. If the list fits in the specified array, it is
  239. * returned therein. Otherwise, a new array is allocated with the runtime
  240. * type of the specified array and the size of this list.<p>
  241. *
  242. * If the list fits in the specified array with room to spare (i.e., the
  243. * array has more elements than the list), the element in the array
  244. * immediately following the end of the collection is set to
  245. * <tt>null</tt>. This is useful in determining the length of the list
  246. * <i>only</i> if the caller knows that the list does not contain any
  247. * <tt>null</tt> elements.
  248. *
  249. * @param a the array into which the elements of the list are to
  250. * be stored, if it is big enough; otherwise, a new array of the
  251. * same runtime type is allocated for this purpose.
  252. * @return an array containing the elements of the list.
  253. * @throws ArrayStoreException if the runtime type of a is not a supertype
  254. * of the runtime type of every element in this list.
  255. */
  256. public Object[] toArray(Object a[]) {
  257. if (a.length < size)
  258. a = (Object[])java.lang.reflect.Array.newInstance(
  259. a.getClass().getComponentType(), size);
  260. System.arraycopy(elementData, 0, a, 0, size);
  261. if (a.length > size)
  262. a[size] = null;
  263. return a;
  264. }
  265. // Positional Access Operations
  266. /**
  267. * Returns the element at the specified position in this list.
  268. *
  269. * @param index index of element to return.
  270. * @return the element at the specified position in this list.
  271. * @throws IndexOutOfBoundsException if index is out of range <tt>(index
  272. * < 0 || index >= size())</tt>.
  273. */
  274. public Object get(int index) {
  275. RangeCheck(index);
  276. return elementData[index];
  277. }
  278. /**
  279. * Replaces the element at the specified position in this list with
  280. * the specified element.
  281. *
  282. * @param index index of element to replace.
  283. * @param element element to be stored at the specified position.
  284. * @return the element previously at the specified position.
  285. * @throws IndexOutOfBoundsException if index out of range
  286. * <tt>(index < 0 || index >= size())</tt>.
  287. */
  288. public Object set(int index, Object element) {
  289. RangeCheck(index);
  290. Object oldValue = elementData[index];
  291. elementData[index] = element;
  292. return oldValue;
  293. }
  294. /**
  295. * Appends the specified element to the end of this list.
  296. *
  297. * @param o element to be appended to this list.
  298. * @return <tt>true</tt> (as per the general contract of Collection.add).
  299. */
  300. public boolean add(Object o) {
  301. ensureCapacity(size + 1); // Increments modCount!!
  302. elementData[size++] = o;
  303. return true;
  304. }
  305. /**
  306. * Inserts the specified element at the specified position in this
  307. * list. Shifts the element currently at that position (if any) and
  308. * any subsequent elements to the right (adds one to their indices).
  309. *
  310. * @param index index at which the specified element is to be inserted.
  311. * @param element element to be inserted.
  312. * @throws IndexOutOfBoundsException if index is out of range
  313. * <tt>(index < 0 || index > size())</tt>.
  314. */
  315. public void add(int index, Object element) {
  316. if (index > size || index < 0)
  317. throw new IndexOutOfBoundsException(
  318. "Index: "+index+", Size: "+size);
  319. ensureCapacity(size+1); // Increments modCount!!
  320. System.arraycopy(elementData, index, elementData, index + 1,
  321. size - index);
  322. elementData[index] = element;
  323. size++;
  324. }
  325. /**
  326. * Removes the element at the specified position in this list.
  327. * Shifts any subsequent elements to the left (subtracts one from their
  328. * indices).
  329. *
  330. * @param index the index of the element to removed.
  331. * @return the element that was removed from the list.
  332. * @throws IndexOutOfBoundsException if index out of range <tt>(index
  333. * < 0 || index >= size())</tt>.
  334. */
  335. public Object remove(int index) {
  336. RangeCheck(index);
  337. modCount++;
  338. Object oldValue = elementData[index];
  339. int numMoved = size - index - 1;
  340. if (numMoved > 0)
  341. System.arraycopy(elementData, index+1, elementData, index,
  342. numMoved);
  343. elementData[--size] = null; // Let gc do its work
  344. return oldValue;
  345. }
  346. /**
  347. * Removes all of the elements from this list. The list will
  348. * be empty after this call returns.
  349. */
  350. public void clear() {
  351. modCount++;
  352. // Let gc do its work
  353. for (int i = 0; i < size; i++)
  354. elementData[i] = null;
  355. size = 0;
  356. }
  357. /**
  358. * Appends all of the elements in the specified Collection to the end of
  359. * this list, in the order that they are returned by the
  360. * specified Collection's Iterator. The behavior of this operation is
  361. * undefined if the specified Collection is modified while the operation
  362. * is in progress. (This implies that the behavior of this call is
  363. * undefined if the specified Collection is this list, and this
  364. * list is nonempty.)
  365. *
  366. * @param index index at which to insert first element
  367. * from the specified collection.
  368. * @param c elements to be inserted into this list.
  369. * @throws IndexOutOfBoundsException if index out of range <tt>(index
  370. * < 0 || index > size())</tt>.
  371. */
  372. public boolean addAll(Collection c) {
  373. modCount++;
  374. int numNew = c.size();
  375. ensureCapacity(size + numNew);
  376. Iterator e = c.iterator();
  377. for (int i=0; i<numNew; i++)
  378. elementData[size++] = e.next();
  379. return numNew != 0;
  380. }
  381. /**
  382. * Inserts all of the elements in the specified Collection into this
  383. * list, starting at the specified position. Shifts the element
  384. * currently at that position (if any) and any subsequent elements to
  385. * the right (increases their indices). The new elements will appear
  386. * in the list in the order that they are returned by the
  387. * specified Collection's iterator.
  388. *
  389. * @param index index at which to insert first element
  390. * from the specified collection.
  391. * @param c elements to be inserted into this list.
  392. * @throws IndexOutOfBoundsException if index out of range <tt>(index
  393. * < 0 || index > size())</tt>.
  394. */
  395. public boolean addAll(int index, Collection c) {
  396. if (index > size || index < 0)
  397. throw new IndexOutOfBoundsException(
  398. "Index: "+index+", Size: "+size);
  399. int numNew = c.size();
  400. ensureCapacity(size + numNew); // Increments modCount!!
  401. int numMoved = size - index;
  402. if (numMoved > 0)
  403. System.arraycopy(elementData, index, elementData, index + numNew,
  404. numMoved);
  405. Iterator e = c.iterator();
  406. for (int i=0; i<numNew; i++)
  407. elementData[index++] = e.next();
  408. size += numNew;
  409. return numNew != 0;
  410. }
  411. /**
  412. * Removes from this List all of the elements whose index is between
  413. * fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding
  414. * elements to the left (reduces their index).
  415. * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
  416. * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
  417. *
  418. * @param fromIndex index of first element to be removed.
  419. * @param fromIndex index after last element to be removed.
  420. */
  421. protected void removeRange(int fromIndex, int toIndex) {
  422. modCount++;
  423. int numMoved = size - toIndex;
  424. System.arraycopy(elementData, toIndex, elementData, fromIndex,
  425. numMoved);
  426. // Let gc do its work
  427. int newSize = size - (toIndex-fromIndex);
  428. while (size != newSize)
  429. elementData[--size] = null;
  430. }
  431. /**
  432. * Check if the given index is in range. If not, throw an appropriate
  433. * runtime exception.
  434. */
  435. private void RangeCheck(int index) {
  436. if (index >= size || index < 0)
  437. throw new IndexOutOfBoundsException(
  438. "Index: "+index+", Size: "+size);
  439. }
  440. /**
  441. * Save the state of the <tt>ArrayList</tt> instance to a stream (that
  442. * is, serialize it).
  443. *
  444. * @serialData The length of the array backing the <tt>ArrayList</tt>
  445. * instance is emitted (int), followed by all of its elements
  446. * (each an <tt>Object</tt>) in the proper order.
  447. */
  448. private synchronized void writeObject(java.io.ObjectOutputStream s)
  449. throws java.io.IOException{
  450. // Write out element count, and any hidden stuff
  451. s.defaultWriteObject();
  452. // Write out array length
  453. s.writeInt(elementData.length);
  454. // Write out all elements in the proper order.
  455. for (int i=0; i<size; i++)
  456. s.writeObject(elementData[i]);
  457. }
  458. /**
  459. * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
  460. * deserialize it).
  461. */
  462. private synchronized void readObject(java.io.ObjectInputStream s)
  463. throws java.io.IOException, ClassNotFoundException {
  464. // Read in size, and any hidden stuff
  465. s.defaultReadObject();
  466. // Read in array length and allocate array
  467. int arrayLength = s.readInt();
  468. elementData = new Object[arrayLength];
  469. // Read in all elements in the proper order.
  470. for (int i=0; i<size; i++)
  471. elementData[i] = s.readObject();
  472. }
  473. }