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