LinkedList.java 23.6 KB
Newer Older
1
/* LinkedList.java -- Linked list implementation of the List interface
2
   Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 4 5 6 7 8 9

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
10

11 12 13 14 15 16 17 18 19 20
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */
37 38 39 40 41 42 43


package java.util;
import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
44
import java.lang.reflect.Array;
45 46

/**
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
 * Linked list implementation of the List interface. In addition to the
 * methods of the List interface, this class provides access to the first
 * and last list elements in O(1) time for easy stack, queue, or double-ended
 * queue (deque) creation. The list is doubly-linked, with traversal to a
 * given index starting from the end closest to the element.<p>
 *
 * LinkedList is not synchronized, so if you need multi-threaded access,
 * consider using:<br>
 * <code>List l = Collections.synchronizedList(new LinkedList(...));</code>
 * <p>
 *
 * The iterators are <i>fail-fast</i>, meaning that any structural
 * modification, except for <code>remove()</code> called on the iterator
 * itself, cause the iterator to throw a
 * {@link ConcurrentModificationException} rather than exhibit
 * non-deterministic behavior.
 *
 * @author Original author unknown
 * @author Bryce McKinlay
 * @author Eric Blake <ebb9@email.byu.edu>
 * @see List
 * @see ArrayList
 * @see Vector
 * @see Collections#synchronizedList(List)
 * @since 1.2
 * @status missing javadoc, but complete to 1.4
73
 */
74
public class LinkedList extends AbstractSequentialList
75
  implements List, Cloneable, Serializable
76
{
77 78 79 80
  /**
   * Compatible with JDK 1.2.
   */
  private static final long serialVersionUID = 876323262645176354L;
81 82

  /**
83
   * The first element in the list.
84
   */
85
  transient Entry first;
86 87 88 89

  /**
   * The last element in the list.
   */
90
  transient Entry last;
91 92 93 94 95 96 97 98 99

  /**
   * The current length of the list.
   */
  transient int size = 0;

  /**
   * Class to represent an entry in the list. Holds a single element.
   */
100
  private static final class Entry
101
  {
102
    /** The element in the list. */
103
    Object data;
104 105

    /** The next list entry, null if this is last. */
106
    Entry next;
107 108

    /** The previous list entry, null if this is first. */
109
    Entry previous;
110 111 112 113 114

    /**
     * Construct an entry.
     * @param data the list element
     */
115 116 117
    Entry(Object data)
    {
      this.data = data;
118
    }
119 120
  } // class Entry

121 122 123 124 125 126
  /**
   * Obtain the Entry at a given position in a list. This method of course
   * takes linear time, but it is intelligent enough to take the shorter of the
   * paths to get to the Entry required. This implies that the first or last
   * entry in the list is obtained in constant time, which is a very desirable
   * property.
127
   * For speed and flexibility, range checking is not done in this method:
128
   * Incorrect values will be returned if (n &lt; 0) or (n &gt;= size).
129
   *
130 131
   * @param n the number of the entry to get
   * @return the entry at position n
132
   */
133 134
  // Package visible for use in nested classes.
  Entry getEntry(int n)
135 136 137 138 139
  {
    Entry e;
    if (n < size / 2)
      {
        e = first;
140 141 142
        // n less than size/2, iterate from start
        while (n-- > 0)
          e = e.next;
143
      }
144 145
    else
      {
146 147 148 149
        e = last;
        // n greater than size/2, iterate from end
        while (++n < size)
          e = e.previous;
150
      }
151 152
    return e;
  }
153 154 155 156 157 158 159

  /**
   * Remove an entry from the list. This will adjust size and deal with
   *  `first' and  `last' appropriatly.
   *
   * @param e the entry to remove
   */
160 161
  // Package visible for use in nested classes.
  void removeEntry(Entry e)
162
  {
163 164 165
    modCount++;
    size--;
    if (size == 0)
166 167 168
      first = last = null;
    else
      {
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
        if (e == first)
          {
            first = e.next;
            e.next.previous = null;
          }
        else if (e == last)
          {
            last = e.previous;
            e.previous.next = null;
          }
        else
          {
            e.next.previous = e.previous;
            e.previous.next = e.next;
          }
184
      }
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
  }

  /**
   * Checks that the index is in the range of possible elements (inclusive).
   *
   * @param index the index to check
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size
   */
  private void checkBoundsInclusive(int index)
  {
    if (index < 0 || index > size)
      throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
                                          + size);
  }

  /**
   * Checks that the index is in the range of existing elements (exclusive).
   *
   * @param index the index to check
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size
   */
  private void checkBoundsExclusive(int index)
  {
    if (index < 0 || index >= size)
      throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
                                          + size);
211 212 213 214 215
  }

  /**
   * Create an empty linked list.
   */
216 217
  public LinkedList()
  {
218 219 220 221 222 223
  }

  /**
   * Create a linked list containing the elements, in order, of a given
   * collection.
   *
224 225
   * @param c the collection to populate this list from
   * @throws NullPointerException if c is null
226
   */
227 228
  public LinkedList(Collection c)
  {
229 230 231
    addAll(c);
  }

232 233 234 235 236 237
  /**
   * Returns the first element in the list.
   *
   * @return the first list element
   * @throws NoSuchElementException if the list is empty
   */
238 239 240
  public Object getFirst()
  {
    if (size == 0)
241
      throw new NoSuchElementException();
242
    return first.data;
243 244
  }

245 246 247 248 249 250
  /**
   * Returns the last element in the list.
   *
   * @return the last list element
   * @throws NoSuchElementException if the list is empty
   */
251 252 253
  public Object getLast()
  {
    if (size == 0)
254
      throw new NoSuchElementException();
255
    return last.data;
256 257
  }

258 259 260 261 262 263
  /**
   * Remove and return the first element in the list.
   *
   * @return the former first element in the list
   * @throws NoSuchElementException if the list is empty
   */
264 265 266
  public Object removeFirst()
  {
    if (size == 0)
267 268
      throw new NoSuchElementException();
    modCount++;
269
    size--;
270
    Object r = first.data;
271

272 273
    if (first.next != null)
      first.next.previous = null;
274 275 276 277
    else
      last = null;

    first = first.next;
278

279
    return r;
280 281
  }

282 283 284 285 286 287
  /**
   * Remove and return the last element in the list.
   *
   * @return the former last element in the list
   * @throws NoSuchElementException if the list is empty
   */
288 289 290
  public Object removeLast()
  {
    if (size == 0)
291 292
      throw new NoSuchElementException();
    modCount++;
293
    size--;
294
    Object r = last.data;
295

296
    if (last.previous != null)
297 298 299
      last.previous.next = null;
    else
      first = null;
300

301
    last = last.previous;
302

303
    return r;
304 305
  }

306 307 308 309 310
  /**
   * Insert an element at the first of the list.
   *
   * @param o the element to insert
   */
311 312 313
  public void addFirst(Object o)
  {
    Entry e = new Entry(o);
314 315

    modCount++;
316 317 318 319
    if (size == 0)
      first = last = e;
    else
      {
320
        e.next = first;
321
        first.previous = e;
322 323
        first = e;
      }
324
    size++;
325 326
  }

327 328 329 330 331
  /**
   * Insert an element at the last of the list.
   *
   * @param o the element to insert
   */
332 333 334 335
  public void addLast(Object o)
  {
    addLastEntry(new Entry(o));
  }
336 337 338 339 340 341

  /**
   * Inserts an element at the end of the list.
   *
   * @param e the entry to add
   */
342 343
  private void addLastEntry(Entry e)
  {
344
    modCount++;
345 346 347 348
    if (size == 0)
      first = last = e;
    else
      {
349
        e.previous = last;
350
        last.next = e;
351
        last = e;
352 353
      }
    size++;
354 355
  }

356 357 358 359 360 361 362
  /**
   * Returns true if the list contains the given object. Comparison is done by
   * <code>o == null ? e = null : o.equals(e)</code>.
   *
   * @param o the element to look for
   * @return true if it is found
   */
363 364 365 366 367
  public boolean contains(Object o)
  {
    Entry e = first;
    while (e != null)
      {
368 369
        if (equals(o, e.data))
          return true;
370 371 372 373 374
        e = e.next;
      }
    return false;
  }

375 376 377 378 379
  /**
   * Returns the size of the list.
   *
   * @return the list size
   */
380 381
  public int size()
  {
382 383
    return size;
  }
384 385 386 387 388 389 390

  /**
   * Adds an element to the end of the list.
   *
   * @param e the entry to add
   * @return true, as it always succeeds
   */
391 392 393 394 395
  public boolean add(Object o)
  {
    addLastEntry(new Entry(o));
    return true;
  }
396 397 398 399 400 401 402 403

  /**
   * Removes the entry at the lowest index in the list that matches the given
   * object, comparing by <code>o == null ? e = null : o.equals(e)</code>.
   *
   * @param o the object to remove
   * @return true if an instance of the object was removed
   */
404 405 406 407 408
  public boolean remove(Object o)
  {
    Entry e = first;
    while (e != null)
      {
409 410 411 412 413
        if (equals(o, e.data))
          {
            removeEntry(e);
            return true;
          }
414 415 416 417
        e = e.next;
      }
    return false;
  }
418

419 420 421 422 423 424 425 426 427
  /**
   * Append the elements of the collection in iteration order to the end of
   * this list. If this list is modified externally (for example, if this
   * list is the collection), behavior is unspecified.
   *
   * @param c the collection to append
   * @return true if the list was modified
   * @throws NullPointerException if c is null
   */
428 429 430 431
  public boolean addAll(Collection c)
  {
    return addAll(size, c);
  }
432 433 434 435 436 437 438 439 440 441 442

  /**
   * Insert the elements of the collection in iteration order at the given
   * index of this list. If this list is modified externally (for example,
   * if this list is the collection), behavior is unspecified.
   *
   * @param c the collection to append
   * @return true if the list was modified
   * @throws NullPointerException if c is null
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
   */
443 444
  public boolean addAll(int index, Collection c)
  {
445
    checkBoundsInclusive(index);
446 447 448 449 450 451
    int csize = c.size();

    if (csize == 0)
      return false;

    Iterator itr = c.iterator();
452

453
    // Get the entries just before and after index. If index is at the start
454 455
    // of the list, BEFORE is null. If index is at the end of the list, AFTER
    // is null. If the list is empty, both are null.
456
    Entry after = null;
457
    Entry before = null;
458 459
    if (index != size)
      {
460 461
        after = getEntry(index);
        before = after.previous;
462 463 464
      }
    else
      before = last;
465

466
    // Create the first new entry. We do not yet set the link from `before'
467 468
    // to the first entry, in order to deal with the case where (c == this).
    // [Actually, we don't have to handle this case to fufill the
469 470 471 472 473
    // contract for addAll(), but Sun's implementation appears to.]
    Entry e = new Entry(itr.next());
    e.previous = before;
    Entry prev = e;
    Entry firstNew = e;
474

475 476 477 478
    // Create and link all the remaining entries.
    for (int pos = 1; pos < csize; pos++)
      {
        e = new Entry(itr.next());
479 480 481
        e.previous = prev;
        prev.next = e;
        prev = e;
482
      }
483

484
    // Link the new chain of entries into the list.
485 486
    modCount++;
    size += csize;
487 488 489 490 491
    prev.next = after;
    if (after != null)
      after.previous = e;
    else
      last = e;
492

493 494 495 496 497
    if (before != null)
      before.next = firstNew;
    else
      first = firstNew;
    return true;
498 499
  }

500 501 502
  /**
   * Remove all elements from this list.
   */
503 504
  public void clear()
  {
505 506 507 508 509 510 511
    if (size > 0)
      {
        modCount++;
        first = null;
        last = null;
        size = 0;
      }
512 513
  }

514 515 516 517 518 519 520
  /**
   * Return the element at index.
   *
   * @param index the place to look
   * @return the element at index
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
   */
521 522
  public Object get(int index)
  {
523 524
    checkBoundsExclusive(index);
    return getEntry(index).data;
525
  }
526 527 528 529 530 531 532 533 534

  /**
   * Replace the element at the given location in the list.
   *
   * @param index which index to change
   * @param o the new element
   * @return the prior element
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
   */
535 536
  public Object set(int index, Object o)
  {
537
    checkBoundsExclusive(index);
538 539 540 541 542 543
    Entry e = getEntry(index);
    Object old = e.data;
    e.data = o;
    return old;
  }

544 545 546 547 548 549 550
  /**
   * Inserts an element in the given position in the list.
   *
   * @param index where to insert the element
   * @param o the element to insert
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
   */
551 552
  public void add(int index, Object o)
  {
553 554 555
    checkBoundsInclusive(index);
    Entry e = new Entry(o);

556 557
    if (index < size)
      {
558 559 560 561 562 563 564 565 566 567
        modCount++;
        Entry after = getEntry(index);
        e.next = after;
        e.previous = after.previous;
        if (after.previous == null)
          first = e;
        else
          after.previous.next = e;
        after.previous = e;
        size++;
568 569 570 571
      }
    else
      addLastEntry(e);
  }
572 573 574 575 576 577 578 579

  /**
   * Removes the element at the given position from the list.
   *
   * @param index the location of the element to remove
   * @return the removed element
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
   */
580 581
  public Object remove(int index)
  {
582
    checkBoundsExclusive(index);
583 584 585 586
    Entry e = getEntry(index);
    removeEntry(e);
    return e.data;
  }
587 588 589 590 591 592 593

  /**
   * Returns the first index where the element is located in the list, or -1.
   *
   * @param o the element to look for
   * @return its position, or -1 if not found
   */
594 595 596 597 598 599
  public int indexOf(Object o)
  {
    int index = 0;
    Entry e = first;
    while (e != null)
      {
600 601 602
        if (equals(o, e.data))
          return index;
        index++;
603 604 605 606
        e = e.next;
      }
    return -1;
  }
607 608 609 610 611 612 613

  /**
   * Returns the last index where the element is located in the list, or -1.
   *
   * @param o the element to look for
   * @return its position, or -1 if not found
   */
614 615 616 617 618 619
  public int lastIndexOf(Object o)
  {
    int index = size - 1;
    Entry e = last;
    while (e != null)
      {
620 621 622
        if (equals(o, e.data))
          return index;
        index--;
623 624
        e = e.previous;
      }
625
    return -1;
626 627
  }

628 629 630 631 632 633
  /**
   * Obtain a ListIterator over this list, starting at a given index. The
   * ListIterator returned by this method supports the add, remove and set
   * methods.
   *
   * @param index the index of the element to be returned by the first call to
634 635
   *        next(), or size() to be initially positioned at the end of the list
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
636
   */
637 638
  public ListIterator listIterator(int index)
  {
639
    checkBoundsInclusive(index);
640
    return new LinkedListItr(index);
641 642 643
  }

  /**
644 645
   * Create a shallow copy of this LinkedList (the elements are not cloned).
   *
646
   * @return an object of the same class as this object, containing the
647
   *         same elements in the same order
648
   */
649
  public Object clone()
650
  {
651
    LinkedList copy = null;
652 653
    try
      {
654
        copy = (LinkedList) super.clone();
655 656 657 658
      }
    catch (CloneNotSupportedException ex)
      {
      }
659
    copy.clear();
660 661 662
    copy.addAll(this);
    return copy;
  }
663 664 665 666 667 668

  /**
   * Returns an array which contains the elements of the list in order.
   *
   * @return an array containing the list elements
   */
669 670 671 672 673 674 675 676 677 678 679
  public Object[] toArray()
  {
    Object[] array = new Object[size];
    Entry e = first;
    for (int i = 0; i < size; i++)
      {
        array[i] = e.data;
        e = e.next;
      }
    return array;
  }
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695

  /**
   * Returns an Array whose component type is the runtime component type of
   * the passed-in Array.  The returned Array is populated with all of the
   * elements in this LinkedList.  If the passed-in Array is not large enough
   * to store all of the elements in this List, a new Array will be created 
   * and returned; if the passed-in Array is <i>larger</i> than the size
   * of this List, then size() index will be set to null.
   *
   * @param a the passed-in Array
   * @return an array representation of this list
   * @throws ArrayStoreException if the runtime type of a does not allow
   *         an element in this list
   * @throws NullPointerException if a is null
   */
  public Object[] toArray(Object[] a)
696
  {
697 698 699 700
    if (a.length < size)
      a = (Object[]) Array.newInstance(a.getClass().getComponentType(), size);
    else if (a.length > size)
      a[size] = null;
701 702 703
    Entry e = first;
    for (int i = 0; i < size; i++)
      {
704
        a[i] = e.data;
705 706
        e = e.next;
      }
707
    return a;
708
  }
709 710

  /**
711 712 713 714 715 716
   * Serializes this object to the given stream.
   *
   * @param s the stream to write to
   * @throws IOException if the underlying stream fails
   * @serialData the size of the list (int), followed by all the elements
   *             (Object) in proper order
717
   */
718
  private void writeObject(ObjectOutputStream s) throws IOException
719
  {
720
    s.defaultWriteObject();
721
    s.writeInt(size);
722 723 724 725 726 727
    Entry e = first;
    while (e != null)
      {
        s.writeObject(e.data);
        e = e.next;
      }
728 729 730
  }

  /**
731 732 733 734 735 736 737
   * Deserializes this object from the given stream.
   *
   * @param s the stream to read from
   * @throws ClassNotFoundException if the underlying stream fails
   * @throws IOException if the underlying stream fails
   * @serialData the size of the list (int), followed by all the elements
   *             (Object) in proper order
738 739 740 741
   */
  private void readObject(ObjectInputStream s)
    throws IOException, ClassNotFoundException
  {
742 743 744
    s.defaultReadObject();
    int i = s.readInt();
    while (--i >= 0)
745
      addLastEntry(new Entry(s.readObject()));
746
  }
747 748 749

  /**
   * A ListIterator over the list. This class keeps track of its
750
   * position in the list and the two list entries it is between.
751 752 753
   *
   * @author Original author unknown
   * @author Eric Blake <ebb9@email.byu.edu>
754
   */
755
  private final class LinkedListItr implements ListIterator
756
  {
757 758 759 760 761 762 763 764
    /** Number of modifications we know about. */
    private int knownMod = modCount;

    /** Entry that will be returned by next(). */
    private Entry next;

    /** Entry that will be returned by previous(). */
    private Entry previous;
765

766 767 768 769 770 771 772 773 774 775 776
    /** Entry that will be affected by remove() or set(). */
    private Entry lastReturned;

    /** Index of `next'. */
    private int position;

    /**
     * Initialize the iterator.
     *
     * @param index the initial index
     */
777
    LinkedListItr(int index)
778
    {
779 780 781
      if (index == size)
        {
          next = null;
782 783
          previous = last;
        }
784 785 786
      else
        {
          next = getEntry(index);
787 788
          previous = next.previous;
        }
789 790 791
      position = index;
    }

792 793 794 795 796
    /**
     * Checks for iterator consistency.
     *
     * @throws ConcurrentModificationException if the list was modified
     */
797 798 799
    private void checkMod()
    {
      if (knownMod != modCount)
800
        throw new ConcurrentModificationException();
801 802
    }

803 804 805 806 807 808
    /**
     * Returns the index of the next element.
     *
     * @return the next index
     * @throws ConcurrentModificationException if the list was modified
     */
809 810 811 812 813 814
    public int nextIndex()
    {
      checkMod();
      return position;
    }

815 816 817 818 819 820
    /**
     * Returns the index of the previous element.
     *
     * @return the previous index
     * @throws ConcurrentModificationException if the list was modified
     */
821 822 823 824 825 826
    public int previousIndex()
    {
      checkMod();
      return position - 1;
    }

827 828 829 830 831 832
    /**
     * Returns true if more elements exist via next.
     *
     * @return true if next will succeed
     * @throws ConcurrentModificationException if the list was modified
     */
833 834 835 836 837 838
    public boolean hasNext()
    {
      checkMod();
      return (next != null);
    }

839 840 841 842 843 844
    /**
     * Returns true if more elements exist via previous.
     *
     * @return true if previous will succeed
     * @throws ConcurrentModificationException if the list was modified
     */
845 846 847 848 849 850
    public boolean hasPrevious()
    {
      checkMod();
      return (previous != null);
    }

851 852 853 854 855 856 857
    /**
     * Returns the next element.
     *
     * @return the next element
     * @throws ConcurrentModificationException if the list was modified
     * @throws NoSuchElementException if there is no next
     */
858 859 860 861
    public Object next()
    {
      checkMod();
      if (next == null)
862
        throw new NoSuchElementException();
863 864 865 866 867 868
      position++;
      lastReturned = previous = next;
      next = lastReturned.next;
      return lastReturned.data;
    }

869 870 871 872 873 874 875
    /**
     * Returns the previous element.
     *
     * @return the previous element
     * @throws ConcurrentModificationException if the list was modified
     * @throws NoSuchElementException if there is no previous
     */
876 877 878 879
    public Object previous()
    {
      checkMod();
      if (previous == null)
880
        throw new NoSuchElementException();
881 882 883 884 885 886
      position--;
      lastReturned = next = previous;
      previous = lastReturned.previous;
      return lastReturned.data;
    }

887 888 889 890 891 892
    /**
     * Remove the most recently returned element from the list.
     *
     * @throws ConcurrentModificationException if the list was modified
     * @throws IllegalStateException if there was no last element
     */
893 894 895 896
    public void remove()
    {
      checkMod();
      if (lastReturned == null)
897
        throw new IllegalStateException();
898 899 900 901

      // Adjust the position to before the removed element, if the element
      // being removed is behind the cursor.
      if (lastReturned == previous)
902
        position--;
903 904 905 906

      next = lastReturned.next;
      previous = lastReturned.previous;
      removeEntry(lastReturned);
907 908
      knownMod++;

909 910 911
      lastReturned = null;
    }

912 913 914 915 916 917
    /**
     * Adds an element between the previous and next, and advance to the next.
     *
     * @param o the element to add
     * @throws ConcurrentModificationException if the list was modified
     */
918 919 920
    public void add(Object o)
    {
      checkMod();
921 922
      modCount++;
      knownMod++;
923 924
      size++;
      position++;
925
      Entry e = new Entry(o);
926 927 928 929
      e.previous = previous;
      e.next = next;

      if (previous != null)
930
        previous.next = e;
931
      else
932
        first = e;
933 934

      if (next != null)
935
        next.previous = e;
936
      else
937
        last = e;
938

939 940 941 942
      previous = e;
      lastReturned = null;
    }

943 944 945 946 947 948 949
    /**
     * Changes the contents of the element most recently returned.
     *
     * @param o the new element
     * @throws ConcurrentModificationException if the list was modified
     * @throws IllegalStateException if there was no last element
     */
950 951 952 953
    public void set(Object o)
    {
      checkMod();
      if (lastReturned == null)
954
        throw new IllegalStateException();
955 956
      lastReturned.data = o;
    }
957
  } // class LinkedListItr
958
}