1. /*
  2. * @(#)AbstractList.java 1.27 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. * This class provides a skeletal implementation of the <tt>List</tt>
  10. * interface to minimize the effort required to implement this interface
  11. * backed by a "random access" data store (such as an array). For sequential
  12. * access data (such as a linked list), <tt>AbstractSequentialList</tt> should
  13. * be used in preference to this class.<p>
  14. *
  15. * To implement an unmodifiable list, the programmer needs only to extend this
  16. * class and provide implementations for the <tt>get(int index)</tt> and
  17. * <tt>size()</tt> methods.<p>
  18. *
  19. * To implement a modifiable list, the programmer must additionally override
  20. * the <tt>set(int index, Object element)</tt> method (which otherwise throws
  21. * an <tt>UnsupportedOperationException</tt>. If the list is variable-size
  22. * the programmer must additionally override the <tt>add(int index, Object
  23. * element)</tt> and <tt>remove(int index)</tt> methods.<p>
  24. *
  25. * The programmer should generally provide a void (no argument) and collection
  26. * constructor, as per the recommendation in the <tt>Collection</tt> interface
  27. * specification.<p>
  28. *
  29. * Unlike the other abstract collection implementations, the programmer does
  30. * <i>not</i> have to provide an iterator implementation; the iterator and
  31. * list iterator are implemented by this class, on top the "random access"
  32. * methods: <tt>get(int index)</tt>, <tt>set(int index, Object element)</tt>,
  33. * <tt>set(int index, Object element)</tt>, <tt>add(int index, Object
  34. * element)</tt> and <tt>remove(int index)</tt>.<p>
  35. *
  36. * The documentation for each non-abstract methods in this class describes its
  37. * implementation in detail. Each of these methods may be overridden if the
  38. * collection being implemented admits a more efficient implementation.
  39. *
  40. * @author Josh Bloch
  41. * @version 1.27 11/29/01
  42. * @see Collection
  43. * @see List
  44. * @see AbstractSequentialList
  45. * @see AbstractCollection
  46. * @since JDK1.2
  47. */
  48. public abstract class AbstractList extends AbstractCollection implements List {
  49. /**
  50. * Sole constructor. (For invocation by subclass constructors, typically
  51. * implicit.)
  52. */
  53. protected AbstractList() {
  54. }
  55. /**
  56. * Appends the specified element to the end of this List (optional
  57. * operation). <p>
  58. *
  59. * This implementation calls <tt>add(size(), o)</tt>.<p>
  60. *
  61. * Note that this implementation throws an
  62. * <tt>UnsupportedOperationException</tt> unless <tt>add(int, Object)</tt>
  63. * is overridden.
  64. *
  65. * @param o element to be appended to this list.
  66. *
  67. * @return <tt>true</tt> (as per the general contract of
  68. * <tt>Collection.add</tt>).
  69. *
  70. * @throws UnsupportedOperationException if the <tt>add</tt> method is not
  71. * supported by this Set.
  72. *
  73. * @throws ClassCastException if the class of the specified element
  74. * prevents it from being added to this set.
  75. *
  76. * @throws IllegalArgumentException some aspect of this element prevents
  77. * it from being added to this collection.
  78. */
  79. public boolean add(Object o) {
  80. add(size(), o);
  81. return true;
  82. }
  83. /**
  84. * Returns the element at the specified position in this list.
  85. *
  86. * @param index index of element to return.
  87. *
  88. * @return the element at the specified position in this list.
  89. * @throws IndexOutOfBoundsException if the given index is out of range
  90. * (<tt>index < 0 || index >= size()</tt>).
  91. */
  92. abstract public Object get(int index);
  93. /**
  94. * Replaces the element at the specified position in this list with the
  95. * specified element (optional operation). <p>
  96. *
  97. * This implementation always throws an
  98. * <tt>UnsupportedOperationException</tt>.
  99. *
  100. * @param index index of element to replace.
  101. * @param element element to be stored at the specified position.
  102. * @return the element previously at the specified position.
  103. *
  104. * @throws UnsupportedOperationException if the <tt>set</tt> method is not
  105. * supported by this List.
  106. * @throws ClassCastException if the class of the specified element
  107. * prevents it from being added to this list.
  108. * @throws IllegalArgumentException if some aspect of the specified
  109. * element prevents it from being added to this list.
  110. *
  111. * @throws IndexOutOfBoundsException if the specified index is out of
  112. * range (<tt>index < 0 || index >= size()</tt>).
  113. */
  114. public Object set(int index, Object element) {
  115. throw new UnsupportedOperationException();
  116. }
  117. /**
  118. * Inserts the specified element at the specified position in this list
  119. * (optional operation). Shifts the element currently at that position
  120. * (if any) and any subsequent elements to the right (adds one to their
  121. * indices).<p>
  122. *
  123. * This implementation always throws an UnsupportedOperationException.
  124. *
  125. * @param index index at which the specified element is to be inserted.
  126. * @param element element to be inserted.
  127. *
  128. * @throws UnsupportedOperationException if the <tt>add</tt> method is not
  129. * supported by this list.
  130. * @throws ClassCastException if the class of the specified element
  131. * prevents it from being added to this list.
  132. * @throws IllegalArgumentException if some aspect of the specified
  133. * element prevents it from being added to this list.
  134. * @throws IndexOutOfBoundsException index is out of range (<tt>index <
  135. * 0 || index > size()</tt>).
  136. */
  137. public void add(int index, Object element) {
  138. throw new UnsupportedOperationException();
  139. }
  140. /**
  141. * Removes the element at the specified position in this list (optional
  142. * operation). Shifts any subsequent elements to the left (subtracts one
  143. * from their indices). Returns the element that was removed from the
  144. * list.<p>
  145. *
  146. * This implementation always throws an
  147. * <tt>UnsupportedOperationException</tt>.
  148. *
  149. * @param index the index of the element to remove.
  150. * @return the element previously at the specified position.
  151. *
  152. * @throws UnsupportedOperationException if the <tt>remove</tt> method is
  153. * not supported by this list.
  154. * @throws IndexOutOfBoundsException if the specified index is out of
  155. * range (<tt>index < 0 || index >= size()</tt>).
  156. */
  157. public Object remove(int index) {
  158. throw new UnsupportedOperationException();
  159. }
  160. // Search Operations
  161. /**
  162. * Returns the index in this list of the first occurence of the specified
  163. * element, or -1 if the list does not contain this element. More
  164. * formally, returns the lowest index <tt>i</tt> such that <tt>(o==null ?
  165. * get(i)==null : o.equals(get(i)))</tt>, or -1 if there is no such
  166. * index.<p>
  167. *
  168. * This implementation first gets a list iterator (with
  169. * <tt>listIterator()</tt>). Then, it iterates over the list until the
  170. * specified element is found or the end of the list is reached.
  171. *
  172. * @param o element to search for.
  173. *
  174. * @return the index in this List of the first occurence of the specified
  175. * element, or -1 if the List does not contain this element.
  176. */
  177. public int indexOf(Object o) {
  178. ListIterator e = listIterator();
  179. if (o==null) {
  180. while (e.hasNext())
  181. if (e.next()==null)
  182. return e.previousIndex();
  183. } else {
  184. while (e.hasNext())
  185. if (o.equals(e.next()))
  186. return e.previousIndex();
  187. }
  188. return -1;
  189. }
  190. /**
  191. * Returns the index in this list of the last occurence of the specified
  192. * element, or -1 if the list does not contain this element. More
  193. * formally, returns the highest index <tt>i</tt> such that <tt>(o==null ?
  194. * get(i)==null : o.equals(get(i)))</tt>, or -1 if there is no such
  195. * index.<p>
  196. *
  197. * This implementation first gets a list iterator that points to the end
  198. * of the list (with listIterator(size())). Then, it iterates backwards
  199. * over the list until the specified element is found, or the beginning of
  200. * the list is reached.
  201. *
  202. * @param o element to search for.
  203. *
  204. * @return the index in this list of the last occurence of the specified
  205. * element, or -1 if the list does not contain this element.
  206. */
  207. public int lastIndexOf(Object o) {
  208. ListIterator e = listIterator(size());
  209. if (o==null) {
  210. while (e.hasPrevious())
  211. if (e.previous()==null)
  212. return e.nextIndex();
  213. } else {
  214. while (e.hasPrevious())
  215. if (o.equals(e.previous()))
  216. return e.nextIndex();
  217. }
  218. return -1;
  219. }
  220. // Bulk Operations
  221. /**
  222. * Removes all of the elements from this collection (optional operation).
  223. * The collection will be empty after this call returns (unless it throws
  224. * an exception).<p>
  225. *
  226. * This implementation calls <tt>removeRange(0, size())</tt>.<p>
  227. *
  228. * Note that this implementation throws an
  229. * <tt>UnsupportedOperationException</tt> unless <tt>remove(int
  230. * index)</tt> or <tt>removeRange(int fromIndex, int toIndex)</tt> is
  231. * overridden.
  232. *
  233. * @throws UnsupportedOperationException if the <tt>clear</tt> method is
  234. * not supported by this Collection.
  235. */
  236. public void clear() {
  237. removeRange(0, size());
  238. }
  239. /**
  240. * Inserts all of the elements in the specified collection into this list
  241. * at the specified position (optional operation). Shifts the element
  242. * currently at that position (if any) and any subsequent elements to the
  243. * right (increases their indices). The new elements will appear in the
  244. * list in the order that they are returned by the specified collection's
  245. * iterator. The behavior of this operation is unspecified if the
  246. * specified collection is modified while the operation is in progress.
  247. * (Note that this will occur if the specified collection is this list,
  248. * and it's nonempty.)<p>
  249. *
  250. * This implementation gets an iterator over the specified collection and
  251. * iterates over it, inserting the elements obtained from the iterator
  252. * into this list at the appropriate position, one at a time, using
  253. * <tt>add(int, Object)</tt>. Many implementations will override this
  254. * method for efficiency.<p>
  255. *
  256. * Note that this implementation throws an
  257. * <tt>UnsupportedOperationException</tt> unless <tt>add(int, Object)</tt>
  258. * is overridden.
  259. *
  260. * @return <tt>true</tt> if this list changed as a result of the call.
  261. * @param index index at which to insert the first element from the
  262. * specified collection.
  263. * @param c elements to be inserted into this List.
  264. *
  265. * @throws UnsupportedOperationException if the <tt>addAll</tt> method is
  266. * not supported by this list.
  267. *
  268. * @throws ClassCastException if the class of an element of the specified
  269. * collection prevents it from being added to this List.
  270. *
  271. * @throws IllegalArgumentException some aspect an element of the
  272. * specified collection prevents it from being added to this
  273. * List.
  274. *
  275. * @throws IndexOutOfBoundsException index out of range (<tt>index < 0
  276. * || index > size()</tt>).
  277. */
  278. public boolean addAll(int index, Collection c) {
  279. boolean modified = false;
  280. Iterator e = c.iterator();
  281. while (e.hasNext()) {
  282. add(index++, e.next());
  283. modified = true;
  284. }
  285. return modified;
  286. }
  287. // Iterators
  288. /**
  289. * Returns an iterator over the elements in this list in proper
  290. * sequence. <p>
  291. *
  292. * This implementation returns a straightforward implementation of the
  293. * iterator interface, relying on the backing list's <tt>size()</tt>,
  294. * <tt>get(int)</tt>, and <tt>remove(int)</tt> methods.<p>
  295. *
  296. * Note that the iterator returned by this method will throw an
  297. * <tt>UnsupportedOperationException</tt> in response to its
  298. * <tt>remove</tt> method unless the list's <tt>remove(int)</tt> method is
  299. * overridden.<p>
  300. *
  301. * This implementation can be made to throw runtime exceptions in the face
  302. * of concurrent modification, as described in the specification for the
  303. * (protected) <tt>modCount</tt> field.
  304. *
  305. * @return an iterator over the elements in this list in proper sequence.
  306. *
  307. * @see #modCount
  308. */
  309. public Iterator iterator() {
  310. return new Itr();
  311. }
  312. /**
  313. * Returns an iterator of the elements in this list (in proper sequence).
  314. * This implementation returns <tt>listIterator(0)</tt>.
  315. *
  316. * @return an iterator of the elements in this list (in proper sequence).
  317. *
  318. * @see #listIterator(int)
  319. */
  320. public ListIterator listIterator() {
  321. return listIterator(0);
  322. }
  323. /**
  324. * Returns a list iterator of the elements in this list (in proper
  325. * sequence), starting at the specified position in the list. The
  326. * specified index indicates the first element that would be returned by
  327. * an initial call to the <tt>next</tt> method. An initial call to
  328. * the <tt>previous</tt> method would return the element with the
  329. * specified index minus one.<p>
  330. *
  331. * This implementation returns a straightforward implementation of the
  332. * <tt>ListIterator</tt> interface that extends the implementation of the
  333. * <tt>Iterator</tt> interface returned by the <tt>iterator()</tt> method.
  334. * The <tt>ListIterator</tt> implementation relies on the backing list's
  335. * <tt>get(int)</tt>, <tt>set(int, Object)</tt>, <tt>add(int, Object)</tt>
  336. * and <tt>remove(int)</tt> methods.<p>
  337. *
  338. * Note that the list iterator returned by this implementation will throw
  339. * an <tt>UnsupportedOperationException</tt> in response to its
  340. * <tt>remove</tt>, <tt>set</tt> and <tt>add</tt> methods unless the
  341. * list's <tt>remove(int)</tt>, <tt>set(int, Object)</tt>, and
  342. * <tt>add(int, Object)</tt> methods are overridden.<p>
  343. *
  344. * This implementation can be made to throw runtime exceptions in the
  345. * face of concurrent modification, as described in the specification for
  346. * the (protected) <tt>modCount</tt> field.
  347. *
  348. * @param index index of the first element to be returned from the list
  349. * iterator (by a call to the <tt>next</tt> method).
  350. *
  351. * @return a list iterator of the elements in this list (in proper
  352. * sequence), starting at the specified position in the list.
  353. *
  354. * @throws IndexOutOfBoundsException if the specified index is out of
  355. * range (<tt>index < 0 || index > size()</tt>).
  356. *
  357. * @see #modCount
  358. */
  359. public ListIterator listIterator(final int index) {
  360. if (index<0 || index>size())
  361. throw new IndexOutOfBoundsException("Index: "+index);
  362. return new ListItr(index);
  363. }
  364. private class Itr implements Iterator {
  365. /**
  366. * Index of element to be returned by subsequent call to next.
  367. */
  368. int cursor = 0;
  369. /**
  370. * Index of element returned by most recent call to next or
  371. * previous. Reset to -1 if this element is deleted by a call
  372. * to remove.
  373. */
  374. int lastRet = -1;
  375. /**
  376. * The modCount value that the iterator believes that the backing
  377. * List should have. If this expectation is violated, the iterator
  378. * has detected concurrent modification.
  379. */
  380. int expectedModCount = modCount;
  381. public boolean hasNext() {
  382. return cursor != size();
  383. }
  384. public Object next() {
  385. try {
  386. Object next = get(cursor);
  387. checkForComodification();
  388. lastRet = cursor++;
  389. return next;
  390. } catch(IndexOutOfBoundsException e) {
  391. checkForComodification();
  392. throw new NoSuchElementException();
  393. }
  394. }
  395. public void remove() {
  396. if (lastRet == -1)
  397. throw new IllegalStateException();
  398. try {
  399. AbstractList.this.remove(lastRet);
  400. if (lastRet < cursor)
  401. cursor--;
  402. lastRet = -1;
  403. int newModCount = modCount;
  404. if (newModCount - expectedModCount > 1)
  405. throw new ConcurrentModificationException();
  406. expectedModCount = newModCount;
  407. } catch(IndexOutOfBoundsException e) {
  408. throw new ConcurrentModificationException();
  409. }
  410. }
  411. final void checkForComodification() {
  412. if (modCount != expectedModCount)
  413. throw new ConcurrentModificationException();
  414. }
  415. }
  416. private class ListItr extends Itr implements ListIterator {
  417. ListItr(int index) {
  418. cursor = index;
  419. }
  420. public boolean hasPrevious() {
  421. return cursor != 0;
  422. }
  423. public Object previous() {
  424. try {
  425. Object previous = get(--cursor);
  426. checkForComodification();
  427. lastRet = cursor;
  428. return previous;
  429. } catch(IndexOutOfBoundsException e) {
  430. checkForComodification();
  431. throw new NoSuchElementException();
  432. }
  433. }
  434. public int nextIndex() {
  435. return cursor;
  436. }
  437. public int previousIndex() {
  438. return cursor-1;
  439. }
  440. public void set(Object o) {
  441. if (lastRet == -1)
  442. throw new IllegalStateException();
  443. try {
  444. AbstractList.this.set(lastRet, o);
  445. int newModCount = modCount;
  446. if (newModCount - expectedModCount > 1)
  447. throw new ConcurrentModificationException();
  448. expectedModCount = newModCount;
  449. } catch(IndexOutOfBoundsException e) {
  450. throw new ConcurrentModificationException();
  451. }
  452. }
  453. public void add(Object o) {
  454. try {
  455. AbstractList.this.add(cursor++, o);
  456. lastRet = -1;
  457. int newModCount = modCount;
  458. if (newModCount - expectedModCount > 1)
  459. throw new ConcurrentModificationException();
  460. expectedModCount = newModCount;
  461. } catch(IndexOutOfBoundsException e) {
  462. throw new ConcurrentModificationException();
  463. }
  464. }
  465. }
  466. /**
  467. * Returns a view of the portion of this list between <tt>fromIndex</tt>,
  468. * inclusive, and <tt>toIndex</tt>, exclusive. The returned list is
  469. * backed by this list, so changes in the returned list are reflected in
  470. * this list, and vice-versa. The returned list supports all of the
  471. * optional list operations supported by this list.<p>
  472. *
  473. * This method eliminates the need for explicit range operations (of the
  474. * sort that commonly exist for arrays). Any operation that expects a
  475. * list can be used as a range operation by operating on a subList view
  476. * instead of a whole list. For example, the following idiom removes a
  477. * range of elements from a list:
  478. *
  479. * <pre> * list.subList(from, to).clear(); </pre> n Similar idioms may be
  480. * constructed for <tt>indexOf</tt> and <tt>lastIndexOf</tt>, and all of
  481. * the algorithms in the <tt>Collections</tt> class can be applied to a
  482. * subList.<p>
  483. *
  484. * The semantics of the list returned by this method become undefined if
  485. * the backing list (i.e., this list) is <i>structurally modified</i> in
  486. * any way other than via the returned list. (Structural modifications are
  487. * those that change the size of the list, or otherwise perturb it in such
  488. * a fashion that iterations in progress may yield incorrect results.)<p>
  489. *
  490. * This implementation returns a list that subclasses
  491. * <tt>AbstractList</tt>. The subclass stores, in private fields, the
  492. * offset of the subList within the backing list, the size of the subList
  493. * (which can change over its lifetime), and the expected
  494. * <tt>modCount</tt> value of the backing list.<p>
  495. *
  496. * The subclass's <tt>set(int, Object)</tt>, <tt>get(int)</tt>,
  497. * <tt>add(int, Object)</tt>, <tt>remove(int)</tt>, <tt>addAll(int,
  498. * Collection)</tt> and <tt>removeRange(int, int)</tt> methods all
  499. * delegate to the corresponding methods on the backing abstract list,
  500. * after bounds-checking the index and adjusting for the offset. The
  501. * <tt>addAll(Collection c)</tt> method merely returns <tt>addAll(size,
  502. * c)</tt>.<p>
  503. *
  504. * The <tt>listIterator(int)</tt> method returns a "wrapper object" over a
  505. * list iterator on the backing list, which is created with the
  506. * corresponding method on the backing list. The <tt>iterator</tt> method
  507. * merely returns <tt>listIterator()</tt>, and the <tt>size</tt> method
  508. * merely returns the subclass's <tt>size</tt> field.<p>
  509. *
  510. * All methods first check to see if the actual <tt>modCount</tt> of the
  511. * backing list is equal to its expected value, and throw a
  512. * <tt>ConcurrentModificationException</tt> if it is not.
  513. *
  514. * @param fromIndex low endpoint (inclusive) of the subList.
  515. * @param toKey high endpoint (exclusive) of the subList.
  516. * @return a view of the specified range within this list.
  517. * @throws IndexOutOfBoundsException endpoint index value out of range
  518. * <tt>(fromIndex < 0 || toIndex > size)</tt>
  519. * @throws IllegalArgumentException endpoint indices out of order
  520. * <tt>(fromIndex > toIndex)</tt>
  521. */
  522. public List subList(int fromIndex, int toIndex) {
  523. return new SubList(this, fromIndex, toIndex);
  524. }
  525. // Comparison and hashing
  526. /**
  527. * Compares the specified object with this list for equality. Returns
  528. * <tt>true</tt> if and only if the specified object is also a list, both
  529. * lists have the same size, and all corresponding pairs of elements in
  530. * the two lists are <i>equal</i>. (Two elements <tt>e1</tt> and
  531. * <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null :
  532. * e1.equals(e2))</tt>.) In other words, two lists are defined to be
  533. * equal if they contain the same elements in the same order.<p>
  534. *
  535. * This implementation first checks if the specified object is this
  536. * list. If so, it returns <tt>true</tt> if not, it checks if the
  537. * specified object is a list. If not, it returns <tt>false</tt> if so,
  538. * it iterates over both lists, comparing corresponding pairs of elements.
  539. * If any comparison returns <tt>false</tt>, this method returns
  540. * <tt>false</tt>. If either iterator runs out of elements before the
  541. * other it returns <tt>false</tt> (as the lists are of unequal length);
  542. * otherwise it returns <tt>true</tt> when the iterations complete.
  543. *
  544. * @param o the object to be compared for equality with this list.
  545. *
  546. * @return <tt>true</tt> if the specified object is equal to this list.
  547. */
  548. public boolean equals(Object o) {
  549. if (o == this)
  550. return true;
  551. if (!(o instanceof List))
  552. return false;
  553. ListIterator e1 = listIterator();
  554. ListIterator e2 = ((List) o).listIterator();
  555. while(e1.hasNext() && e2.hasNext()) {
  556. Object o1 = e1.next();
  557. Object o2 = e2.next();
  558. if (!(o1==null ? o2==null : o1.equals(o2)))
  559. return false;
  560. }
  561. return !(e1.hasNext() || e2.hasNext());
  562. }
  563. /**
  564. * Returns the hash code value for this list. <p>
  565. *
  566. * This implementation uses exactly the code that is used to define the
  567. * list hash function in the documentation for the <tt>List.hashCode</tt>
  568. * method.
  569. *
  570. * @return the hash code value for this list.
  571. */
  572. public int hashCode() {
  573. int hashCode = 1;
  574. Iterator i = iterator();
  575. while (i.hasNext()) {
  576. Object obj = i.next();
  577. hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
  578. }
  579. return hashCode;
  580. }
  581. /**
  582. * Removes from this list all of the elements whose index is between
  583. * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
  584. * Shifts any succeeding elements to the left (reduces their index). This
  585. * call shortens the ArrayList by <tt>(toIndex - fromIndex)</tt>
  586. * elements. (If <tt>toIndex==fromIndex</tt>, this operation has no
  587. * effect.)<p>
  588. *
  589. * This method is called by the <tt>clear</tt> operation on this list
  590. * and its subLists. Overriding this method to take advantage of
  591. * the internals of the list implementation can <i>substantially</i>
  592. * improve the performance of the <tt>clear</tt> operation on this list
  593. * and its subLists.<p>
  594. *
  595. * This implementation gets a list iterator positioned before
  596. * <tt>fromIndex</tt>, and repeatedly calls <tt>ListIterator.next</tt>
  597. * followed by <tt>ListIterator.remove</tt> until the entire range has
  598. * been removed. <b>Note: if <tt>ListIterator.remove</tt> requires linear
  599. * time, this implementation requires quadratic time.</b>
  600. *
  601. * @param fromIndex index of first element to be removed.
  602. * @param toIndex index after last element to be removed.
  603. */
  604. protected void removeRange(int fromIndex, int toIndex) {
  605. ListIterator it = listIterator(fromIndex);
  606. for (int i=0, n=toIndex-fromIndex; i<n; i++) {
  607. it.next();
  608. it.remove();
  609. }
  610. }
  611. /**
  612. * The number of times this list has been <i>structurally modified</i>.
  613. * Structural modifications are those that change the size of the
  614. * list, or otherwise perturb it in such a fashion that iterations in
  615. * progress may yield incorrect results.<p>
  616. *
  617. * This field is used by the iterator and list iterator implementation
  618. * returned by the <tt>iterator</tt> and <tt>listIterator</tt> methods.
  619. * If the value of this field changes unexpectedly, the iterator (or list
  620. * iterator) will throw a <tt>ConcurrentModificationException</tt> in
  621. * response to the <tt>next</tt>, <tt>remove</tt>, <tt>previous</tt>,
  622. * <tt>set</tt> or <tt>add</tt> operations. This provides
  623. * <i>fail-fast</i> behavior, rather than non-deterministic behavior in
  624. * the face of concurrent modification during iteration.<p>
  625. *
  626. * <b>Use of this field by subclasses is optional.</b> If a subclass
  627. * wishes to provide fail-fast iterators (and list iterators), then it
  628. * merely has to increment this field in its <tt>add(int, Object)</tt> and
  629. * <tt>remove(int)</tt> methods (and any other methods that it overrides
  630. * that result in structural modifications to the list). A single call to
  631. * <tt>add(int, Object)</tt> or <tt>remove(int)</tt> must add no more than
  632. * one to this field, or the iterators (and list iterators) will throw
  633. * bogus <tt>ConcurrentModificationExceptions</tt>. If an implementation
  634. * does not wish to provide fail-fast iterators, this field may be
  635. * ignored.
  636. */
  637. protected transient int modCount = 0;
  638. }
  639. class SubList extends AbstractList {
  640. private AbstractList l;
  641. private int offset;
  642. private int size;
  643. private int expectedModCount;
  644. SubList(AbstractList list, int fromIndex, int toIndex) {
  645. if (fromIndex < 0)
  646. throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
  647. if (toIndex > list.size())
  648. throw new IndexOutOfBoundsException("toIndex = " + toIndex);
  649. if (fromIndex > toIndex)
  650. throw new IllegalArgumentException("fromIndex(" + fromIndex +
  651. ") > toIndex(" + toIndex + ")");
  652. l = list;
  653. offset = fromIndex;
  654. size = toIndex - fromIndex;
  655. expectedModCount = l.modCount;
  656. }
  657. public Object set(int index, Object element) {
  658. rangeCheck(index);
  659. checkForComodification();
  660. return l.set(index+offset, element);
  661. }
  662. public Object get(int index) {
  663. rangeCheck(index);
  664. checkForComodification();
  665. return l.get(index+offset);
  666. }
  667. public int size() {
  668. checkForComodification();
  669. return size;
  670. }
  671. public void add(int index, Object element) {
  672. if (index<0 || index>size)
  673. throw new IndexOutOfBoundsException();
  674. checkForComodification();
  675. l.add(index+offset, element);
  676. expectedModCount = l.modCount;
  677. size++;
  678. modCount++;
  679. }
  680. public Object remove(int index) {
  681. rangeCheck(index);
  682. checkForComodification();
  683. Object result = l.remove(index+offset);
  684. expectedModCount = l.modCount;
  685. size--;
  686. modCount++;
  687. return result;
  688. }
  689. protected void removeRange(int fromIndex, int toIndex) {
  690. checkForComodification();
  691. l.removeRange(fromIndex+offset, toIndex+offset);
  692. expectedModCount = l.modCount;
  693. size -= (toIndex-fromIndex);
  694. modCount++;
  695. }
  696. public boolean addAll(Collection c) {
  697. return addAll(size, c);
  698. }
  699. public boolean addAll(int index, Collection c) {
  700. if (index<0 || index>size)
  701. throw new IndexOutOfBoundsException(
  702. "Index: "+index+", Size: "+size);
  703. int cSize = c.size();
  704. if (cSize==0)
  705. return false;
  706. checkForComodification();
  707. l.addAll(offset+index, c);
  708. expectedModCount = l.modCount;
  709. size += cSize;
  710. modCount++;
  711. return true;
  712. }
  713. public Iterator iterator() {
  714. return listIterator();
  715. }
  716. public ListIterator listIterator(final int index) {
  717. checkForComodification();
  718. if (index<0 || index>size)
  719. throw new IndexOutOfBoundsException(
  720. "Index: "+index+", Size: "+size);
  721. return new ListIterator() {
  722. private ListIterator i = l.listIterator(index+offset);
  723. public boolean hasNext() {
  724. return nextIndex() < size;
  725. }
  726. public Object next() {
  727. if (hasNext())
  728. return i.next();
  729. else
  730. throw new NoSuchElementException();
  731. }
  732. public boolean hasPrevious() {
  733. return previousIndex() >= 0;
  734. }
  735. public Object previous() {
  736. if (hasPrevious())
  737. return i.previous();
  738. else
  739. throw new NoSuchElementException();
  740. }
  741. public int nextIndex() {
  742. return i.nextIndex() - offset;
  743. }
  744. public int previousIndex() {
  745. return i.previousIndex() - offset;
  746. }
  747. public void remove() {
  748. i.remove();
  749. expectedModCount = l.modCount;
  750. size--;
  751. modCount++;
  752. }
  753. public void set(Object o) {
  754. i.set(o);
  755. }
  756. public void add(Object o) {
  757. i.add(o);
  758. expectedModCount = l.modCount;
  759. size++;
  760. modCount++;
  761. }
  762. };
  763. }
  764. public List subList(int fromIndex, int toIndex) {
  765. return new SubList(this, fromIndex, toIndex);
  766. }
  767. private void rangeCheck(int index) {
  768. if (index<0 || index>=size)
  769. throw new IndexOutOfBoundsException("Index: "+index+
  770. ",Size: "+size);
  771. }
  772. private void checkForComodification() {
  773. if (l.modCount != expectedModCount)
  774. throw new ConcurrentModificationException();
  775. }
  776. }