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

Diff of /classpath/java/util/LinkedList.java

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

revision 1.13 by bryce, Tue Jul 17 01:49:54 2001 UTC revision 1.14 by ericb, Mon Oct 22 03:46:07 2001 UTC
# Line 1  Line 1 
1  /* LinkedList.java -- Linked list implementation of the List interface  /* LinkedList.java -- Linked list implementation of the List interface
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 32  import java.io.ObjectInputStream; Line 32  import java.io.ObjectInputStream;
32  import java.io.IOException;  import java.io.IOException;
33  import java.lang.reflect.Array;  import java.lang.reflect.Array;
34    
 // TO DO:  
 // ~ Doc comment for the class.  
 // ~ Doc comments for the non-list methods.  
 // ~ other general implementation notes.  
   
35  /**  /**
36   * Linked list implementation of the List interface.   * Linked list implementation of the List interface. In addition to the
37     * methods of the List interface, this class provides access to the first
38     * and last list elements in O(1) time for easy stack, queue, or double-ended
39     * queue (deque) creation. The list is doubly-linked, with traversal to a
40     * given index starting from the end closest to the element.<p>
41     *
42     * LinkedList is not synchronized, so if you need multi-threaded access,
43     * consider using:<br>
44     * <code>List l = Collections.synchronizedList(new LinkedList(...));</code>
45     * <p>
46     *
47     * The iterators are <i>fail-fast</i>, meaning that any structural
48     * modification, except for <code>remove()</code> called on the iterator
49     * itself, cause the iterator to throw a
50     * {@link ConcurrentModificationException} rather than exhibit
51     * non-deterministic behavior.
52     *
53     * @author Original author unknown
54     * @author Eric Blake <ebb9@email.byu.edu>
55     * @see List
56     * @see ArrayList
57     * @see Vector
58     * @see Collections#synchronizedList(List)
59     * @since 1.2
60     * @status missing javadoc, but complete to 1.4
61   */   */
62  public class LinkedList extends AbstractSequentialList  public class LinkedList extends AbstractSequentialList
63    implements List, Cloneable, Serializable    implements List, Cloneable, Serializable
64  {  {
65    static final long serialVersionUID = 876323262645176354L;    /**
66       * Compatible with JDK 1.2.
67       */
68      private static final long serialVersionUID = 876323262645176354L;
69    
70    /**    /**
71     * An Entry containing the head (in the next field) and the tail (in the     * The first element in the list.
    * previous field) of the list. The data field is null. If the list is empty,  
    * both the head and the tail point to ends itself.  
72     */     */
73    transient Entry first;    transient Entry first;
74    
75      /**
76       * The last element in the list.
77       */
78    transient Entry last;    transient Entry last;
79    
80    /**    /**
# Line 61  public class LinkedList extends Abstract Line 85  public class LinkedList extends Abstract
85    /**    /**
86     * Class to represent an entry in the list. Holds a single element.     * Class to represent an entry in the list. Holds a single element.
87     */     */
88    private static class Entry    private static final class Entry
89    {    {
90        /** The element in the list. */
91      Object data;      Object data;
92    
93        /** The next list entry, null if this is last. */
94      Entry next;      Entry next;
95    
96        /** The previous list entry, null if this is first. */
97      Entry previous;      Entry previous;
98        
99        /**
100         * Construct an entry.
101         * @param data the list element
102         */
103      Entry(Object data)      Entry(Object data)
104      {      {
105        this.data = data;        this.data = data;
106      }      }
107    }    } // class Entry
108      
109    /**    /**
110     * Obtain the Entry at a given position in a list. This method of course     * Obtain the Entry at a given position in a list. This method of course
111     * takes linear time, but it is intelligent enough to take the shorter of the     * takes linear time, but it is intelligent enough to take the shorter of the
# Line 82  public class LinkedList extends Abstract Line 115  public class LinkedList extends Abstract
115     * For speed and flexibility, range checking is not done in this method:     * For speed and flexibility, range checking is not done in this method:
116     * Incorrect values will be returned if (n < 0) or (n >= size).     * Incorrect values will be returned if (n < 0) or (n >= size).
117     *     *
118     * @param n the number of the entry to get.     * @param n the number of the entry to get
119       * @return the entry at position n
120     */     */
121    private Entry getEntry(int n)    private Entry getEntry(int n)
122    {    {
# Line 90  public class LinkedList extends Abstract Line 124  public class LinkedList extends Abstract
124      if (n < size / 2)      if (n < size / 2)
125        {        {
126          e = first;          e = first;
127          // n less than size/2, iterate from start          // n less than size/2, iterate from start
128          while (n-- > 0)          while (n-- > 0)
129            {            e = e.next;
             e = e.next;  
           }  
130        }        }
131      else      else
132        {        {
133          e = last;                e = last;
134          // n greater than size/2, iterate from end          // n greater than size/2, iterate from end
135          while (++n < size)          while (++n < size)
136            {            e = e.previous;
             e = e.previous;  
           }  
137        }        }
138      return e;      return e;
139    }    }
140      
141    /** Remove an entry from the list. This will adjust size and deal with    /**
142     *  `first' and  `last' appropriatly. It does not effect modCount, that is     * Remove an entry from the list. This will adjust size and deal with
143     *  the responsibility of the caller. */     *  `first' and  `last' appropriatly.
144       *
145       * @param e the entry to remove
146       */
147    private void removeEntry(Entry e)    private void removeEntry(Entry e)
148    {    {
149      if (size == 1)      modCount++;
150        size--;
151        if (size == 0)
152        first = last = null;        first = last = null;
153      else      else
154        {        {
155          if (e == first)          if (e == first)
156            {            {
157              first = e.next;              first = e.next;
158              e.next.previous = null;              e.next.previous = null;
159            }            }
160          else if (e == last)          else if (e == last)
161            {            {
162              last = e.previous;              last = e.previous;
163              e.previous.next = null;              e.previous.next = null;
164            }            }
165          else          else
166            {            {
167              e.next.previous = e.previous;                    e.next.previous = e.previous;
168              e.previous.next = e.next;              e.previous.next = e.next;
169            }            }
170        }        }
171      size--;    }
172    
173      /**
174       * Checks that the index is in the range of possible elements (inclusive).
175       *
176       * @param index the index to check
177       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size
178       */
179      private void rangeInclusive(int index)
180      {
181        if (index < 0 || index > size)
182          throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
183                                              + size);
184      }
185    
186      /**
187       * Checks that the index is in the range of existing elements (exclusive).
188       *
189       * @param index the index to check
190       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size
191       */
192      private void rangeExclusive(int index)
193      {
194        if (index < 0 || index >= size)
195          throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
196                                              + size);
197    }    }
198    
199    /**    /**
# Line 141  public class LinkedList extends Abstract Line 201  public class LinkedList extends Abstract
201     */     */
202    public LinkedList()    public LinkedList()
203    {    {
     super();  
204    }    }
205    
206    /**    /**
207     * Create a linked list containing the elements, in order, of a given     * Create a linked list containing the elements, in order, of a given
208     * collection.     * collection.
209     *     *
210     * @param c the collection to populate this list from.     * @param c the collection to populate this list from
211       * @throws NullPointerException if c is null
212     */     */
213    public LinkedList(Collection c)    public LinkedList(Collection c)
214    {    {
     super();  
     // Note: addAll could be made slightly faster, but not enough so to justify  
     // re-implementing it from scratch. It is just a matter of a relatively  
     // small constant factor.  
215      addAll(c);      addAll(c);
216    }    }
217    
218      /**
219       * Returns the first element in the list.
220       *
221       * @return the first list element
222       * @throws NoSuchElementException if the list is empty
223       */
224    public Object getFirst()    public Object getFirst()
225    {    {
226      if (size == 0)      if (size == 0)
# Line 166  public class LinkedList extends Abstract Line 228  public class LinkedList extends Abstract
228      return first.data;      return first.data;
229    }    }
230    
231      /**
232       * Returns the last element in the list.
233       *
234       * @return the last list element
235       * @throws NoSuchElementException if the list is empty
236       */
237    public Object getLast()    public Object getLast()
238    {    {
239      if (size == 0)      if (size == 0)
# Line 173  public class LinkedList extends Abstract Line 241  public class LinkedList extends Abstract
241      return last.data;      return last.data;
242    }    }
243    
244      /**
245       * Remove and return the first element in the list.
246       *
247       * @return the former first element in the list
248       * @throws NoSuchElementException if the list is empty
249       */
250    public Object removeFirst()    public Object removeFirst()
251    {    {
252      if (size == 0)      if (size == 0)
253        throw new NoSuchElementException();        throw new NoSuchElementException();
     size--;  
254      modCount++;      modCount++;
255        size--;
256      Object r = first.data;      Object r = first.data;
257        
258      if (first.next != null)      if (first.next != null)
259        first.next.previous = null;        first.next.previous = null;
260      else      else
261        last = null;        last = null;
262    
263      first = first.next;      first = first.next;
264        
265      return r;      return r;
266    }    }
267    
268      /**
269       * Remove and return the last element in the list.
270       *
271       * @return the former last element in the list
272       * @throws NoSuchElementException if the list is empty
273       */
274    public Object removeLast()    public Object removeLast()
275    {    {
276      if (size == 0)      if (size == 0)
277        throw new NoSuchElementException();        throw new NoSuchElementException();
     size--;  
278      modCount++;      modCount++;
279        size--;
280      Object r = last.data;      Object r = last.data;
281        
282      if (last.previous != null)      if (last.previous != null)
283        last.previous.next = null;        last.previous.next = null;
284      else      else
285        first = null;        first = null;
286        
287      last = last.previous;      last = last.previous;
288        
289      return r;      return r;
290    }    }
291    
292      /**
293       * Insert an element at the first of the list.
294       *
295       * @param o the element to insert
296       */
297    public void addFirst(Object o)    public void addFirst(Object o)
298    {    {
     modCount++;  
299      Entry e = new Entry(o);      Entry e = new Entry(o);
300        
301      if (size == 0)      modCount++;
302        size++;
303        if (size == 1)
304        first = last = e;        first = last = e;
305      else      else
306        {        {
307          e.next = first;          e.next = first;
308          first.previous = e;          first.previous = e;
309          first = e;          first = e;
310        }            }
     size++;  
311    }    }
312    
313      /**
314       * Insert an element at the last of the list.
315       *
316       * @param o the element to insert
317       */
318    public void addLast(Object o)    public void addLast(Object o)
319    {    {
     modCount++;  
320      addLastEntry(new Entry(o));      addLastEntry(new Entry(o));
321    }    }
322      
323      /**
324       * Inserts an element at the end of the list.
325       *
326       * @param e the entry to add
327       */
328    private void addLastEntry(Entry e)    private void addLastEntry(Entry e)
329    {    {
330        modCount++;
331        size++;
332      if (size == 0)      if (size == 0)
333        first = last = e;        first = last = e;
334      else      else
335        {        {
336          e.previous = last;          e.previous = last;
337          last.next = e;          last.next = e;
338          last = e;          last = e;
339        }        }
     size++;  
340    }    }
341    
342      /**
343       * Returns true if the list contains the given object. Comparison is done by
344       * <code>o == null ? e = null : o.equals(e)</code>.
345       *
346       * @param o the element to look for
347       * @return true if it is found
348       */
349    public boolean contains(Object o)    public boolean contains(Object o)
350    {    {
351      Entry e = first;      Entry e = first;
352      while (e != null)      while (e != null)
353        {        {
354          if (e.data == null ? o == null : o.equals(e.data))          if (equals(o, e.data))
355            return true;            return true;
356          e = e.next;          e = e.next;
357        }        }
358      return false;      return false;
359    }    }
360    
361      /**
362       * Returns the size of the list.
363       *
364       * @return the list size
365       */
366    public int size()    public int size()
367    {    {
368      return size;      return size;
369    }    }
370      
371      /**
372       * Adds an element to the end of the list.
373       *
374       * @param e the entry to add
375       * @return true, as it always succeeds
376       */
377    public boolean add(Object o)    public boolean add(Object o)
378    {    {
     modCount++;  
379      addLastEntry(new Entry(o));      addLastEntry(new Entry(o));
380      return true;      return true;
381    }    }
382      
383      /**
384       * Removes the entry at the lowest index in the list that matches the given
385       * object, comparing by <code>o == null ? e = null : o.equals(e)</code>.
386       *
387       * @param o the object to remove
388       * @return true if an instance of the object was removed
389       */
390    public boolean remove(Object o)    public boolean remove(Object o)
391    {    {
     modCount++;  
392      Entry e = first;      Entry e = first;
393      while (e != null)      while (e != null)
394        {        {
395          if (e.data == null ? o == null : o.equals(e.data))          if (equals(o, e.data))
396            {            {
397              removeEntry(e);              removeEntry(e);
398              return true;              return true;
399            }            }
400          e = e.next;          e = e.next;
401        }        }
402      return false;      return false;
403    }    }
404    
405      /**
406       * Append the elements of the collection in iteration order to the end of
407       * this list. If this list is modified externally (for example, if this
408       * list is the collection), behavior is unspecified.
409       *
410       * @param c the collection to append
411       * @return true if the list was modified
412       * @throws NullPointerException if c is null
413       */
414    public boolean addAll(Collection c)    public boolean addAll(Collection c)
415    {    {
416      return addAll(size, c);      return addAll(size, c);
417    }    }
418      
419      /**
420       * Insert the elements of the collection in iteration order at the given
421       * index of this list. If this list is modified externally (for example,
422       * if this list is the collection), behavior is unspecified.
423       *
424       * @param c the collection to append
425       * @return true if the list was modified
426       * @throws NullPointerException if c is null
427       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
428       */
429    public boolean addAll(int index, Collection c)    public boolean addAll(int index, Collection c)
430    {    {
431      if (index < 0 || index > size)      rangeInclusive(index);
       throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +  
                                           size);  
     modCount++;  
432      int csize = c.size();      int csize = c.size();
433    
434      if (csize == 0)      if (csize == 0)
435        return false;        return false;
436    
437      Iterator itr = c.iterator();      Iterator itr = c.iterator();
438        
439      // Get the entries just before and after index. If index is at the start      // Get the entries just before and after index. If index is at the start
440      // of the list, BEFORE is null. If index is at the end of thelist, AFTER is      // of the list, BEFORE is null. If index is at the end of the list, AFTER
441      // null. If the list is empty, both are null.      // is null. If the list is empty, both are null.
442      Entry after = null;      Entry after = null;
443      Entry before = null;          Entry before = null;
444      if (index != size)      if (index != size)
445        {        {
446          after = getEntry(index);          after = getEntry(index);
447          before = after.previous;          before = after.previous;
448        }        }
449      else      else
450        before = last;        before = last;
451          
452      // Create the first new entry. We do not yet set the link from `before'      // Create the first new entry. We do not yet set the link from `before'
453      // to the first entry, in order to deal with the case where (c == this).      // to the first entry, in order to deal with the case where (c == this).
454      // [Actually, we don't have to handle this case to fufill the      // [Actually, we don't have to handle this case to fufill the
455      // contract for addAll(), but Sun's implementation appears to.]      // contract for addAll(), but Sun's implementation appears to.]
456      Entry e = new Entry(itr.next());      Entry e = new Entry(itr.next());
457      e.previous = before;      e.previous = before;
458      Entry prev = e;      Entry prev = e;
459      Entry firstNew = e;      Entry firstNew = e;
460        
461      // Create and link all the remaining entries.      // Create and link all the remaining entries.
462      for (int pos = 1; pos < csize; pos++)      for (int pos = 1; pos < csize; pos++)
463        {        {
464          e = new Entry(itr.next());          e = new Entry(itr.next());
465          e.previous = prev;                e.previous = prev;
466          prev.next = e;          prev.next = e;
467          prev = e;          prev = e;
468        }        }
469    
470      // Link the new chain of entries into the list.      // Link the new chain of entries into the list.
471        modCount++;
472        size += csize;
473      prev.next = after;      prev.next = after;
474      if (after != null)      if (after != null)
475        after.previous = e;        after.previous = e;
476      else      else
477        last = e;        last = e;
478        
479      if (before != null)      if (before != null)
480        before.next = firstNew;        before.next = firstNew;
481      else      else
482        first = firstNew;        first = firstNew;
       
     size += csize;  
483      return true;      return true;
484    }    }
485    
486      /**
487       * Remove all elements from this list.
488       */
489    public void clear()    public void clear()
490    {    {
491      modCount++;      if (size > 0)
492      first = null;        {
493      last = null;          modCount++;
494      size = 0;          first = null;
495            last = null;
496            size = 0;
497          }
498    }    }
499    
500      /**
501       * Return the element at index.
502       *
503       * @param index the place to look
504       * @return the element at index
505       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
506       */
507    public Object get(int index)    public Object get(int index)
508    {    {
509      if (index < 0 || index >= size)      rangeExclusive(index);
510        throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +      return getEntry(index).data;
                                           size);  
     Entry e = getEntry(index);  
     return e.data;  
511    }    }
512      
513      /**
514       * Replace the element at the given location in the list.
515       *
516       * @param index which index to change
517       * @param o the new element
518       * @return the prior element
519       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
520       */
521    public Object set(int index, Object o)    public Object set(int index, Object o)
522    {    {
523      if (index < 0 || index >= size)      rangeExclusive(index);
       throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +  
                                           size);  
524      Entry e = getEntry(index);      Entry e = getEntry(index);
525      Object old = e.data;      Object old = e.data;
526      e.data = o;      e.data = o;
527      return old;      return old;
528    }    }
529    
530      /**
531       * Inserts an element in the given position in the list.
532       *
533       * @param index where to insert the element
534       * @param o the element to insert
535       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
536       */
537    public void add(int index, Object o)    public void add(int index, Object o)
538    {    {
539      if (index < 0 || index > size)      rangeInclusive(index);
540        throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +      Entry e = new Entry(o);
541                                            size);  
     modCount++;  
     addEntry(index, new Entry(o));      
   }  
     
   private void addEntry(int index, Entry e)  
   {  
542      if (index < size)      if (index < size)
543        {        {
544          Entry after = getEntry(index);          modCount++;
545          e.next = after;          size++;
546          e.previous = after.previous;          Entry after = getEntry(index);
547          if (after.previous == null)          e.next = after;
548            first = e;          e.previous = after.previous;
549          else          if (after.previous == null)
550            after.previous.next = e;            first = e;
551          after.previous = e;          else
552          size++;                    after.previous.next = e;
553            after.previous = e;
554        }        }
555      else      else
556        addLastEntry(e);        addLastEntry(e);
557    }    }
558      
559      /**
560       * Removes the element at the given position from the list.
561       *
562       * @param index the location of the element to remove
563       * @return the removed element
564       * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
565       */
566    public Object remove(int index)    public Object remove(int index)
567    {    {
568      if (index < 0 || index >= size)      rangeExclusive(index);
       throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +  
                                           size);  
     modCount++;  
569      Entry e = getEntry(index);      Entry e = getEntry(index);
570      removeEntry(e);      removeEntry(e);
571      return e.data;      return e.data;
572    }    }
573      
574      /**
575       * Returns the first index where the element is located in the list, or -1.
576       *
577       * @param o the element to look for
578       * @return its position, or -1 if not found
579       */
580    public int indexOf(Object o)    public int indexOf(Object o)
581    {    {
582      int index = 0;      int index = 0;
583      Entry e = first;      Entry e = first;
584      while (e != null)      while (e != null)
585        {        {
586          if (e.data == null ? o == null : o.equals(e.data))          if (equals(o, e.data))
587            return index;            return index;
588          ++index;          index++;
589          e = e.next;          e = e.next;
590        }        }
591      return -1;      return -1;
592    }    }
593      
594      /**
595       * Returns the last index where the element is located in the list, or -1.
596       *
597       * @param o the element to look for
598       * @return its position, or -1 if not found
599       */
600    public int lastIndexOf(Object o)    public int lastIndexOf(Object o)
601    {    {
602      int index = size - 1;      int index = size - 1;
603      Entry e = last;      Entry e = last;
604      while (e != null)      while (e != null)
605        {        {
606          if (e.data == null ? o == null : o.equals(e.data))          if (equals(o, e.data))
607            return index;            return index;
608          --index;          index--;
609          e = e.previous;          e = e.previous;
610        }        }
611      return -1;        return -1;
612    }    }
613    
614    /**    /**
# Line 448  public class LinkedList extends Abstract Line 617  public class LinkedList extends Abstract
617     * methods.     * methods.
618     *     *
619     * @param index the index of the element to be returned by the first call to     * @param index the index of the element to be returned by the first call to
620     *   next(), or size() to be initially positioned at the end of the list.     *        next(), or size() to be initially positioned at the end of the list
621     * @exception IndexOutOfBoundsException if index < 0 || index > size().     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
622     */     */
623    public ListIterator listIterator(int index)    public ListIterator listIterator(int index)
624    {    {
625      if (index < 0 || index > size)      rangeInclusive(index);
       throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +  
                                           size);  
626      return new LinkedListItr(index);      return new LinkedListItr(index);
627    }    }
628    
629    /**    /**
630     * Create a shallow copy of this LinkedList.     * Create a shallow copy of this LinkedList (the elements are not cloned).
631       *
632     * @return an object of the same class as this object, containing the     * @return an object of the same class as this object, containing the
633     * same elements in the same order.     *         same elements in the same order
634     */     */
635    public Object clone()    public Object clone()
636    {    {
637      LinkedList copy = null;      LinkedList copy = null;
638      try      try
639        {        {
640          copy = (LinkedList) super.clone();          copy = (LinkedList) super.clone();
641        }        }
642      catch (CloneNotSupportedException ex)      catch (CloneNotSupportedException ex)
643        {        {
# Line 478  public class LinkedList extends Abstract Line 646  public class LinkedList extends Abstract
646      copy.addAll(this);      copy.addAll(this);
647      return copy;      return copy;
648    }    }
649      
650      /**
651       * Returns an array which contains the elements of the list in order.
652       *
653       * @return an array containing the list elements
654       */
655    public Object[] toArray()    public Object[] toArray()
656    {    {
657      Object[] array = new Object[size];      Object[] array = new Object[size];
# Line 490  public class LinkedList extends Abstract Line 663  public class LinkedList extends Abstract
663        }        }
664      return array;      return array;
665    }    }
666      
667    public Object[] toArray(Object[] array)    /**
668    {     * Returns an Array whose component type is the runtime component type of
669      if (array.length < size)     * the passed-in Array.  The returned Array is populated with all of the
670        array = (Object[]) Array.newInstance(array.getClass().getComponentType(),     * elements in this LinkedList.  If the passed-in Array is not large enough
671                                             size);     * to store all of the elements in this List, a new Array will be created
672      else if (array.length > size)     * and returned; if the passed-in Array is <i>larger</i> than the size
673        array[size] = null;     * of this List, then size() index will be set to null.
674       *
675       * @param a the passed-in Array
676       * @return an array representation of this list
677       * @throws ArrayStoreException if the runtime type of a does not allow
678       *         an element in this list
679       * @throws NullPointerException if a is null
680       */
681      public Object[] toArray(Object[] a)
682      {
683        if (a.length < size)
684          a = (Object[]) Array.newInstance(a.getClass().getComponentType(), size);
685        else if (a.length > size)
686          a[size] = null;
687      Entry e = first;      Entry e = first;
688      for (int i = 0; i < size; i++)      for (int i = 0; i < size; i++)
689        {        {
690          array[i] = e.data;          a[i] = e.data;
691          e = e.next;          e = e.next;
692        }        }
693      return array;        return a;
694    }    }
695    
696    /**    /**
697     * Serialize an object to a stream.     * Serializes this object to the given stream.
698     * @serialdata the size of the list (int), followed by all the elements     *
699     * (Object) in proper order.     * @param s the stream to write to
700       * @throws IOException if the underlying stream fails
701       * @serialData the size of the list (int), followed by all the elements
702       *             (Object) in proper order
703     */     */
704    private void writeObject(ObjectOutputStream s) throws IOException    private void writeObject(ObjectOutputStream s) throws IOException
705    {    {
706      s.writeInt(size);      s.writeInt(size);
707      Iterator itr = iterator();      Entry e = first;
708      for (int i = 0; i < size; i++)      while (e != null)
709        s.writeObject(itr.next());        {
710            s.writeObject(e.data);
711            e = e.next;
712          }
713    }    }
714    
715    /**    /**
716     * Deserialize an object from a stream.     * Deserializes this object from the given stream.
717     * @serialdata the size of the list (int), followed by all the elements     *
718     * (Object) in proper order.     * @param s the stream to read from
719       * @throws ClassNotFoundException if the underlying stream fails
720       * @throws IOException if the underlying stream fails
721       * @serialData the size of the list (int), followed by all the elements
722       *             (Object) in proper order
723     */     */
724    private void readObject(ObjectInputStream s)    private void readObject(ObjectInputStream s)
725      throws IOException, ClassNotFoundException      throws IOException, ClassNotFoundException
726    {    {
727      int serialSize = s.readInt();      int i = s.readInt();
728      for (int i = 0; i < serialSize; i++)      while (--i >= 0)
729        addLastEntry(new Entry(s.readObject()));        addLastEntry(new Entry(s.readObject()));
730    }    }
731      
732    /** A ListIterator over the list. This class keeps track of its    /**
733       * A ListIterator over the list. This class keeps track of its
734     * position in the list and the two list entries it is between.     * position in the list and the two list entries it is between.
735       *
736       * @author Original author unknown
737       * @author Eric Blake <ebb9@email.byu.edu>
738     */     */
739    class LinkedListItr implements ListIterator    private final class LinkedListItr implements ListIterator
740    {    {
741      int knownMod;      /** Number of modifications we know about. */
742      Entry next;         // entry that will be returned by next().      private int knownMod = modCount;
743      Entry previous;     // entry that will be returned by previous().  
744      Entry lastReturned; // entry that will be affected by remove() or set().      /** Entry that will be returned by next(). */
745      int position;       // index of `next'.      private Entry next;
746    
747        /** Entry that will be returned by previous(). */
748        private Entry previous;
749    
750        /** Entry that will be affected by remove() or set(). */
751        private Entry lastReturned;
752    
753        /** Index of `next'. */
754        private int position;
755    
756        /**
757         * Initialize the iterator.
758         *
759         * @param index the initial index
760         */
761      LinkedListItr(int index)      LinkedListItr(int index)
762      {      {
763        if (index == size)        if (index == size)
764          {          {
765            next = null;            next = null;
766            previous = last;            previous = last;
767          }          }
768        else        else
769          {          {
770            next = getEntry(index);            next = getEntry(index);
771            previous = next.previous;            previous = next.previous;
772          }          }
773        position = index;        position = index;
       knownMod = modCount;  
774      }      }
775    
776        /**
777         * Checks for iterator consistency.
778         *
779         * @throws ConcurrentModificationException if the list was modified
780         */
781      private void checkMod()      private void checkMod()
782      {      {
783        if (knownMod != modCount)        if (knownMod != modCount)
784          throw new ConcurrentModificationException();          throw new ConcurrentModificationException();
785      }      }
786    
787        /**
788         * Returns the index of the next element.
789         *
790         * @return the next index
791         * @throws ConcurrentModificationException if the list was modified
792         */
793      public int nextIndex()      public int nextIndex()
794      {      {
795        checkMod();        checkMod();
796        return position;        return position;
797      }      }
798    
799        /**
800         * Returns the index of the previous element.
801         *
802         * @return the previous index
803         * @throws ConcurrentModificationException if the list was modified
804         */
805      public int previousIndex()      public int previousIndex()
806      {      {
807        checkMod();        checkMod();
808        return position - 1;        return position - 1;
809      }      }
810    
811        /**
812         * Returns true if more elements exist via next.
813         *
814         * @return true if next will succeed
815         * @throws ConcurrentModificationException if the list was modified
816         */
817      public boolean hasNext()      public boolean hasNext()
818      {      {
819        checkMod();        checkMod();
820        return (next != null);        return (next != null);
821      }      }
822    
823        /**
824         * Returns true if more elements exist via previous.
825         *
826         * @return true if previous will succeed
827         * @throws ConcurrentModificationException if the list was modified
828         */
829      public boolean hasPrevious()      public boolean hasPrevious()
830      {      {
831        checkMod();        checkMod();
832        return (previous != null);        return (previous != null);
833      }      }
834    
835        /**
836         * Returns the next element.
837         *
838         * @return the next element
839         * @throws ConcurrentModificationException if the list was modified
840         * @throws NoSuchElementException if there is no next
841         */
842      public Object next()      public Object next()
843      {      {
844        checkMod();        checkMod();
845        if (next == null)        if (next == null)
846          throw new NoSuchElementException();          throw new NoSuchElementException();
847        position++;        position++;
848        lastReturned = previous = next;        lastReturned = previous = next;
849        next = lastReturned.next;        next = lastReturned.next;
850        return lastReturned.data;        return lastReturned.data;
851      }      }
852    
853        /**
854         * Returns the previous element.
855         *
856         * @return the previous element
857         * @throws ConcurrentModificationException if the list was modified
858         * @throws NoSuchElementException if there is no previous
859         */
860      public Object previous()      public Object previous()
861      {      {
862        checkMod();        checkMod();
863        if (previous == null)        if (previous == null)
864          throw new NoSuchElementException();          throw new NoSuchElementException();
865        position--;        position--;
866        lastReturned = next = previous;        lastReturned = next = previous;
867        previous = lastReturned.previous;        previous = lastReturned.previous;
868        return lastReturned.data;        return lastReturned.data;
869      }      }
870    
871        /**
872         * Remove the most recently returned element from the list.
873         *
874         * @throws ConcurrentModificationException if the list was modified
875         * @throws IllegalStateException if there was no last element
876         */
877      public void remove()      public void remove()
878      {      {
879        checkMod();        checkMod();
880        if (lastReturned == null)        if (lastReturned == null)
881          throw new IllegalStateException();          throw new IllegalStateException();
882    
883        // Adjust the position to before the removed element, if the element        // Adjust the position to before the removed element, if the element
884        // being removed is behind the cursor.        // being removed is behind the cursor.
885        if (lastReturned == previous)        if (lastReturned == previous)
886          position--;          position--;
887    
888        next = lastReturned.next;        next = lastReturned.next;
889        previous = lastReturned.previous;        previous = lastReturned.previous;
       modCount++;  
       knownMod++;  
890        removeEntry(lastReturned);        removeEntry(lastReturned);
891                knownMod++;
892    
893        lastReturned = null;        lastReturned = null;
894      }      }
895    
896        /**
897         * Adds an element between the previous and next, and advance to the next.
898         *
899         * @param o the element to add
900         * @throws ConcurrentModificationException if the list was modified
901         */
902      public void add(Object o)      public void add(Object o)
903      {      {
904        checkMod();        checkMod();
905        modCount++;        modCount++;
906        knownMod++;        knownMod++;
907          size++;
908          position++;
909        Entry e = new Entry(o);        Entry e = new Entry(o);
910        e.previous = previous;        e.previous = previous;
911        e.next = next;        e.next = next;
912    
913        if (previous != null)        if (previous != null)
914          previous.next = e;          previous.next = e;
915        else        else
916          first = e;          first = e;
917    
918        if (next != null)        if (next != null)
919          {          {
920            next.previous = e;            next.previous = e;
921            next = next.next;            next = next.next;
922          }          }
923        else        else
924          last = e;          last = e;
925    
926        previous = e;        previous = e;
       size++;  
       position++;  
927        lastReturned = null;        lastReturned = null;
928      }      }
929    
930        /**
931         * Changes the contents of the element most recently returned.
932         *
933         * @param o the new element
934         * @throws ConcurrentModificationException if the list was modified
935         * @throws IllegalStateException if there was no last element
936         */
937      public void set(Object o)      public void set(Object o)
938      {      {
939        checkMod();        checkMod();
940        if (lastReturned == null)        if (lastReturned == null)
941          throw new IllegalStateException();          throw new IllegalStateException();
942        lastReturned.data = o;        lastReturned.data = o;
943      }      }
944    }  // class LinkedListItr      } // class LinkedListItr
945  }  }

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

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