/[classpath]/classpath/java/util/AbstractList.java
ViewVC logotype

Diff of /classpath/java/util/AbstractList.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.14 by bryce, Fri Nov 3 03:59:49 2000 UTC revision 1.15 by ericb, Fri Oct 19 00:17:44 2001 UTC
# Line 1  Line 1 
1  /* AbstractList.java -- Abstract implementation of most of List  /* AbstractList.java -- Abstract implementation of most of List
2     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 25  This exception does not however invalida Line 25  This exception does not however invalida
25  executable file might be covered by the GNU General Public License. */  executable file might be covered by the GNU General Public License. */
26    
27    
 // TO DO:  
 // ~ Doc comments for almost everything.  
 // ~ Better general commenting  
   
28  package java.util;  package java.util;
29    
30  /**  /**
31   * A basic implementation of most of the methods in the List interface to make   * A basic implementation of most of the methods in the List interface to make
32   * it easier to create a List based on a random-access data structure. To   * it easier to create a List based on a random-access data structure. If
33   * create an unmodifiable list, it is only necessary to override the size() and   * the list is sequential (such as a linked list), use AbstractSequentialList.
34   * get(int) methods (this contrasts with all other abstract collection classes   * To create an unmodifiable list, it is only necessary to override the
35   * which require an iterator to be provided). To make the list modifiable, the   * size() and get(int) methods (this contrasts with all other abstract
36   * set(int, Object)  method should also be overridden, and to make the list   * collection classes which require an iterator to be provided). To make the
37   * resizable, the add(int, Object) and remove(int) methods should be overridden   * list modifiable, the set(int, Object) method should also be overridden, and
38   * too. Other methods should be overridden if the backing data structure allows   * to make the list resizable, the add(int, Object) and remove(int) methods
39   * for a more efficient implementation. The precise implementation used by   * should be overridden too. Other methods should be overridden if the
40   * AbstractList is documented, so that subclasses can tell which methods could   * backing data structure allows for a more efficient implementation.
41   * be implemented more efficiently.   * The precise implementation used by AbstractList is documented, so that
42     * subclasses can tell which methods could be implemented more efficiently.
43     * <p>
44     *
45     * As recommended by Collection and List, the subclass should provide at
46     * least a no-argument and a Collection constructor. This class is not
47     * synchronized.
48     *
49     * @author Original author unknown
50     * @author Eric Blake <ebb9@email.byu.edu>
51     * @see Collection
52     * @see List
53     * @see AbstractSequentialList
54     * @see AbstractCollection
55     * @see ListIterator
56     * @since 1.2
57     * @status updated to 1.4
58   */   */
59  public abstract class AbstractList extends AbstractCollection implements List  public abstract class AbstractList extends AbstractCollection implements List
60  {  {
61    /**    /**
62     * A count of the number of structural modifications that have been made to     * A count of the number of structural modifications that have been made to
63     * the list (that is, insertions and removals).     * the list (that is, insertions and removals). Structural modifications
64       * are ones which change the list size or affect how iterations would
65       * behave. This field is available for use by Iterator and ListIterator,
66       * in order to throw a {@link ConcurrentModificationException} in response
67       * to the next operation on the iterator. This <i>fail-fast</i> behavior
68       * saves the user from many subtle bugs otherwise possible from concurrent
69       * modification during iteration.
70       * <p>
71       *
72       * To make lists fail-fast, increment this field by just 1 in the
73       * <code>add(int, Object)</code> and <code>remove(int)</code> methods.
74       * Otherwise, this field may be ignored.
75       */
76      protected int modCount = 0;
77    
78      /**
79       * The main constructor, for use by subclasses.
80     */     */
81    protected transient int modCount = 0;    protected AbstractList()
82      {
83      }
84    
85      /**
86       * Returns the elements at the specified position in the list.
87       *
88       * @param index the element to return
89       * @return the element at that position
90       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
91       */
92    public abstract Object get(int index);    public abstract Object get(int index);
93    
94      /**
95       * Insert an element into the list at a given position (optional operation).
96       * This shifts all existing elements from that position to the end one
97       * index to the right.  This version of add has no return, since it is
98       * assumed to always succeed if there is no exception. This implementation
99       * always throws UnsupportedOperationException, and must be overridden to
100       * make a modifiable List.  If you want fail-fast iterators, be sure to
101       * increment modCount when overriding this.
102       *
103       * @param index the location to insert the item
104       * @param o the object to insert
105       * @throws UnsupportedOperationException if this list does not support the
106       *         add operation
107       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
108       * @throws ClassCastException if o cannot be added to this list due to its
109       *         type
110       * @throws IllegalArgumentException if o cannot be added to this list for
111       *         some other reason
112       * @see #modCount
113       */
114    public void add(int index, Object o)    public void add(int index, Object o)
115    {    {
116      throw new UnsupportedOperationException();      throw new UnsupportedOperationException();
117    }    }
118    
119      /**
120       * Add an element to the end of the list (optional operation). If the list
121       * imposes restraints on what can be inserted, such as no null elements,
122       * this should be documented. This implementation calls
123       * <code>add(size(), o);</code>, and will fail if that version does.
124       *
125       * @param o the object to add
126       * @return true, as defined by Collection for a modified list
127       * @throws UnsupportedOperationException if this list does not support the
128       *         add operation
129       * @throws ClassCastException if o cannot be added to this list due to its
130       *         type
131       * @throws IllegalArgumentException if o cannot be added to this list for
132       *         some other reason
133       * @see #add(int, Object)
134       */
135    public boolean add(Object o)    public boolean add(Object o)
136    {    {
137      add(size(), o);      add(size(), o);
138      return true;      return true;
139    }    }
140    
141      /**
142       * Insert the contents of a collection into the list at a given position
143       * (optional operation). Shift all elements at that position to the right
144       * by the number of elements inserted. This operation is undefined if
145       * this list is modified during the operation (for example, if you try
146       * to insert a list into itself). This implementation uses the iterator of
147       * the collection, repeatedly calling add(int, Object); this will fail
148       * if add does. This can often be made more efficient.
149       *
150       * @param index the location to insert the collection
151       * @param c the collection to insert
152       * @return true if the list was modified by this action, that is, if c is
153       *         non-empty
154       * @throws UnsupportedOperationException if this list does not support the
155       *         addAll operation
156       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
157       * @throws ClassCastException if some element of c cannot be added to this
158       *         list due to its type
159       * @throws IllegalArgumentException if some element of c cannot be added
160       *         to this list for some other reason
161       * @throws NullPointerException if the specified collection is null
162       * @see #add(int, Object)
163       */
164    public boolean addAll(int index, Collection c)    public boolean addAll(int index, Collection c)
165    {    {
166      Iterator itr = c.iterator();      Iterator itr = c.iterator();
167      int size = c.size();      int size = c.size();
168      for (int pos = 0; pos < size; pos++)      for (int pos = size; pos > 0; pos--)
169        {        add(index++, itr.next());
170          add(index++, itr.next());      return size > 0;
       }  
     return (size > 0);  
171    }    }
172    
173      /**
174       * Clear the list, such that a subsequent call to isEmpty() would return
175       * true (optional operation). This implementation calls
176       * <code>removeRange(0, size())</code>, so it will fail unless remove
177       * or removeRange is overridden.
178       *
179       * @throws UnsupportedOperationException if this list does not support the
180       *         clear operation
181       * @see #remove(int)
182       * @see #removeRange(int, int)
183       */
184    public void clear()    public void clear()
185    {    {
186      removeRange(0, size());      removeRange(0, size());
187    }    }
188    
189      /**
190       * Test whether this list is equal to another object. A List is defined to be
191       * equal to an object if and only if that object is also a List, and the two
192       * lists have the same sequence. Two lists l1 and l2 are equal if and only
193       * if <code>l1.size() == l2.size()</code>, and for every integer n between 0
194       * and <code>l1.size() - 1</code> inclusive, <code>l1.get(n) == null ?
195       * l2.get(n) == null : l1.get(n).equals(l2.get(n))</code>.
196       * <p>
197       *
198       * This implementation returns true if the object is this, or false if the
199       * object is not a List.  Otherwise, it iterates over both lists (with
200       * iterator()), returning false if two elements compare false or one list
201       * is shorter, and true if the iteration completes successfully.
202       *
203       * @param o the object to test for equality with this list
204       * @return true if o is equal to this list
205       * @see Object#equals(Object)
206       * @see #hashCode()
207       */
208    public boolean equals(Object o)    public boolean equals(Object o)
209    {    {
210      if (o == this)      if (o == this)
# Line 94  public abstract class AbstractList exten Line 218  public abstract class AbstractList exten
218      Iterator itr1 = iterator();      Iterator itr1 = iterator();
219      Iterator itr2 = ((List) o).iterator();      Iterator itr2 = ((List) o).iterator();
220    
221      for (int pos = 0; pos < size; pos++)      while (--size >= 0)
222        {        if (! equals(itr1.next(), itr2.next()))
223          Object e = itr1.next();          return false;
         if (e == null ? itr2.next() != null : !e.equals(itr2.next()))  
           return false;  
       }  
224      return true;      return true;
225    }    }
226    
227      /**
228       * Obtain a hash code for this list. In order to obey the general contract of
229       * the hashCode method of class Object, this value is calculated as follows:
230       * <pre>
231       *   hashCode = 1;
232       *   Iterator i = list.iterator();
233       *   while (i.hasNext())
234       *     {
235       *       Object obj = i.next();
236       *       hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
237       *     }
238       * </pre>
239       * This ensures that the general contract of Object.hashCode() is adhered to.
240       *
241       * @return the hash code of this list
242       * @see Object#hashCode()
243       * @see #equals(Object)
244       */
245    public int hashCode()    public int hashCode()
246    {    {
247      int hashCode = 1;      int hashCode = 1;
248      Iterator itr = iterator();      Iterator itr = iterator();
249      int size = size();      int pos = size();
250      for (int pos = 0; pos < size; pos++)      while (--pos >= 0)
251        {        hashCode = 31 * hashCode + hashCode(itr.next());
         Object obj = itr.next();  
         hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());  
       }  
252      return hashCode;      return hashCode;
253    }    }
254    
255      /**
256       * Obtain the first index at which a given object is to be found in this
257       * list. This implementation follows a listIterator() until a match is found,
258       * or returns -1 if the list end is reached.
259       *
260       * @param o the object to search for
261       * @return the least integer n such that <code>o == null ? get(n) == null :
262       *         o.equals(get(n))</code>, or -1 if there is no such index
263       */
264    public int indexOf(Object o)    public int indexOf(Object o)
265    {    {
266      ListIterator itr = listIterator(0);      ListIterator itr = listIterator();
267      int size = size();      int size = size();
268      for (int pos = 0; pos < size; pos++)      for (int pos = 0; pos < size; pos++)
269        {        if (equals(o, itr.next()))
270          if (o == null ? itr.next() == null : o.equals(itr.next()))          return pos;
           return pos;  
       }  
271      return -1;      return -1;
272    }    }
273    
274      /**
275       * Obtain an Iterator over this list, whose sequence is the list order.
276       * This implementation uses size(), get(int), and remove(int) of the
277       * backing list, and does not support remove unless the list does. This
278       * implementation is fail-fast if you correctly maintain modCount.
279       * Also, this implementation is specified by Sun to be distinct from
280       * listIterator, although you could easily implement it as
281       * <code>return listIterator(0)</code>.
282       *
283       * @return an Iterator over the elements of this list, in order
284       * @see #modCount
285       */
286    public Iterator iterator()    public Iterator iterator()
287    {    {
288      return new AbstractListItr(0);      // Bah, Sun's implementation forbids using listIterator(0).
289        return new Iterator()
290        {
291          private int pos = 0;
292          private int size = size();
293          private int last = -1;
294          private int knownMod = modCount;
295    
296          // This will get inlined, since it is private.
297          private void checkMod()
298          {
299            if (knownMod != modCount)
300              throw new ConcurrentModificationException();
301          }
302    
303          public boolean hasNext()
304          {
305            checkMod();
306            return pos < size;
307          }
308    
309          public Object next()
310          {
311            checkMod();
312            if (pos == size)
313              throw new NoSuchElementException();
314            last = pos++;
315            return get(pos);
316          }
317    
318          public void remove()
319          {
320            checkMod();
321            if (last < 0)
322              throw new IllegalStateException();
323            AbstractList.this.remove(last);
324            pos--;
325            size--;
326            knownMod = modCount;
327            last = -1;
328          }
329        };
330    }    }
331    
332      /**
333       * Obtain the last index at which a given object is to be found in this
334       * list. This implementation grabs listIterator(size()), then searches
335       * backwards for a match or returns -1.
336       *
337       * @return the greatest integer n such that <code>o == null ? get(n) == null
338       *         : o.equals(get(n))</code>, or -1 if there is no such index
339       */
340    public int lastIndexOf(Object o)    public int lastIndexOf(Object o)
341    {    {
342      int size = size();      int pos = size();
343      ListIterator itr = listIterator(size);      ListIterator itr = listIterator(pos);
344      for (int pos = size; pos > 0; pos--)      while (--pos >= 0)
345        {        if (equals(o, itr.previous()))
346          if (o == null ? itr.previous() == null : o.equals(itr.previous()))          return pos;
           return pos - 1;  
       }  
347      return -1;      return -1;
348    }    }
349    
350    /**    /**
351     * Return an Iterator over this List. This implementation calls     * Obtain a ListIterator over this list, starting at the beginning. This
352     * listIterator(0).     * implementation returns listIterator(0).
353     *     *
354     * @return an Iterator over this List     * @return a ListIterator over the elements of this list, in order, starting
355       *         at the beginning
356     */     */
357    public ListIterator listIterator()    public ListIterator listIterator()
358    {    {
359      return listIterator(0);      return listIterator(0);
360    }    }
361    
362    public ListIterator listIterator(int index)    /**
363       * Obtain a ListIterator over this list, starting at a given position.
364       * A first call to next() would return the same as get(index), and a
365       * first call to previous() would return the same as get(index - 1).
366       * <p>
367       *
368       * This implementation uses size(), get(int), set(int, Object),
369       * add(int, Object), and remove(int) of the backing list, and does not
370       * support remove, set, or add unless the list does. This implementation
371       * is fail-fast if you correctly maintain modCount.
372       *
373       * @param index the position, between 0 and size() inclusive, to begin the
374       *        iteration from
375       * @return a ListIterator over the elements of this list, in order, starting
376       *         at index
377       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
378       * @see #modCount
379       */
380      public ListIterator listIterator(final int index)
381    {    {
382      if (index < 0 || index > size())      if (index < 0 || index > size())
383        throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +        throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
384                                            size());                                            + size());
385    
386        return new ListIterator()
387        {
388          private int knownMod = modCount;
389          private int position = index;
390          private int lastReturned = -1;
391          private int size = size();
392    
393          // This will get inlined, since it is private.
394          private void checkMod()
395          {
396            if (knownMod != modCount)
397              throw new ConcurrentModificationException();
398          }
399    
400          public boolean hasNext()
401          {
402            checkMod();
403            return position < size;
404          }
405    
406          public boolean hasPrevious()
407          {
408            checkMod();
409            return position > 0;
410          }
411    
412          public Object next()
413          {
414            checkMod();
415            if (position == size)
416              throw new NoSuchElementException();
417            lastReturned = position++;
418            return get(lastReturned);
419          }
420    
421          public Object previous()
422          {
423            checkMod();
424            if (position == 0)
425              throw new NoSuchElementException();
426            lastReturned = --position;
427            return get(lastReturned);
428          }
429    
430          public int nextIndex()
431          {
432            checkMod();
433            return position;
434          }
435    
436      return new AbstractListItr(index);        public int previousIndex()
437          {
438            checkMod();
439            return position - 1;
440          }
441    
442          public void remove()
443          {
444            checkMod();
445            if (lastReturned < 0)
446              throw new IllegalStateException();
447            AbstractList.this.remove(lastReturned);
448            size--;
449            knownMod = modCount;
450            position = lastReturned;
451            lastReturned = -1;
452          }
453    
454          public void set(Object o)
455          {
456            checkMod();
457            if (lastReturned < 0)
458              throw new IllegalStateException();
459            AbstractList.this.set(lastReturned, o);
460          }
461    
462          public void add(Object o)
463          {
464            checkMod();
465            AbstractList.this.add(position++, o);
466            size++;
467            lastReturned = -1;
468            knownMod = modCount;
469          }
470        };
471    }    }
472    
473      /**
474       * Remove the element at a given position in this list (optional operation).
475       * Shifts all remaining elements to the left to fill the gap. This
476       * implementation always throws an UnsupportedOperationException.
477       * If you want fail-fast iterators, be sure to increment modCount when
478       * overriding this.
479       *
480       * @param index the position within the list of the object to remove
481       * @return the object that was removed
482       * @throws UnsupportedOperationException if this list does not support the
483       *         remove operation
484       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
485       * @see #modCount
486       */
487    public Object remove(int index)    public Object remove(int index)
488    {    {
489      throw new UnsupportedOperationException();      throw new UnsupportedOperationException();
# Line 175  public abstract class AbstractList exten Line 494  public abstract class AbstractList exten
494     * removeRange methods of the class which implements subList, which are     * removeRange methods of the class which implements subList, which are
495     * difficult for subclasses to override directly. Therefore, this method     * difficult for subclasses to override directly. Therefore, this method
496     * should be overridden instead by the more efficient implementation, if one     * should be overridden instead by the more efficient implementation, if one
497     * exists.     * exists. Overriding this can reduce quadratic efforts to constant time
498       * in some cases!
499     * <p>     * <p>
500       *
501     * This implementation first checks for illegal or out of range arguments. It     * This implementation first checks for illegal or out of range arguments. It
502     * then obtains a ListIterator over the list using listIterator(fromIndex).     * then obtains a ListIterator over the list using listIterator(fromIndex).
503     * It then calls next() and remove() on this iterator repeatedly, toIndex -     * It then calls next() and remove() on this iterator repeatedly, toIndex -
# Line 190  public abstract class AbstractList exten Line 511  public abstract class AbstractList exten
511      ListIterator itr = listIterator(fromIndex);      ListIterator itr = listIterator(fromIndex);
512      for (int index = fromIndex; index < toIndex; index++)      for (int index = fromIndex; index < toIndex; index++)
513        {        {
514          itr.next();          itr.next();
515          itr.remove();          itr.remove();
516        }        }
517    }    }
518    
519      /**
520       * Replace an element of this list with another object (optional operation).
521       * This implementation always throws an UnsupportedOperationException.
522       *
523       * @param index the position within this list of the element to be replaced
524       * @param o the object to replace it with
525       * @return the object that was replaced
526       * @throws UnsupportedOperationException if this list does not support the
527       *         set operation
528       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
529       * @throws ClassCastException if o cannot be added to this list due to its
530       *         type
531       * @throws IllegalArgumentException if o cannot be added to this list for
532       *         some other reason
533       */
534    public Object set(int index, Object o)    public Object set(int index, Object o)
535    {    {
536      throw new UnsupportedOperationException();      throw new UnsupportedOperationException();
537    }    }
538    
539      /**
540       * Obtain a List view of a subsection of this list, from fromIndex
541       * (inclusive) to toIndex (exclusive). If the two indices are equal, the
542       * sublist is empty. The returned list should be modifiable if and only
543       * if this list is modifiable. Changes to the returned list should be
544       * reflected in this list. If this list is structurally modified in
545       * any way other than through the returned list, the result of any subsequent
546       * operations on the returned list is undefined.
547       * <p>
548       *
549       * This implementation returns a subclass of AbstractList. It stores, in
550       * private fields, the offset and size of the sublist, and the expected
551       * modCount of the backing list. If the backing list implements RandomAccess,
552       * the sublist will also.
553       * <p>
554       *
555       * The subclass's <code>set(int, Object)</code>, <code>get(int)</code>,
556       * <code>add(int, Object)</code>, <code>remove(int)</code>,
557       * <code>addAll(int, Collection)</code> and
558       * <code>removeRange(int, int)</code> methods all delegate to the
559       * corresponding methods on the backing abstract list, after
560       * bounds-checking the index and adjusting for the offset. The
561       * <code>addAll(Collection c)</code> method merely returns addAll(size, c).
562       * The <code>listIterator(int)</code> method returns a "wrapper object"
563       * over a list iterator on the backing list, which is created with the
564       * corresponding method on the backing list. The <code>iterator()</code>
565       * method merely returns listIterator(), and the <code>size()</code> method
566       * merely returns the subclass's size field.
567       * <p>
568       *
569       * All methods first check to see if the actual modCount of the backing
570       * list is equal to its expected value, and throw a
571       * ConcurrentModificationException if it is not.
572       *
573       * @param fromIndex the index that the returned list should start from
574       *        (inclusive)
575       * @param toIndex the index that the returned list should go to (exclusive)
576       * @return a List backed by a subsection of this list
577       * @throws IndexOutOfBoundsException if fromIndex &lt; 0
578       *         || toIndex &gt; size()
579       * @throws IllegalArgumentException if fromIndex &gt; toIndex
580       * @see ConcurrentModificationException
581       * @see RandomAccess
582       */
583    public List subList(int fromIndex, int toIndex)    public List subList(int fromIndex, int toIndex)
584    {    {
585        // This follows the specification of AbstractList, but is inconsistent
586        // with the one in List. Don't you love Sun's inconsistencies?
587      if (fromIndex > toIndex)      if (fromIndex > toIndex)
588        throw new IllegalArgumentException(fromIndex + " > " + toIndex);        throw new IllegalArgumentException(fromIndex + " > " + toIndex);
589      if (fromIndex < 0 || toIndex > size())      if (fromIndex < 0 || toIndex > size())
590        throw new IndexOutOfBoundsException();        throw new IndexOutOfBoundsException();
591    
592        if (this instanceof RandomAccess)
593          return new RandomAccessSubList(this, fromIndex, toIndex);
594      return new SubList(this, fromIndex, toIndex);      return new SubList(this, fromIndex, toIndex);
595    }    }
596    
597    class AbstractListItr implements ListIterator  } // class AbstractList
   {  
     private int knownMod = modCount;  
     private int position;  
     private int lastReturned = -1;  
     private int size = size();  
   
     AbstractListItr(int start_pos)  
     {  
       this.position = start_pos;  
     }  
   
     private void checkMod()  
     {  
       if (knownMod != modCount)  
         throw new ConcurrentModificationException();  
     }  
   
     public boolean hasNext()  
     {  
       checkMod();  
       return position < size;  
     }  
   
     public boolean hasPrevious()  
     {  
       checkMod();  
       return position > 0;  
     }  
   
     public Object next()  
     {  
       checkMod();  
       if (position < size)  
         {  
           lastReturned = position++;  
           return get(lastReturned);  
         }  
       else  
         {  
           throw new NoSuchElementException();  
         }  
     }  
   
     public Object previous()  
     {  
       checkMod();  
       if (position > 0)  
         {  
           lastReturned = --position;  
           return get(lastReturned);  
         }  
       else  
         {  
           throw new NoSuchElementException();  
         }  
     }  
   
     public int nextIndex()  
     {  
       checkMod();  
       return position;  
     }  
   
     public int previousIndex()  
     {  
       checkMod();  
       return position - 1;  
     }  
   
     public void remove()  
     {  
       checkMod();  
       if (lastReturned < 0)  
         {  
           throw new IllegalStateException();  
         }  
       AbstractList.this.remove(lastReturned);  
       knownMod++;  
       position = lastReturned;  
       lastReturned = -1;  
     }  
   
     public void set(Object o)  
     {  
       checkMod();  
       if (lastReturned < 0)  
         throw new IllegalStateException();  
       AbstractList.this.set(lastReturned, o);  
     }  
   
     public void add(Object o)  
     {  
       checkMod();  
       AbstractList.this.add(position++, o);  
       lastReturned = -1;  
       knownMod++;  
     }  
   }                             // AbstractList.Iterator  
 }  
   
598    
599    
600    /**
601     * This class follows the implementation requirements set forth in
602     * {@link AbstractList#subList(int, int)}. Some compilers have problems
603     * with AbstractList.this.modCount if this class is nested in AbstractList,
604     * even though the JLS defines that to be legal, so we make it a top-level
605     * class.
606     *
607     * @author Original author unknown
608     * @author Eric Blake <ebb9@email.byu.edu>
609     */
610  class SubList extends AbstractList  class SubList extends AbstractList
611  {  {
612    private AbstractList backingList;    private AbstractList backingList;
613    private int offset;    private int offset;
614    private int size;    private int size;
615    
616    public SubList(AbstractList backing, int fromIndex, int toIndex)    /**
617       * Construct the sublist.
618       *
619       * @param backing the list this comes from
620       * @param fromIndex the lower bound, inclusive
621       * @param toIndex the upper bound, exclusive
622       */
623      SubList(AbstractList backing, int fromIndex, int toIndex)
624    {    {
625      backingList = backing;      backingList = backing;
626      modCount = backingList.modCount;      modCount = backingList.modCount;
# Line 329  class SubList extends AbstractList Line 630  class SubList extends AbstractList
630    
631    /**    /**
632     * This method checks the two modCount fields to ensure that there has     * This method checks the two modCount fields to ensure that there has
633     * not been a concurrent modification. It throws an exception if there     * not been a concurrent modification, returning if all is okay.
    * has been, and otherwise returns normally.  
    * Note that since this method is private, it will be inlined.  
634     *     *
635     * @exception ConcurrentModificationException if there has been a     * @throws ConcurrentModificationException if the backing list has been
636     *   concurrent modification.     *         modified externally to this sublist
637     */     */
638      // This will get inlined, since it is private.
639    private void checkMod()    private void checkMod()
640    {    {
641      if (modCount != backingList.modCount)      if (modCount != backingList.modCount)
# Line 345  class SubList extends AbstractList Line 645  class SubList extends AbstractList
645    /**    /**
646     * This method checks that a value is between 0 and size (inclusive). If     * This method checks that a value is between 0 and size (inclusive). If
647     * it is not, an exception is thrown.     * it is not, an exception is thrown.
    * Note that since this method is private, it will be inlined.  
648     *     *
649     * @exception IndexOutOfBoundsException if the value is out of range.     * @param index the value to check
650       * @throws IndexOutOfBoundsException if the value is out of range
651     */     */
652      // This will get inlined, since it is private.
653    private void checkBoundsInclusive(int index)    private void checkBoundsInclusive(int index)
654    {    {
655      if (index < 0 || index > size)      if (index < 0 || index > size)
656        throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +        throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
657                                            size);                                            + size);
658    }    }
659    
660    /**    /**
661     * This method checks that a value is between 0 (inclusive) and size     * This method checks that a value is between 0 (inclusive) and size
662     * (exclusive). If it is not, an exception is thrown.     * (exclusive). If it is not, an exception is thrown.
    * Note that since this method is private, it will be inlined.  
663     *     *
664     * @exception IndexOutOfBoundsException if the value is out of range.     * @param index the value to check
665       * @throws IndexOutOfBoundsException if the value is out of range
666     */     */
667      // This will get inlined, since it is private.
668    private void checkBoundsExclusive(int index)    private void checkBoundsExclusive(int index)
669    {    {
670      if (index < 0 || index >= size)      if (index < 0 || index >= size)
671        throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +        throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
672                                            size);                                            + size);
673    }    }
674    
675      /**
676       * Specified by AbstractList.subList to return the private field size.
677       *
678       * @return the sublist size
679       */
680    public int size()    public int size()
681    {    {
682      checkMod();      checkMod();
683      return size;      return size;
684    }    }
685    
686      /**
687       * Specified by AbstractList.subList to delegate to the backing list.
688       *
689       * @param index the location to modify
690       * @param o the new value
691       * @return the old value
692       */
693    public Object set(int index, Object o)    public Object set(int index, Object o)
694    {    {
695      checkMod();      checkMod();
696      checkBoundsExclusive(index);      checkBoundsExclusive(index);
697      o = backingList.set(index + offset, o);      return backingList.set(index + offset, o);
     return o;  
698    }    }
699    
700      /**
701       * Specified by AbstractList.subList to delegate to the backing list.
702       *
703       * @param index the location to get from
704       * @return the object at that location
705       */
706    public Object get(int index)    public Object get(int index)
707    {    {
708      checkMod();      checkMod();
# Line 391  class SubList extends AbstractList Line 710  class SubList extends AbstractList
710      return backingList.get(index + offset);      return backingList.get(index + offset);
711    }    }
712    
713      /**
714       * Specified by AbstractList.subList to delegate to the backing list.
715       *
716       * @param index the index to insert at
717       * @param o the object to add
718       */
719    public void add(int index, Object o)    public void add(int index, Object o)
720    {    {
721      checkMod();      checkMod();
722      checkBoundsInclusive(index);      checkBoundsInclusive(index);
723      backingList.add(index + offset, o);      backingList.add(index + offset, o);
724      this.modCount++;      modCount = backingList.modCount;
725      size++;      size++;
726    }    }
727    
728      /**
729       * Specified by AbstractList.subList to delegate to the backing list.
730       *
731       * @param index the index to remove
732       * @return the removed object
733       */
734    public Object remove(int index)    public Object remove(int index)
735    {    {
736      checkMod();      checkMod();
737      checkBoundsExclusive(index);      checkBoundsExclusive(index);
738      Object o = backingList.remove(index + offset);      Object o = backingList.remove(index + offset);
739      this.modCount++;      modCount = backingList.modCount;
740      size--;      size--;
741      return o;      return o;
742    }    }
743    
744    public void removeRange(int fromIndex, int toIndex)    /**
745       * Specified by AbstractList.subList to delegate to the backing list.
746       * This does no bounds checking, as it assumes it will only be called
747       * by trusted code like clear() which has already checked the bounds.
748       *
749       * @param fromIndex the lower bound, inclusive
750       * @param toIndex the upper bound, exclusive
751       */
752      protected void removeRange(int fromIndex, int toIndex)
753    {    {
754      checkMod();      checkMod();
     checkBoundsExclusive(fromIndex);  
     checkBoundsInclusive(toIndex);  
755    
     // this call will catch the toIndex < fromIndex condition  
756      backingList.removeRange(offset + fromIndex, offset + toIndex);      backingList.removeRange(offset + fromIndex, offset + toIndex);
757      this.modCount = backingList.modCount;      modCount = backingList.modCount;
758      size -= toIndex - fromIndex;      size -= toIndex - fromIndex;
759    }    }
760    
761      /**
762       * Specified by AbstractList.subList to delegate to the backing list.
763       *
764       * @param index the location to insert at
765       * @param c the collection to insert
766       * @return true if this list was modified, in other words, c is non-empty
767       */
768    public boolean addAll(int index, Collection c)    public boolean addAll(int index, Collection c)
769    {    {
770      checkMod();      checkMod();
771      checkBoundsInclusive(index);      checkBoundsInclusive(index);
772      int csize = c.size();      int csize = c.size();
773      boolean result = backingList.addAll(offset + index, c);      boolean result = backingList.addAll(offset + index, c);
774      this.modCount = backingList.modCount;      modCount = backingList.modCount;
775      size += csize;      size += csize;
776      return result;      return result;
777    }    }
778    
779      /**
780       * Specified by AbstractList.subList to return addAll(size, c).
781       *
782       * @param c the collection to insert
783       * @return true if this list was modified, in other words, c is non-empty
784       */
785      public boolean addAll(Collection c)
786      {
787        return addAll(size, c);
788      }
789    
790      /**
791       * Specified by AbstractList.subList to return listIterator().
792       *
793       * @return an iterator over the sublist
794       */
795    public Iterator iterator()    public Iterator iterator()
796    {    {
797      return listIterator(0);      return listIterator();
798    }    }
799    
800      /**
801       * Specified by AbstractList.subList to return a wrapper around the
802       * backing list's iterator.
803       *
804       * @param index the start location of the iterator
805       * @return a list iterator over the sublist
806       */
807    public ListIterator listIterator(final int index)    public ListIterator listIterator(final int index)
808    {          {
809      checkMod();      checkMod();
810      checkBoundsInclusive(index);      checkBoundsInclusive(index);
811    
812      return new ListIterator()      return new ListIterator()
813      {      {
814        ListIterator i = backingList.listIterator(index + offset);        ListIterator i = backingList.listIterator(index + offset);
815        int position = index;        int position = index;
# Line 462  class SubList extends AbstractList Line 828  class SubList extends AbstractList
828    
829        public Object next()        public Object next()
830        {        {
831          if (position < size)          if (position == size)
           {  
             Object o = i.next();  
             position++;  
             return o;  
           }  
         else  
832            throw new NoSuchElementException();            throw new NoSuchElementException();
833            position++;
834            return i.next();
835        }        }
836    
837        public Object previous()        public Object previous()
838        {        {
839          if (position > 0)          if (position == 0)
           {  
             Object o = i.previous();  
             position--;  
             return o;  
           }  
         else  
840            throw new NoSuchElementException();            throw new NoSuchElementException();
841            position--;
842            return i.previous();
843        }        }
844    
845        public int nextIndex()        public int nextIndex()
846        {        {
847          return offset + i.nextIndex();          return i.nextIndex() - offset;
848        }        }
849    
850        public int previousIndex()        public int previousIndex()
851        {        {
852          return offset + i.previousIndex();          return i.previousIndex() - offset;
853        }        }
854    
855        public void remove()        public void remove()
856        {        {
857          i.remove();          i.remove();
858          modCount++;          modCount = backingList.modCount;
859          size--;          size--;
860          position = nextIndex();          position = nextIndex();
861        }        }
# Line 510  class SubList extends AbstractList Line 868  class SubList extends AbstractList
868        public void add(Object o)        public void add(Object o)
869        {        {
870          i.add(o);          i.add(o);
871          modCount++;          modCount = backingList.modCount;
872          size++;          size++;
873          position++;          position++;
874        }        }
875    
876        // Here is the reason why the various modCount fields are mostly        // Here is the reason why the various modCount fields are mostly
877        // ignored in this wrapper listIterator.        // ignored in this wrapper listIterator.
878        // IF the backing listIterator is failfast, then the following holds:        // If the backing listIterator is failfast, then the following holds:
879        //   Using any other method on this list will call a corresponding        //   Using any other method on this list will call a corresponding
880        //   method on the backing list *after* the backing listIterator        //   method on the backing list *after* the backing listIterator
881        //   is created, which will in turn cause a ConcurrentModException        //   is created, which will in turn cause a ConcurrentModException
# Line 530  class SubList extends AbstractList Line 888  class SubList extends AbstractList
888        //   only, but somewhat pointless when the list can be changed under        //   only, but somewhat pointless when the list can be changed under
889        //   us.        //   us.
890        // Either way, no explicit handling of modCount is needed.        // Either way, no explicit handling of modCount is needed.
891        // However modCount++ must be executed in add and remove, and size        // However modCount = backingList.modCount must be executed in add
892        // must also be updated in these two methods, since they do not go        // and remove, and size must also be updated in these two methods,
893        // through the corresponding methods of the subList.        // since they do not go through the corresponding methods of the subList.
894      };      };
895    }    }
896  }  // SubList  } // class SubList
897    
898    /**
899     * This class is a RandomAccess version of SubList, as required by
900     * {@link AbstractList#subList(int, int)}.
901     *
902     * @author Eric Blake <ebb9@email.byu.edu>
903     */
904    final class RandomAccessSubList extends SubList
905      implements RandomAccess
906    {
907      /**
908       * Construct the sublist.
909       *
910       * @param backing the list this comes from
911       * @param fromIndex the lower bound, inclusive
912       * @param toIndex the upper bound, exclusive
913       */
914      RandomAccessSubList(AbstractList backing, int fromIndex, int toIndex)
915      {
916        super(backing, fromIndex, toIndex);
917      }
918    } // class RandomAccessSubList

Legend:
Removed from v.1.14  
changed lines
  Added in v.1.15

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26