ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/LinkedList.java
(Generate patch)

Comparing jsr166/src/main/java/util/LinkedList.java (file contents):
Revision 1.32 by jsr166, Wed May 18 00:46:42 2005 UTC vs.
Revision 1.49 by jsr166, Sun May 18 23:59:57 2008 UTC

# Line 1 | Line 1
1   /*
2 < * %W% %E%
2 > * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
3 > * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4   *
5 < * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
6 < * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
5 > * This code is free software; you can redistribute it and/or modify it
6 > * under the terms of the GNU General Public License version 2 only, as
7 > * published by the Free Software Foundation.  Sun designates this
8 > * particular file as subject to the "Classpath" exception as provided
9 > * by Sun in the LICENSE file that accompanied this code.
10 > *
11 > * This code is distributed in the hope that it will be useful, but WITHOUT
12 > * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 > * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 > * version 2 for more details (a copy is included in the LICENSE file that
15 > * accompanied this code).
16 > *
17 > * You should have received a copy of the GNU General Public License version
18 > * 2 along with this work; if not, write to the Free Software Foundation,
19 > * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 > *
21 > * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 > * CA 95054 USA or visit www.sun.com if you need additional information or
23 > * have any questions.
24   */
25  
26   package java.util;
# Line 25 | Line 43 | package java.util;
43   * list.  Operations that index into the list will traverse the list from
44   * the beginning or the end, whichever is closer to the specified index.<p>
45   *
46 < * <b>Note that this implementation is not synchronized.</b> If multiple
47 < * threads access a list concurrently, and at least one of the threads
48 < * modifies the list structurally, it <i>must</i> be synchronized
49 < * externally.  (A structural modification is any operation that adds or
50 < * deletes one or more elements; merely setting the value of an element is not
51 < * a structural modification.)  This is typically accomplished by
52 < * synchronizing on some object that naturally encapsulates the list.  If no
53 < * such object exists, the list should be "wrapped" using the
54 < * Collections.synchronizedList method.  This is best done at creation time,
55 < * to prevent accidental unsynchronized access to the list: <pre>
56 < *     List list = Collections.synchronizedList(new LinkedList(...));
57 < * </pre>
46 > * <p><strong>Note that this implementation is not synchronized.</strong>
47 > * If multiple threads access a linked list concurrently, and at least
48 > * one of the threads modifies the list structurally, it <i>must</i> be
49 > * synchronized externally.  (A structural modification is any operation
50 > * that adds or deletes one or more elements; merely setting the value of
51 > * an element is not a structural modification.)  This is typically
52 > * accomplished by synchronizing on some object that naturally
53 > * encapsulates the list.
54 > *
55 > * If no such object exists, the list should be "wrapped" using the
56 > * {@link Collections#synchronizedList Collections.synchronizedList}
57 > * method.  This is best done at creation time, to prevent accidental
58 > * unsynchronized access to the list:<pre>
59 > *   List list = Collections.synchronizedList(new LinkedList(...));</pre>
60   *
61   * <p>The iterators returned by this class's <tt>iterator</tt> and
62   * <tt>listIterator</tt> methods are <i>fail-fast</i>: if the list is
# Line 57 | Line 77 | package java.util;
77   * should be used only to detect bugs.</i>
78   *
79   * <p>This class is a member of the
80 < * <a href="{@docRoot}/../guide/collections/index.html">
80 > * <a href="{@docRoot}/../technotes/guides/collections/index.html">
81   * Java Collections Framework</a>.
82   *
83   * @author  Josh Bloch
84 < * @version %I%, %G%
85 < * @see     List
86 < * @see     ArrayList
67 < * @see     Vector
68 < * @see     Collections#synchronizedList(List)
84 > * @see     List
85 > * @see     ArrayList
86 > * @see     Vector
87   * @since 1.2
88   * @param <E> the type of elements held in this collection
89   */
# Line 92 | Line 110 | public class LinkedList<E>
110       * @param  c the collection whose elements are to be placed into this list
111       * @throws NullPointerException if the specified collection is null
112       */
113 <     public LinkedList(Collection<? extends E> c) {
114 <         this();
115 <         addAll(c);
116 <     }
113 >    public LinkedList(Collection<? extends E> c) {
114 >        this();
115 >        addAll(c);
116 >    }
117  
118      /**
119       * Returns the first element in this list.
# Line 104 | Line 122 | public class LinkedList<E>
122       * @throws NoSuchElementException if this list is empty
123       */
124      public E getFirst() {
125 <        if (size==0)
126 <            throw new NoSuchElementException();
125 >        if (size==0)
126 >            throw new NoSuchElementException();
127  
128 <        return header.next.element;
128 >        return header.next.element;
129      }
130  
131      /**
# Line 117 | Line 135 | public class LinkedList<E>
135       * @throws NoSuchElementException if this list is empty
136       */
137      public E getLast()  {
138 <        if (size==0)
139 <            throw new NoSuchElementException();
138 >        if (size==0)
139 >            throw new NoSuchElementException();
140  
141 <        return header.previous.element;
141 >        return header.previous.element;
142      }
143  
144      /**
# Line 130 | Line 148 | public class LinkedList<E>
148       * @throws NoSuchElementException if this list is empty
149       */
150      public E removeFirst() {
151 <        return remove(header.next);
151 >        return remove(header.next);
152      }
153  
154      /**
# Line 140 | Line 158 | public class LinkedList<E>
158       * @throws NoSuchElementException if this list is empty
159       */
160      public E removeLast() {
161 <        return remove(header.previous);
161 >        return remove(header.previous);
162      }
163  
164      /**
165 <     * Inserts the given element at the beginning of this list.
165 >     * Inserts the specified element at the beginning of this list.
166       *
167 <     * @param e the element to be inserted at the beginning of this list
167 >     * @param e the element to add
168       */
169      public void addFirst(E e) {
170 <        addBefore(e, header.next);
170 >        addBefore(e, header.next);
171      }
172  
173      /**
174 <     * Appends the given element to the end of this list.  (Identical in
175 <     * function to the <tt>add</tt> method; included only for consistency.)
174 >     * Appends the specified element to the end of this list.
175 >     *
176 >     * <p>This method is equivalent to {@link #add}.
177       *
178 <     * @param e the element to be inserted at the end of this list
178 >     * @param e the element to add
179       */
180      public void addLast(E e) {
181 <        addBefore(e, header);
181 >        addBefore(e, header);
182      }
183  
184      /**
# Line 181 | Line 200 | public class LinkedList<E>
200       * @return the number of elements in this list
201       */
202      public int size() {
203 <        return size;
203 >        return size;
204      }
205  
206      /**
207       * Appends the specified element to the end of this list.
208       *
209 +     * <p>This method is equivalent to {@link #addLast}.
210 +     *
211       * @param e element to be appended to this list
212 <     * @return <tt>true</tt> (as per the spec for {@link Collection#add})
212 >     * @return <tt>true</tt> (as specified by {@link Collection#add})
213       */
214      public boolean add(E e) {
215 <        addBefore(e, header);
215 >        addBefore(e, header);
216          return true;
217      }
218  
# Line 232 | Line 253 | public class LinkedList<E>
253       * this list, in the order that they are returned by the specified
254       * collection's iterator.  The behavior of this operation is undefined if
255       * the specified collection is modified while the operation is in
256 <     * progress.  (This implies that the behavior of this call is undefined if
257 <     * the specified Collection is this list, and this list is nonempty.)
256 >     * progress.  (Note that this will occur if the specified collection is
257 >     * this list, and it's nonempty.)
258       *
259       * @param c collection containing elements to be added to this list
260       * @return <tt>true</tt> if this list changed as a result of the call
# Line 266 | Line 287 | public class LinkedList<E>
287          int numNew = a.length;
288          if (numNew==0)
289              return false;
290 <        modCount++;
290 >        modCount++;
291  
292          Entry<E> successor = (index==size ? header : entry(index));
293          Entry<E> predecessor = successor.previous;
294 <        for (int i=0; i<numNew; i++) {
294 >        for (int i=0; i<numNew; i++) {
295              Entry<E> e = new Entry<E>((E)a[i], successor, predecessor);
296              predecessor.next = e;
297              predecessor = e;
# Line 294 | Line 315 | public class LinkedList<E>
315          }
316          header.next = header.previous = header;
317          size = 0;
318 <        modCount++;
318 >        modCount++;
319      }
320  
321  
# Line 481 | Line 502 | public class LinkedList<E>
502       * Adds the specified element as the tail (last element) of this list.
503       *
504       * @param e the element to add
505 <     * @return <tt>true</tt> (as per the spec for {@link Queue#offer})
505 >     * @return <tt>true</tt> (as specified by {@link Queue#offer})
506       * @since 1.5
507       */
508      public boolean offer(E e) {
# Line 493 | Line 514 | public class LinkedList<E>
514       * Inserts the specified element at the front of this list.
515       *
516       * @param e the element to insert
517 <     * @return <tt>true</tt> (as per the spec for {@link Deque#offerFirst})
517 >     * @return <tt>true</tt> (as specified by {@link Deque#offerFirst})
518       * @since 1.6
519       */
520      public boolean offerFirst(E e) {
# Line 505 | Line 526 | public class LinkedList<E>
526       * Inserts the specified element at the end of this list.
527       *
528       * @param e the element to insert
529 <     * @return <tt>true</tt> (as per the spec for {@link Deque#offerLast})
529 >     * @return <tt>true</tt> (as specified by {@link Deque#offerLast})
530       * @since 1.6
531       */
532      public boolean offerLast(E e) {
# Line 542 | Line 563 | public class LinkedList<E>
563      }
564  
565      /**
566 <     * Retrieves and removes the first element of this list, or
567 <     * <tt>null</tt> if this list is empty.
566 >     * Retrieves and removes the first element of this list,
567 >     * or returns <tt>null</tt> if this list is empty.
568       *
569       * @return the first element of this list, or <tt>null</tt> if
570       *     this list is empty
# Line 556 | Line 577 | public class LinkedList<E>
577      }
578  
579      /**
580 <     * Retrieves and removes the last element of this list, or
581 <     * <tt>null</tt> if this list is empty.
580 >     * Retrieves and removes the last element of this list,
581 >     * or returns <tt>null</tt> if this list is empty.
582       *
583       * @return the last element of this list, or <tt>null</tt> if
584       *     this list is empty
# Line 621 | Line 642 | public class LinkedList<E>
642       */
643      public boolean removeLastOccurrence(Object o) {
644          if (o==null) {
645 <            for (Entry e = header.previous; e != header; e = e.previous) {
645 >            for (Entry<E> e = header.previous; e != header; e = e.previous) {
646                  if (e.element==null) {
647                      remove(e);
648                      return true;
649                  }
650              }
651          } else {
652 <            for (Entry e = header.previous; e != header; e = e.previous) {
652 >            for (Entry<E> e = header.previous; e != header; e = e.previous) {
653                  if (o.equals(e.element)) {
654                      remove(e);
655                      return true;
# Line 660 | Line 681 | public class LinkedList<E>
681       * @see List#listIterator(int)
682       */
683      public ListIterator<E> listIterator(int index) {
684 <        return new ListItr(index);
684 >        return new ListItr(index);
685      }
686  
687      private class ListItr implements ListIterator<E> {
688 <        private Entry<E> lastReturned = header;
689 <        private Entry<E> next;
690 <        private int nextIndex;
691 <        private int expectedModCount = modCount;
692 <
693 <        ListItr(int index) {
694 <            if (index < 0 || index > size)
695 <                throw new IndexOutOfBoundsException("Index: "+index+
696 <                                                    ", Size: "+size);
697 <            if (index < (size >> 1)) {
698 <                next = header.next;
699 <                for (nextIndex=0; nextIndex<index; nextIndex++)
700 <                    next = next.next;
701 <            } else {
702 <                next = header;
703 <                for (nextIndex=size; nextIndex>index; nextIndex--)
704 <                    next = next.previous;
705 <            }
706 <        }
707 <
708 <        public boolean hasNext() {
709 <            return nextIndex != size;
710 <        }
711 <
712 <        public E next() {
713 <            checkForComodification();
714 <            if (nextIndex == size)
715 <                throw new NoSuchElementException();
695 <
696 <            lastReturned = next;
697 <            next = next.next;
698 <            nextIndex++;
699 <            return lastReturned.element;
700 <        }
701 <
702 <        public boolean hasPrevious() {
703 <            return nextIndex != 0;
704 <        }
705 <
706 <        public E previous() {
707 <            if (nextIndex == 0)
708 <                throw new NoSuchElementException();
709 <
710 <            lastReturned = next = next.previous;
711 <            nextIndex--;
712 <            checkForComodification();
713 <            return lastReturned.element;
714 <        }
715 <
716 <        public int nextIndex() {
717 <            return nextIndex;
718 <        }
719 <
720 <        public int previousIndex() {
721 <            return nextIndex-1;
722 <        }
688 >        private Entry<E> lastReturned = header;
689 >        private Entry<E> next;
690 >        private int nextIndex;
691 >        private int expectedModCount = modCount;
692 >
693 >        ListItr(int index) {
694 >            if (index < 0 || index > size)
695 >                throw new IndexOutOfBoundsException("Index: "+index+
696 >                                                    ", Size: "+size);
697 >            if (index < (size >> 1)) {
698 >                next = header.next;
699 >                for (nextIndex=0; nextIndex<index; nextIndex++)
700 >                    next = next.next;
701 >            } else {
702 >                next = header;
703 >                for (nextIndex=size; nextIndex>index; nextIndex--)
704 >                    next = next.previous;
705 >            }
706 >        }
707 >
708 >        public boolean hasNext() {
709 >            return nextIndex != size;
710 >        }
711 >
712 >        public E next() {
713 >            checkForComodification();
714 >            if (nextIndex == size)
715 >                throw new NoSuchElementException();
716  
717 <        public void remove() {
717 >            lastReturned = next;
718 >            next = next.next;
719 >            nextIndex++;
720 >            return lastReturned.element;
721 >        }
722 >
723 >        public boolean hasPrevious() {
724 >            return nextIndex != 0;
725 >        }
726 >
727 >        public E previous() {
728 >            if (nextIndex == 0)
729 >                throw new NoSuchElementException();
730 >
731 >            lastReturned = next = next.previous;
732 >            nextIndex--;
733 >            checkForComodification();
734 >            return lastReturned.element;
735 >        }
736 >
737 >        public int nextIndex() {
738 >            return nextIndex;
739 >        }
740 >
741 >        public int previousIndex() {
742 >            return nextIndex-1;
743 >        }
744 >
745 >        public void remove() {
746              checkForComodification();
747              Entry<E> lastNext = lastReturned.next;
748              try {
# Line 729 | Line 750 | public class LinkedList<E>
750              } catch (NoSuchElementException e) {
751                  throw new IllegalStateException();
752              }
753 <            if (next==lastReturned)
753 >            if (next==lastReturned)
754                  next = lastNext;
755              else
756 <                nextIndex--;
757 <            lastReturned = header;
758 <            expectedModCount++;
759 <        }
760 <
761 <        public void set(E e) {
762 <            if (lastReturned == header)
763 <                throw new IllegalStateException();
764 <            checkForComodification();
765 <            lastReturned.element = e;
766 <        }
767 <
768 <        public void add(E e) {
769 <            checkForComodification();
770 <            lastReturned = header;
771 <            addBefore(e, next);
772 <            nextIndex++;
773 <            expectedModCount++;
774 <        }
775 <
776 <        final void checkForComodification() {
777 <            if (modCount != expectedModCount)
778 <                throw new ConcurrentModificationException();
779 <        }
756 >                nextIndex--;
757 >            lastReturned = header;
758 >            expectedModCount++;
759 >        }
760 >
761 >        public void set(E e) {
762 >            if (lastReturned == header)
763 >                throw new IllegalStateException();
764 >            checkForComodification();
765 >            lastReturned.element = e;
766 >        }
767 >
768 >        public void add(E e) {
769 >            checkForComodification();
770 >            lastReturned = header;
771 >            addBefore(e, next);
772 >            nextIndex++;
773 >            expectedModCount++;
774 >        }
775 >
776 >        final void checkForComodification() {
777 >            if (modCount != expectedModCount)
778 >                throw new ConcurrentModificationException();
779 >        }
780      }
781  
782      private static class Entry<E> {
783 <        E element;
784 <        Entry<E> next;
785 <        Entry<E> previous;
786 <
787 <        Entry(E element, Entry<E> next, Entry<E> previous) {
788 <            this.element = element;
789 <            this.next = next;
790 <            this.previous = previous;
791 <        }
783 >        E element;
784 >        Entry<E> next;
785 >        Entry<E> previous;
786 >
787 >        Entry(E element, Entry<E> next, Entry<E> previous) {
788 >            this.element = element;
789 >            this.next = next;
790 >            this.previous = previous;
791 >        }
792      }
793  
794      private Entry<E> addBefore(E e, Entry<E> entry) {
795 <        Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
796 <        newEntry.previous.next = newEntry;
797 <        newEntry.next.previous = newEntry;
798 <        size++;
799 <        modCount++;
800 <        return newEntry;
795 >        Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
796 >        newEntry.previous.next = newEntry;
797 >        newEntry.next.previous = newEntry;
798 >        size++;
799 >        modCount++;
800 >        return newEntry;
801      }
802  
803      private E remove(Entry<E> e) {
804 <        if (e == header)
805 <            throw new NoSuchElementException();
804 >        if (e == header)
805 >            throw new NoSuchElementException();
806  
807          E result = e.element;
808 <        e.previous.next = e.next;
809 <        e.next.previous = e.previous;
808 >        e.previous.next = e.next;
809 >        e.next.previous = e.previous;
810          e.next = e.previous = null;
811          e.element = null;
812 <        size--;
813 <        modCount++;
812 >        size--;
813 >        modCount++;
814          return result;
815      }
816  
817      /**
818 +     * @since 1.6
819 +     */
820 +    public Iterator<E> descendingIterator() {
821 +        return new DescendingIterator();
822 +    }
823 +
824 +    /** Adapter to provide descending iterators via ListItr.previous */
825 +    private class DescendingIterator implements Iterator {
826 +        final ListItr itr = new ListItr(size());
827 +        public boolean hasNext() {
828 +            return itr.hasPrevious();
829 +        }
830 +        public E next() {
831 +            return itr.previous();
832 +        }
833 +        public void remove() {
834 +            itr.remove();
835 +        }
836 +    }
837 +
838 +    /**
839       * Returns a shallow copy of this <tt>LinkedList</tt>. (The elements
840       * themselves are not cloned.)
841       *
# Line 801 | Line 843 | public class LinkedList<E>
843       */
844      public Object clone() {
845          LinkedList<E> clone = null;
846 <        try {
847 <            clone = (LinkedList<E>) super.clone();
848 <        } catch (CloneNotSupportedException e) {
849 <            throw new InternalError();
850 <        }
846 >        try {
847 >            clone = (LinkedList<E>) super.clone();
848 >        } catch (CloneNotSupportedException e) {
849 >            throw new InternalError();
850 >        }
851  
852          // Put clone into "virgin" state
853          clone.header = new Entry<E>(null, null, null);
# Line 835 | Line 877 | public class LinkedList<E>
877       *         in proper sequence
878       */
879      public Object[] toArray() {
880 <        Object[] result = new Object[size];
880 >        Object[] result = new Object[size];
881          int i = 0;
882          for (Entry<E> e = header.next; e != header; e = e.next)
883              result[i++] = e.element;
884 <        return result;
884 >        return result;
885      }
886  
887      /**
# Line 885 | Line 927 | public class LinkedList<E>
927              a = (T[])java.lang.reflect.Array.newInstance(
928                                  a.getClass().getComponentType(), size);
929          int i = 0;
930 <        Object[] result = a;
930 >        Object[] result = a;
931          for (Entry<E> e = header.next; e != header; e = e.next)
932              result[i++] = e.element;
933  
# Line 907 | Line 949 | public class LinkedList<E>
949       */
950      private void writeObject(java.io.ObjectOutputStream s)
951          throws java.io.IOException {
952 <        // Write out any hidden serialization magic
953 <        s.defaultWriteObject();
952 >        // Write out any hidden serialization magic
953 >        s.defaultWriteObject();
954  
955          // Write out size
956          s.writeInt(size);
957  
958 <        // Write out all elements in the proper order.
958 >        // Write out all elements in the proper order.
959          for (Entry e = header.next; e != header; e = e.next)
960              s.writeObject(e.element);
961      }
# Line 924 | Line 966 | public class LinkedList<E>
966       */
967      private void readObject(java.io.ObjectInputStream s)
968          throws java.io.IOException, ClassNotFoundException {
969 <        // Read in any hidden serialization magic
970 <        s.defaultReadObject();
969 >        // Read in any hidden serialization magic
970 >        s.defaultReadObject();
971  
972          // Read in size
973          int size = s.readInt();
# Line 934 | Line 976 | public class LinkedList<E>
976          header = new Entry<E>(null, null, null);
977          header.next = header.previous = header;
978  
979 <        // Read in all elements in the proper order.
980 <        for (int i=0; i<size; i++)
979 >        // Read in all elements in the proper order.
980 >        for (int i=0; i<size; i++)
981              addBefore((E)s.readObject(), header);
982      }
983   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines