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