[关闭]
@ZeroGeek 2015-08-18T05:52:16.000000Z 字数 25339 阅读 530

ArrayList源码解析

Java 集合


transient 关键字

用来保护数据不被序列化(主要限于Serializable,其它方式无效),详情自行google。

jdk 版本:1.7.0_55

  1. public class ArrayList<E> extends AbstractList<E>
  2. implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  3. {
  4. private static final long serialVersionUID = 8683452581122892189L;
  5. /**
  6. * 默认容量.
  7. */
  8. private static final int DEFAULT_CAPACITY = 10;
  9. /**
  10. * Shared empty array instance used for empty instances.
  11. */
  12. private static final Object[] EMPTY_ELEMENTDATA = {};
  13. /**
  14. * The array buffer into which the elements of the ArrayList are stored.
  15. * The capacity of the ArrayList is the length of this array buffer. Any
  16. * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
  17. * DEFAULT_CAPACITY when the first element is added.
  18. */
  19. private transient Object[] elementData;
  20. /**
  21. * The size of the ArrayList (the number of elements it contains).
  22. *
  23. * @serial
  24. */
  25. private int size;
  26. /**
  27. * Constructs an empty list with the specified initial capacity.
  28. *
  29. * @param initialCapacity the initial capacity of the list
  30. * @throws IllegalArgumentException if the specified initial capacity
  31. * is negative
  32. */
  33. public ArrayList(int initialCapacity) {
  34. super();
  35. if (initialCapacity < 0)
  36. throw new IllegalArgumentException("Illegal Capacity: "+
  37. initialCapacity);
  38. this.elementData = new Object[initialCapacity];
  39. }
  40. /**
  41. * Constructs an empty list with an initial capacity of ten.
  42. */
  43. public ArrayList() {
  44. super();
  45. this.elementData = EMPTY_ELEMENTDATA;
  46. }
  47. /**
  48. * Constructs a list containing the elements of the specified
  49. * collection, in the order they are returned by the collection's
  50. * iterator.
  51. *
  52. * @param c the collection whose elements are to be placed into this list
  53. * @throws NullPointerException if the specified collection is null
  54. */
  55. public ArrayList(Collection<? extends E> c) {
  56. elementData = c.toArray();
  57. size = elementData.length;
  58. // c.toArray might (incorrectly) not return Object[] (see 6260652)
  59. if (elementData.getClass() != Object[].class)
  60. elementData = Arrays.copyOf(elementData, size, Object[].class);
  61. }
  62. /**
  63. * Trims the capacity of this <tt>ArrayList</tt> instance to be the
  64. * list's current size. An application can use this operation to minimize
  65. * the storage of an <tt>ArrayList</tt> instance.
  66. */
  67. public void trimToSize() {
  68. modCount++;
  69. if (size < elementData.length) {
  70. elementData = Arrays.copyOf(elementData, size);
  71. }
  72. }
  73. /**
  74. * Increases the capacity of this <tt>ArrayList</tt> instance, if
  75. * necessary, to ensure that it can hold at least the number of elements
  76. * specified by the minimum capacity argument.
  77. *
  78. * @param minCapacity the desired minimum capacity
  79. */
  80. public void ensureCapacity(int minCapacity) {
  81. int minExpand = (elementData != EMPTY_ELEMENTDATA)
  82. // any size if real element table
  83. ? 0
  84. // larger than default for empty table. It's already supposed to be
  85. // at default size.
  86. : DEFAULT_CAPACITY;
  87. if (minCapacity > minExpand) {
  88. ensureExplicitCapacity(minCapacity);
  89. }
  90. }
  91. private void ensureCapacityInternal(int minCapacity) {
  92. if (elementData == EMPTY_ELEMENTDATA) {
  93. minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
  94. }
  95. ensureExplicitCapacity(minCapacity);
  96. }
  97. private void ensureExplicitCapacity(int minCapacity) {
  98. modCount++;
  99. // overflow-conscious code
  100. if (minCapacity - elementData.length > 0)
  101. grow(minCapacity);
  102. }
  103. /**
  104. * The maximum size of array to allocate.
  105. * Some VMs reserve some header words in an array.
  106. * Attempts to allocate larger arrays may result in
  107. * OutOfMemoryError: Requested array size exceeds VM limit
  108. */
  109. private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  110. /**
  111. * Increases the capacity to ensure that it can hold at least the
  112. * number of elements specified by the minimum capacity argument.
  113. *
  114. * @param minCapacity the desired minimum capacity
  115. */
  116. private void grow(int minCapacity) {
  117. // overflow-conscious code
  118. int oldCapacity = elementData.length;
  119. int newCapacity = oldCapacity + (oldCapacity >> 1);
  120. if (newCapacity - minCapacity < 0)
  121. newCapacity = minCapacity;
  122. if (newCapacity - MAX_ARRAY_SIZE > 0)
  123. newCapacity = hugeCapacity(minCapacity);
  124. // minCapacity is usually close to size, so this is a win:
  125. elementData = Arrays.copyOf(elementData, newCapacity);
  126. }
  127. private static int hugeCapacity(int minCapacity) {
  128. if (minCapacity < 0) // overflow
  129. throw new OutOfMemoryError();
  130. return (minCapacity > MAX_ARRAY_SIZE) ?
  131. Integer.MAX_VALUE :
  132. MAX_ARRAY_SIZE;
  133. }
  134. /**
  135. * Returns the number of elements in this list.
  136. *
  137. * @return the number of elements in this list
  138. */
  139. public int size() {
  140. return size;
  141. }
  142. /**
  143. * Returns <tt>true</tt> if this list contains no elements.
  144. *
  145. * @return <tt>true</tt> if this list contains no elements
  146. */
  147. public boolean isEmpty() {
  148. return size == 0;
  149. }
  150. /**
  151. * Returns <tt>true</tt> if this list contains the specified element.
  152. * More formally, returns <tt>true</tt> if and only if this list contains
  153. * at least one element <tt>e</tt> such that
  154. * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
  155. *
  156. * @param o element whose presence in this list is to be tested
  157. * @return <tt>true</tt> if this list contains the specified element
  158. */
  159. public boolean contains(Object o) {
  160. return indexOf(o) >= 0;
  161. }
  162. /**
  163. * Returns the index of the first occurrence of the specified element
  164. * in this list, or -1 if this list does not contain the element.
  165. * More formally, returns the lowest index <tt>i</tt> such that
  166. * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
  167. * or -1 if there is no such index.
  168. */
  169. public int indexOf(Object o) {
  170. if (o == null) {
  171. for (int i = 0; i < size; i++)
  172. if (elementData[i]==null)
  173. return i;
  174. } else {
  175. for (int i = 0; i < size; i++)
  176. if (o.equals(elementData[i]))
  177. return i;
  178. }
  179. return -1;
  180. }
  181. /**
  182. * Returns the index of the last occurrence of the specified element
  183. * in this list, or -1 if this list does not contain the element.
  184. * More formally, returns the highest index <tt>i</tt> such that
  185. * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
  186. * or -1 if there is no such index.
  187. */
  188. public int lastIndexOf(Object o) {
  189. if (o == null) {
  190. for (int i = size-1; i >= 0; i--)
  191. if (elementData[i]==null)
  192. return i;
  193. } else {
  194. for (int i = size-1; i >= 0; i--)
  195. if (o.equals(elementData[i]))
  196. return i;
  197. }
  198. return -1;
  199. }
  200. /**
  201. * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The
  202. * elements themselves are not copied.)
  203. *
  204. * @return a clone of this <tt>ArrayList</tt> instance
  205. */
  206. public Object clone() {
  207. try {
  208. @SuppressWarnings("unchecked")
  209. ArrayList<E> v = (ArrayList<E>) super.clone();
  210. v.elementData = Arrays.copyOf(elementData, size);
  211. v.modCount = 0;
  212. return v;
  213. } catch (CloneNotSupportedException e) {
  214. // this shouldn't happen, since we are Cloneable
  215. throw new InternalError();
  216. }
  217. }
  218. /**
  219. * Returns an array containing all of the elements in this list
  220. * in proper sequence (from first to last element).
  221. *
  222. * <p>The returned array will be "safe" in that no references to it are
  223. * maintained by this list. (In other words, this method must allocate
  224. * a new array). The caller is thus free to modify the returned array.
  225. *
  226. * <p>This method acts as bridge between array-based and collection-based
  227. * APIs.
  228. *
  229. * @return an array containing all of the elements in this list in
  230. * proper sequence
  231. */
  232. public Object[] toArray() {
  233. return Arrays.copyOf(elementData, size);
  234. }
  235. /**
  236. * Returns an array containing all of the elements in this list in proper
  237. * sequence (from first to last element); the runtime type of the returned
  238. * array is that of the specified array. If the list fits in the
  239. * specified array, it is returned therein. Otherwise, a new array is
  240. * allocated with the runtime type of the specified array and the size of
  241. * this list.
  242. *
  243. * <p>If the list fits in the specified array with room to spare
  244. * (i.e., the array has more elements than the list), the element in
  245. * the array immediately following the end of the collection is set to
  246. * <tt>null</tt>. (This is useful in determining the length of the
  247. * list <i>only</i> if the caller knows that the list does not contain
  248. * any null elements.)
  249. *
  250. * @param a the array into which the elements of the list are to
  251. * be stored, if it is big enough; otherwise, a new array of the
  252. * same runtime type is allocated for this purpose.
  253. * @return an array containing the elements of the list
  254. * @throws ArrayStoreException if the runtime type of the specified array
  255. * is not a supertype of the runtime type of every element in
  256. * this list
  257. * @throws NullPointerException if the specified array is null
  258. */
  259. @SuppressWarnings("unchecked")
  260. public <T> T[] toArray(T[] a) {
  261. if (a.length < size)
  262. // Make a new array of a's runtime type, but my contents:
  263. return (T[]) Arrays.copyOf(elementData, size, a.getClass());
  264. System.arraycopy(elementData, 0, a, 0, size);
  265. if (a.length > size)
  266. a[size] = null;
  267. return a;
  268. }
  269. // Positional Access Operations
  270. @SuppressWarnings("unchecked")
  271. E elementData(int index) {
  272. return (E) elementData[index];
  273. }
  274. /**
  275. * Returns the element at the specified position in this list.
  276. *
  277. * @param index index of the element to return
  278. * @return the element at the specified position in this list
  279. * @throws IndexOutOfBoundsException {@inheritDoc}
  280. */
  281. public E get(int index) {
  282. rangeCheck(index);
  283. return elementData(index);
  284. }
  285. /**
  286. * Replaces the element at the specified position in this list with
  287. * the specified element.
  288. *
  289. * @param index index of the element to replace
  290. * @param element element to be stored at the specified position
  291. * @return the element previously at the specified position
  292. * @throws IndexOutOfBoundsException {@inheritDoc}
  293. */
  294. public E set(int index, E element) {
  295. rangeCheck(index);
  296. E oldValue = elementData(index);
  297. elementData[index] = element;
  298. return oldValue;
  299. }
  300. /**
  301. * Appends the specified element to the end of this list.
  302. *
  303. * @param e element to be appended to this list
  304. * @return <tt>true</tt> (as specified by {@link Collection#add})
  305. */
  306. public boolean add(E e) {
  307. ensureCapacityInternal(size + 1); // Increments modCount!!
  308. elementData[size++] = e;
  309. return true;
  310. }
  311. /**
  312. * Inserts the specified element at the specified position in this
  313. * list. Shifts the element currently at that position (if any) and
  314. * any subsequent elements to the right (adds one to their indices).
  315. *
  316. * @param index index at which the specified element is to be inserted
  317. * @param element element to be inserted
  318. * @throws IndexOutOfBoundsException {@inheritDoc}
  319. */
  320. public void add(int index, E element) {
  321. rangeCheckForAdd(index);
  322. ensureCapacityInternal(size + 1); // Increments modCount!!
  323. System.arraycopy(elementData, index, elementData, index + 1,
  324. size - index);
  325. elementData[index] = element;
  326. size++;
  327. }
  328. /**
  329. * Removes the element at the specified position in this list.
  330. * Shifts any subsequent elements to the left (subtracts one from their
  331. * indices).
  332. *
  333. * @param index the index of the element to be removed
  334. * @return the element that was removed from the list
  335. * @throws IndexOutOfBoundsException {@inheritDoc}
  336. */
  337. public E remove(int index) {
  338. rangeCheck(index);
  339. modCount++;
  340. E oldValue = elementData(index);
  341. int numMoved = size - index - 1;
  342. if (numMoved > 0)
  343. System.arraycopy(elementData, index+1, elementData, index,
  344. numMoved);
  345. elementData[--size] = null; // clear to let GC do its work
  346. return oldValue;
  347. }
  348. /**
  349. * Removes the first occurrence of the specified element from this list,
  350. * if it is present. If the list does not contain the element, it is
  351. * unchanged. More formally, removes the element with the lowest index
  352. * <tt>i</tt> such that
  353. * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
  354. * (if such an element exists). Returns <tt>true</tt> if this list
  355. * contained the specified element (or equivalently, if this list
  356. * changed as a result of the call).
  357. *
  358. * @param o element to be removed from this list, if present
  359. * @return <tt>true</tt> if this list contained the specified element
  360. */
  361. public boolean remove(Object o) {
  362. if (o == null) {
  363. for (int index = 0; index < size; index++)
  364. if (elementData[index] == null) {
  365. fastRemove(index);
  366. return true;
  367. }
  368. } else {
  369. for (int index = 0; index < size; index++)
  370. if (o.equals(elementData[index])) {
  371. fastRemove(index);
  372. return true;
  373. }
  374. }
  375. return false;
  376. }
  377. /*
  378. * Private remove method that skips bounds checking and does not
  379. * return the value removed.
  380. */
  381. private void fastRemove(int index) {
  382. modCount++;
  383. int numMoved = size - index - 1;
  384. if (numMoved > 0)
  385. System.arraycopy(elementData, index+1, elementData, index,
  386. numMoved);
  387. elementData[--size] = null; // clear to let GC do its work
  388. }
  389. /**
  390. * Removes all of the elements from this list. The list will
  391. * be empty after this call returns.
  392. */
  393. public void clear() {
  394. modCount++;
  395. // clear to let GC do its work
  396. for (int i = 0; i < size; i++)
  397. elementData[i] = null;
  398. size = 0;
  399. }
  400. /**
  401. * Appends all of the elements in the specified collection to the end of
  402. * this list, in the order that they are returned by the
  403. * specified collection's Iterator. The behavior of this operation is
  404. * undefined if the specified collection is modified while the operation
  405. * is in progress. (This implies that the behavior of this call is
  406. * undefined if the specified collection is this list, and this
  407. * list is nonempty.)
  408. *
  409. * @param c collection containing elements to be added to this list
  410. * @return <tt>true</tt> if this list changed as a result of the call
  411. * @throws NullPointerException if the specified collection is null
  412. */
  413. public boolean addAll(Collection<? extends E> c) {
  414. Object[] a = c.toArray();
  415. int numNew = a.length;
  416. ensureCapacityInternal(size + numNew); // Increments modCount
  417. System.arraycopy(a, 0, elementData, size, numNew);
  418. size += numNew;
  419. return numNew != 0;
  420. }
  421. /**
  422. * Inserts all of the elements in the specified collection into this
  423. * list, starting at the specified position. Shifts the element
  424. * currently at that position (if any) and any subsequent elements to
  425. * the right (increases their indices). The new elements will appear
  426. * in the list in the order that they are returned by the
  427. * specified collection's iterator.
  428. *
  429. * @param index index at which to insert the first element from the
  430. * specified collection
  431. * @param c collection containing elements to be added to this list
  432. * @return <tt>true</tt> if this list changed as a result of the call
  433. * @throws IndexOutOfBoundsException {@inheritDoc}
  434. * @throws NullPointerException if the specified collection is null
  435. */
  436. public boolean addAll(int index, Collection<? extends E> c) {
  437. rangeCheckForAdd(index);
  438. Object[] a = c.toArray();
  439. int numNew = a.length;
  440. ensureCapacityInternal(size + numNew); // Increments modCount
  441. int numMoved = size - index;
  442. if (numMoved > 0)
  443. System.arraycopy(elementData, index, elementData, index + numNew,
  444. numMoved);
  445. System.arraycopy(a, 0, elementData, index, numNew);
  446. size += numNew;
  447. return numNew != 0;
  448. }
  449. /**
  450. * Removes from this list all of the elements whose index is between
  451. * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
  452. * Shifts any succeeding elements to the left (reduces their index).
  453. * This call shortens the list by {@code (toIndex - fromIndex)} elements.
  454. * (If {@code toIndex==fromIndex}, this operation has no effect.)
  455. *
  456. * @throws IndexOutOfBoundsException if {@code fromIndex} or
  457. * {@code toIndex} is out of range
  458. * ({@code fromIndex < 0 ||
  459. * fromIndex >= size() ||
  460. * toIndex > size() ||
  461. * toIndex < fromIndex})
  462. */
  463. protected void removeRange(int fromIndex, int toIndex) {
  464. modCount++;
  465. int numMoved = size - toIndex;
  466. System.arraycopy(elementData, toIndex, elementData, fromIndex,
  467. numMoved);
  468. // clear to let GC do its work
  469. int newSize = size - (toIndex-fromIndex);
  470. for (int i = newSize; i < size; i++) {
  471. elementData[i] = null;
  472. }
  473. size = newSize;
  474. }
  475. /**
  476. * Checks if the given index is in range. If not, throws an appropriate
  477. * runtime exception. This method does *not* check if the index is
  478. * negative: It is always used immediately prior to an array access,
  479. * which throws an ArrayIndexOutOfBoundsException if index is negative.
  480. */
  481. private void rangeCheck(int index) {
  482. if (index >= size)
  483. throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  484. }
  485. /**
  486. * A version of rangeCheck used by add and addAll.
  487. */
  488. private void rangeCheckForAdd(int index) {
  489. if (index > size || index < 0)
  490. throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  491. }
  492. /**
  493. * Constructs an IndexOutOfBoundsException detail message.
  494. * Of the many possible refactorings of the error handling code,
  495. * this "outlining" performs best with both server and client VMs.
  496. */
  497. private String outOfBoundsMsg(int index) {
  498. return "Index: "+index+", Size: "+size;
  499. }
  500. /**
  501. * Removes from this list all of its elements that are contained in the
  502. * specified collection.
  503. *
  504. * @param c collection containing elements to be removed from this list
  505. * @return {@code true} if this list changed as a result of the call
  506. * @throws ClassCastException if the class of an element of this list
  507. * is incompatible with the specified collection
  508. * (<a href="Collection.html#optional-restrictions">optional</a>)
  509. * @throws NullPointerException if this list contains a null element and the
  510. * specified collection does not permit null elements
  511. * (<a href="Collection.html#optional-restrictions">optional</a>),
  512. * or if the specified collection is null
  513. * @see Collection#contains(Object)
  514. */
  515. public boolean removeAll(Collection<?> c) {
  516. return batchRemove(c, false);
  517. }
  518. /**
  519. * Retains only the elements in this list that are contained in the
  520. * specified collection. In other words, removes from this list all
  521. * of its elements that are not contained in the specified collection.
  522. *
  523. * @param c collection containing elements to be retained in this list
  524. * @return {@code true} if this list changed as a result of the call
  525. * @throws ClassCastException if the class of an element of this list
  526. * is incompatible with the specified collection
  527. * (<a href="Collection.html#optional-restrictions">optional</a>)
  528. * @throws NullPointerException if this list contains a null element and the
  529. * specified collection does not permit null elements
  530. * (<a href="Collection.html#optional-restrictions">optional</a>),
  531. * or if the specified collection is null
  532. * @see Collection#contains(Object)
  533. */
  534. public boolean retainAll(Collection<?> c) {
  535. return batchRemove(c, true);
  536. }
  537. private boolean batchRemove(Collection<?> c, boolean complement) {
  538. final Object[] elementData = this.elementData;
  539. int r = 0, w = 0;
  540. boolean modified = false;
  541. try {
  542. for (; r < size; r++)
  543. if (c.contains(elementData[r]) == complement)
  544. elementData[w++] = elementData[r];
  545. } finally {
  546. // Preserve behavioral compatibility with AbstractCollection,
  547. // even if c.contains() throws.
  548. if (r != size) {
  549. System.arraycopy(elementData, r,
  550. elementData, w,
  551. size - r);
  552. w += size - r;
  553. }
  554. if (w != size) {
  555. // clear to let GC do its work
  556. for (int i = w; i < size; i++)
  557. elementData[i] = null;
  558. modCount += size - w;
  559. size = w;
  560. modified = true;
  561. }
  562. }
  563. return modified;
  564. }
  565. /**
  566. * Save the state of the <tt>ArrayList</tt> instance to a stream (that
  567. * is, serialize it).
  568. *
  569. * @serialData The length of the array backing the <tt>ArrayList</tt>
  570. * instance is emitted (int), followed by all of its elements
  571. * (each an <tt>Object</tt>) in the proper order.
  572. */
  573. private void writeObject(java.io.ObjectOutputStream s)
  574. throws java.io.IOException{
  575. // Write out element count, and any hidden stuff
  576. int expectedModCount = modCount;
  577. s.defaultWriteObject();
  578. // Write out size as capacity for behavioural compatibility with clone()
  579. s.writeInt(size);
  580. // Write out all elements in the proper order.
  581. for (int i=0; i<size; i++) {
  582. s.writeObject(elementData[i]);
  583. }
  584. if (modCount != expectedModCount) {
  585. throw new ConcurrentModificationException();
  586. }
  587. }
  588. /**
  589. * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
  590. * deserialize it).
  591. */
  592. private void readObject(java.io.ObjectInputStream s)
  593. throws java.io.IOException, ClassNotFoundException {
  594. elementData = EMPTY_ELEMENTDATA;
  595. // Read in size, and any hidden stuff
  596. s.defaultReadObject();
  597. // Read in capacity
  598. s.readInt(); // ignored
  599. if (size > 0) {
  600. // be like clone(), allocate array based upon size not capacity
  601. ensureCapacityInternal(size);
  602. Object[] a = elementData;
  603. // Read in all elements in the proper order.
  604. for (int i=0; i<size; i++) {
  605. a[i] = s.readObject();
  606. }
  607. }
  608. }
  609. /**
  610. * Returns a list iterator over the elements in this list (in proper
  611. * sequence), starting at the specified position in the list.
  612. * The specified index indicates the first element that would be
  613. * returned by an initial call to {@link ListIterator#next next}.
  614. * An initial call to {@link ListIterator#previous previous} would
  615. * return the element with the specified index minus one.
  616. *
  617. * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
  618. *
  619. * @throws IndexOutOfBoundsException {@inheritDoc}
  620. */
  621. public ListIterator<E> listIterator(int index) {
  622. if (index < 0 || index > size)
  623. throw new IndexOutOfBoundsException("Index: "+index);
  624. return new ListItr(index);
  625. }
  626. /**
  627. * Returns a list iterator over the elements in this list (in proper
  628. * sequence).
  629. *
  630. * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
  631. *
  632. * @see #listIterator(int)
  633. */
  634. public ListIterator<E> listIterator() {
  635. return new ListItr(0);
  636. }
  637. /**
  638. * Returns an iterator over the elements in this list in proper sequence.
  639. *
  640. * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
  641. *
  642. * @return an iterator over the elements in this list in proper sequence
  643. */
  644. public Iterator<E> iterator() {
  645. return new Itr();
  646. }
  647. /**
  648. * An optimized version of AbstractList.Itr
  649. */
  650. private class Itr implements Iterator<E> {
  651. int cursor; // index of next element to return
  652. int lastRet = -1; // index of last element returned; -1 if no such
  653. int expectedModCount = modCount;
  654. public boolean hasNext() {
  655. return cursor != size;
  656. }
  657. @SuppressWarnings("unchecked")
  658. public E next() {
  659. checkForComodification();
  660. int i = cursor;
  661. if (i >= size)
  662. throw new NoSuchElementException();
  663. Object[] elementData = ArrayList.this.elementData;
  664. if (i >= elementData.length)
  665. throw new ConcurrentModificationException();
  666. cursor = i + 1;
  667. return (E) elementData[lastRet = i];
  668. }
  669. public void remove() {
  670. if (lastRet < 0)
  671. throw new IllegalStateException();
  672. checkForComodification();
  673. try {
  674. ArrayList.this.remove(lastRet);
  675. cursor = lastRet;
  676. lastRet = -1;
  677. expectedModCount = modCount;
  678. } catch (IndexOutOfBoundsException ex) {
  679. throw new ConcurrentModificationException();
  680. }
  681. }
  682. final void checkForComodification() {
  683. if (modCount != expectedModCount)
  684. throw new ConcurrentModificationException();
  685. }
  686. }
  687. /**
  688. * An optimized version of AbstractList.ListItr
  689. */
  690. private class ListItr extends Itr implements ListIterator<E> {
  691. ListItr(int index) {
  692. super();
  693. cursor = index;
  694. }
  695. public boolean hasPrevious() {
  696. return cursor != 0;
  697. }
  698. public int nextIndex() {
  699. return cursor;
  700. }
  701. public int previousIndex() {
  702. return cursor - 1;
  703. }
  704. @SuppressWarnings("unchecked")
  705. public E previous() {
  706. checkForComodification();
  707. int i = cursor - 1;
  708. if (i < 0)
  709. throw new NoSuchElementException();
  710. Object[] elementData = ArrayList.this.elementData;
  711. if (i >= elementData.length)
  712. throw new ConcurrentModificationException();
  713. cursor = i;
  714. return (E) elementData[lastRet = i];
  715. }
  716. public void set(E e) {
  717. if (lastRet < 0)
  718. throw new IllegalStateException();
  719. checkForComodification();
  720. try {
  721. ArrayList.this.set(lastRet, e);
  722. } catch (IndexOutOfBoundsException ex) {
  723. throw new ConcurrentModificationException();
  724. }
  725. }
  726. public void add(E e) {
  727. checkForComodification();
  728. try {
  729. int i = cursor;
  730. ArrayList.this.add(i, e);
  731. cursor = i + 1;
  732. lastRet = -1;
  733. expectedModCount = modCount;
  734. } catch (IndexOutOfBoundsException ex) {
  735. throw new ConcurrentModificationException();
  736. }
  737. }
  738. }
  739. /**
  740. * Returns a view of the portion of this list between the specified
  741. * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. (If
  742. * {@code fromIndex} and {@code toIndex} are equal, the returned list is
  743. * empty.) The returned list is backed by this list, so non-structural
  744. * changes in the returned list are reflected in this list, and vice-versa.
  745. * The returned list supports all of the optional list operations.
  746. *
  747. * <p>This method eliminates the need for explicit range operations (of
  748. * the sort that commonly exist for arrays). Any operation that expects
  749. * a list can be used as a range operation by passing a subList view
  750. * instead of a whole list. For example, the following idiom
  751. * removes a range of elements from a list:
  752. * <pre>
  753. * list.subList(from, to).clear();
  754. * </pre>
  755. * Similar idioms may be constructed for {@link #indexOf(Object)} and
  756. * {@link #lastIndexOf(Object)}, and all of the algorithms in the
  757. * {@link Collections} class can be applied to a subList.
  758. *
  759. * <p>The semantics of the list returned by this method become undefined if
  760. * the backing list (i.e., this list) is <i>structurally modified</i> in
  761. * any way other than via the returned list. (Structural modifications are
  762. * those that change the size of this list, or otherwise perturb it in such
  763. * a fashion that iterations in progress may yield incorrect results.)
  764. *
  765. * @throws IndexOutOfBoundsException {@inheritDoc}
  766. * @throws IllegalArgumentException {@inheritDoc}
  767. */
  768. public List<E> subList(int fromIndex, int toIndex) {
  769. subListRangeCheck(fromIndex, toIndex, size);
  770. return new SubList(this, 0, fromIndex, toIndex);
  771. }
  772. static void subListRangeCheck(int fromIndex, int toIndex, int size) {
  773. if (fromIndex < 0)
  774. throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
  775. if (toIndex > size)
  776. throw new IndexOutOfBoundsException("toIndex = " + toIndex);
  777. if (fromIndex > toIndex)
  778. throw new IllegalArgumentException("fromIndex(" + fromIndex +
  779. ") > toIndex(" + toIndex + ")");
  780. }
  781. private class SubList extends AbstractList<E> implements RandomAccess {
  782. private final AbstractList<E> parent;
  783. private final int parentOffset;
  784. private final int offset;
  785. int size;
  786. SubList(AbstractList<E> parent,
  787. int offset, int fromIndex, int toIndex) {
  788. this.parent = parent;
  789. this.parentOffset = fromIndex;
  790. this.offset = offset + fromIndex;
  791. this.size = toIndex - fromIndex;
  792. this.modCount = ArrayList.this.modCount;
  793. }
  794. public E set(int index, E e) {
  795. rangeCheck(index);
  796. checkForComodification();
  797. E oldValue = ArrayList.this.elementData(offset + index);
  798. ArrayList.this.elementData[offset + index] = e;
  799. return oldValue;
  800. }
  801. public E get(int index) {
  802. rangeCheck(index);
  803. checkForComodification();
  804. return ArrayList.this.elementData(offset + index);
  805. }
  806. public int size() {
  807. checkForComodification();
  808. return this.size;
  809. }
  810. public void add(int index, E e) {
  811. rangeCheckForAdd(index);
  812. checkForComodification();
  813. parent.add(parentOffset + index, e);
  814. this.modCount = parent.modCount;
  815. this.size++;
  816. }
  817. public E remove(int index) {
  818. rangeCheck(index);
  819. checkForComodification();
  820. E result = parent.remove(parentOffset + index);
  821. this.modCount = parent.modCount;
  822. this.size--;
  823. return result;
  824. }
  825. protected void removeRange(int fromIndex, int toIndex) {
  826. checkForComodification();
  827. parent.removeRange(parentOffset + fromIndex,
  828. parentOffset + toIndex);
  829. this.modCount = parent.modCount;
  830. this.size -= toIndex - fromIndex;
  831. }
  832. public boolean addAll(Collection<? extends E> c) {
  833. return addAll(this.size, c);
  834. }
  835. public boolean addAll(int index, Collection<? extends E> c) {
  836. rangeCheckForAdd(index);
  837. int cSize = c.size();
  838. if (cSize==0)
  839. return false;
  840. checkForComodification();
  841. parent.addAll(parentOffset + index, c);
  842. this.modCount = parent.modCount;
  843. this.size += cSize;
  844. return true;
  845. }
  846. public Iterator<E> iterator() {
  847. return listIterator();
  848. }
  849. public ListIterator<E> listIterator(final int index) {
  850. checkForComodification();
  851. rangeCheckForAdd(index);
  852. final int offset = this.offset;
  853. return new ListIterator<E>() {
  854. int cursor = index;
  855. int lastRet = -1;
  856. int expectedModCount = ArrayList.this.modCount;
  857. public boolean hasNext() {
  858. return cursor != SubList.this.size;
  859. }
  860. @SuppressWarnings("unchecked")
  861. public E next() {
  862. checkForComodification();
  863. int i = cursor;
  864. if (i >= SubList.this.size)
  865. throw new NoSuchElementException();
  866. Object[] elementData = ArrayList.this.elementData;
  867. if (offset + i >= elementData.length)
  868. throw new ConcurrentModificationException();
  869. cursor = i + 1;
  870. return (E) elementData[offset + (lastRet = i)];
  871. }
  872. public boolean hasPrevious() {
  873. return cursor != 0;
  874. }
  875. @SuppressWarnings("unchecked")
  876. public E previous() {
  877. checkForComodification();
  878. int i = cursor - 1;
  879. if (i < 0)
  880. throw new NoSuchElementException();
  881. Object[] elementData = ArrayList.this.elementData;
  882. if (offset + i >= elementData.length)
  883. throw new ConcurrentModificationException();
  884. cursor = i;
  885. return (E) elementData[offset + (lastRet = i)];
  886. }
  887. public int nextIndex() {
  888. return cursor;
  889. }
  890. public int previousIndex() {
  891. return cursor - 1;
  892. }
  893. public void remove() {
  894. if (lastRet < 0)
  895. throw new IllegalStateException();
  896. checkForComodification();
  897. try {
  898. SubList.this.remove(lastRet);
  899. cursor = lastRet;
  900. lastRet = -1;
  901. expectedModCount = ArrayList.this.modCount;
  902. } catch (IndexOutOfBoundsException ex) {
  903. throw new ConcurrentModificationException();
  904. }
  905. }
  906. public void set(E e) {
  907. if (lastRet < 0)
  908. throw new IllegalStateException();
  909. checkForComodification();
  910. try {
  911. ArrayList.this.set(offset + lastRet, e);
  912. } catch (IndexOutOfBoundsException ex) {
  913. throw new ConcurrentModificationException();
  914. }
  915. }
  916. public void add(E e) {
  917. checkForComodification();
  918. try {
  919. int i = cursor;
  920. SubList.this.add(i, e);
  921. cursor = i + 1;
  922. lastRet = -1;
  923. expectedModCount = ArrayList.this.modCount;
  924. } catch (IndexOutOfBoundsException ex) {
  925. throw new ConcurrentModificationException();
  926. }
  927. }
  928. final void checkForComodification() {
  929. if (expectedModCount != ArrayList.this.modCount)
  930. throw new ConcurrentModificationException();
  931. }
  932. };
  933. }
  934. public List<E> subList(int fromIndex, int toIndex) {
  935. subListRangeCheck(fromIndex, toIndex, size);
  936. return new SubList(this, offset, fromIndex, toIndex);
  937. }
  938. private void rangeCheck(int index) {
  939. if (index < 0 || index >= this.size)
  940. throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  941. }
  942. private void rangeCheckForAdd(int index) {
  943. if (index < 0 || index > this.size)
  944. throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  945. }
  946. private String outOfBoundsMsg(int index) {
  947. return "Index: "+index+", Size: "+this.size;
  948. }
  949. private void checkForComodification() {
  950. if (ArrayList.this.modCount != this.modCount)
  951. throw new ConcurrentModificationException();
  952. }
  953. }
  954. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注