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

Comparing jsr166/src/main/java/util/ArrayDeque.java (file contents):
Revision 1.12 by jsr166, Tue May 17 16:14:34 2005 UTC vs.
Revision 1.33 by jsr166, Fri Jun 10 00:20:44 2011 UTC

# Line 1 | Line 1
1   /*
2   * Written by Josh Bloch of Google Inc. and released to the public domain,
3 < * as explained at http://creativecommons.org/licenses/publicdomain.
3 > * as explained at http://creativecommons.org/publicdomain/zero/1.0/.
4   */
5  
6   package java.util;
7 import java.io.*;
7  
8   /**
9   * Resizable-array implementation of the {@link Deque} interface.  Array
# Line 44 | Line 43 | import java.io.*;
43   * Iterator} interfaces.
44   *
45   * <p>This class is a member of the
46 < * <a href="{@docRoot}/../guide/collections/index.html">
46 > * <a href="{@docRoot}/../technotes/guides/collections/index.html">
47   * Java Collections Framework</a>.
48   *
49   * @author  Josh Bloch and Doug Lea
# Line 52 | Line 51 | import java.io.*;
51   * @param <E> the type of elements held in this collection
52   */
53   public class ArrayDeque<E> extends AbstractCollection<E>
54 <                           implements Deque<E>, Cloneable, Serializable
54 >                           implements Deque<E>, Cloneable, java.io.Serializable
55   {
56      /**
57       * The array in which the elements of the deque are stored.
# Line 202 | Line 201 | public class ArrayDeque<E> extends Abstr
201  
202      /**
203       * Inserts the specified element at the end of this deque.
204 <     * This method is equivalent to {@link #add} and {@link #push}.
204 >     *
205 >     * <p>This method is equivalent to {@link #add}.
206       *
207       * @param e the element to add
208       * @throws NullPointerException if the specified element is null
# Line 219 | Line 219 | public class ArrayDeque<E> extends Abstr
219       * Inserts the specified element at the front of this deque.
220       *
221       * @param e the element to add
222 <     * @return <tt>true</tt> (as per the spec for {@link Deque#offerFirst})
222 >     * @return <tt>true</tt> (as specified by {@link Deque#offerFirst})
223       * @throws NullPointerException if the specified element is null
224       */
225      public boolean offerFirst(E e) {
# Line 231 | Line 231 | public class ArrayDeque<E> extends Abstr
231       * Inserts the specified element at the end of this deque.
232       *
233       * @param e the element to add
234 <     * @return <tt>true</tt> (as per the spec for {@link Deque#offerLast})
234 >     * @return <tt>true</tt> (as specified by {@link Deque#offerLast})
235       * @throws NullPointerException if the specified element is null
236       */
237      public boolean offerLast(E e) {
# Line 371 | Line 371 | public class ArrayDeque<E> extends Abstr
371       * <p>This method is equivalent to {@link #addLast}.
372       *
373       * @param e the element to add
374 <     * @return <tt>true</tt> (as per the spec for {@link Collection#add})
374 >     * @return <tt>true</tt> (as specified by {@link Collection#add})
375       * @throws NullPointerException if the specified element is null
376       */
377      public boolean add(E e) {
# Line 385 | Line 385 | public class ArrayDeque<E> extends Abstr
385       * <p>This method is equivalent to {@link #offerLast}.
386       *
387       * @param e the element to add
388 <     * @return <tt>true</tt> (as per the spec for {@link Queue#offer})
388 >     * @return <tt>true</tt> (as specified by {@link Queue#offer})
389       * @throws NullPointerException if the specified element is null
390       */
391      public boolean offer(E e) {
# Line 394 | Line 394 | public class ArrayDeque<E> extends Abstr
394  
395      /**
396       * Retrieves and removes the head of the queue represented by this deque.
397 <     * This method differs from {@link #poll} only in that it throws an
397 >     *
398 >     * This method differs from {@link #poll poll} only in that it throws an
399       * exception if this deque is empty.
400       *
401       * <p>This method is equivalent to {@link #removeFirst}.
# Line 422 | Line 423 | public class ArrayDeque<E> extends Abstr
423  
424      /**
425       * Retrieves, but does not remove, the head of the queue represented by
426 <     * this deque.  This method differs from {@link #peek} only in that it
427 <     * throws an exception if this deque is empty.
426 >     * this deque.  This method differs from {@link #peek peek} only in
427 >     * that it throws an exception if this deque is empty.
428       *
429       * <p>This method is equivalent to {@link #getFirst}.
430       *
# Line 476 | Line 477 | public class ArrayDeque<E> extends Abstr
477          return removeFirst();
478      }
479  
480 +    private void checkInvariants() {
481 +        assert elements[tail] == null;
482 +        assert head == tail ? elements[head] == null :
483 +            (elements[head] != null &&
484 +             elements[(tail - 1) & (elements.length - 1)] != null);
485 +        assert elements[(head - 1) & (elements.length - 1)] == null;
486 +    }
487 +
488      /**
489       * Removes the element at the specified position in the elements array,
490       * adjusting head and tail as necessary.  This can result in motion of
# Line 487 | Line 496 | public class ArrayDeque<E> extends Abstr
496       * @return true if elements moved backwards
497       */
498      private boolean delete(int i) {
499 <        int mask = elements.length - 1;
500 <
501 <        // Invariant: head <= i < tail mod circularity
502 <        if (((i - head) & mask) >= ((tail - head) & mask))
503 <            throw new ConcurrentModificationException();
504 <
505 <        // Case 1: Deque doesn't wrap
506 <        // Case 2: Deque does wrap and removed element is in the head portion
507 <        if (i >= head) {
508 <            System.arraycopy(elements, head, elements, head + 1, i - head);
509 <            elements[head] = null;
510 <            head = (head + 1) & mask;
499 >        checkInvariants();
500 >        final E[] elements = this.elements;
501 >        final int mask = elements.length - 1;
502 >        final int h = head;
503 >        final int t = tail;
504 >        final int front = (i - h) & mask;
505 >        final int back  = (t - i) & mask;
506 >
507 >        // Invariant: head <= i < tail mod circularity
508 >        if (front >= ((t - h) & mask))
509 >            throw new ConcurrentModificationException();
510 >
511 >        // Optimize for least element motion
512 >        if (front < back) {
513 >            if (h <= i) {
514 >                System.arraycopy(elements, h, elements, h + 1, front);
515 >            } else { // Wrap around
516 >                System.arraycopy(elements, 0, elements, 1, i);
517 >                elements[0] = elements[mask];
518 >                System.arraycopy(elements, h, elements, h + 1, mask - h);
519 >            }
520 >            elements[h] = null;
521 >            head = (h + 1) & mask;
522              return false;
523 +        } else {
524 +            if (i < t) { // Copy the null tail as well
525 +                System.arraycopy(elements, i + 1, elements, i, back);
526 +                tail = t - 1;
527 +            } else { // Wrap around
528 +                System.arraycopy(elements, i + 1, elements, i, mask - i);
529 +                elements[mask] = elements[0];
530 +                System.arraycopy(elements, 1, elements, 0, t);
531 +                tail = (t - 1) & mask;
532 +            }
533 +            return true;
534          }
504
505        // Case 3: Deque wraps and removed element is in the tail portion
506        tail--;
507        System.arraycopy(elements, i + 1, elements, i, tail - i);
508        elements[tail] = null;
509        return true;
535      }
536  
537      // *** Collection Methods ***
# Line 535 | Line 560 | public class ArrayDeque<E> extends Abstr
560       * order that elements would be dequeued (via successive calls to
561       * {@link #remove} or popped (via successive calls to {@link #pop}).
562       *
563 <     * @return an <tt>Iterator</tt> over the elements in this deque
563 >     * @return an iterator over the elements in this deque
564       */
565      public Iterator<E> iterator() {
566          return new DeqIterator();
567      }
568  
569 +    public Iterator<E> descendingIterator() {
570 +        return new DescendingIterator();
571 +    }
572 +
573      private class DeqIterator implements Iterator<E> {
574          /**
575           * Index of element to be returned by subsequent call to next.
# Line 564 | Line 593 | public class ArrayDeque<E> extends Abstr
593          }
594  
595          public E next() {
567            E result;
596              if (cursor == fence)
597                  throw new NoSuchElementException();
598 +            E result = elements[cursor];
599              // This check doesn't catch all possible comodifications,
600              // but does catch the ones that corrupt traversal
601 <            if (tail != fence || (result = elements[cursor]) == null)
601 >            if (tail != fence || result == null)
602                  throw new ConcurrentModificationException();
603              lastRet = cursor;
604              cursor = (cursor + 1) & (elements.length - 1);
# Line 579 | Line 608 | public class ArrayDeque<E> extends Abstr
608          public void remove() {
609              if (lastRet < 0)
610                  throw new IllegalStateException();
611 <            if (delete(lastRet))
612 <                cursor--;
611 >            if (delete(lastRet)) { // if left-shifted, undo increment in next()
612 >                cursor = (cursor - 1) & (elements.length - 1);
613 >                fence = tail;
614 >            }
615 >            lastRet = -1;
616 >        }
617 >    }
618 >
619 >    private class DescendingIterator implements Iterator<E> {
620 >        /*
621 >         * This class is nearly a mirror-image of DeqIterator, using
622 >         * tail instead of head for initial cursor, and head instead of
623 >         * tail for fence.
624 >         */
625 >        private int cursor = tail;
626 >        private int fence = head;
627 >        private int lastRet = -1;
628 >
629 >        public boolean hasNext() {
630 >            return cursor != fence;
631 >        }
632 >
633 >        public E next() {
634 >            if (cursor == fence)
635 >                throw new NoSuchElementException();
636 >            cursor = (cursor - 1) & (elements.length - 1);
637 >            E result = elements[cursor];
638 >            if (head != fence || result == null)
639 >                throw new ConcurrentModificationException();
640 >            lastRet = cursor;
641 >            return result;
642 >        }
643 >
644 >        public void remove() {
645 >            if (lastRet < 0)
646 >                throw new IllegalStateException();
647 >            if (!delete(lastRet)) {
648 >                cursor = (cursor + 1) & (elements.length - 1);
649 >                fence = head;
650 >            }
651              lastRet = -1;
585            fence = tail;
652          }
653      }
654  
# Line 650 | Line 716 | public class ArrayDeque<E> extends Abstr
716       * <p>The returned array will be "safe" in that no references to it are
717       * maintained by this deque.  (In other words, this method must allocate
718       * a new array).  The caller is thus free to modify the returned array.
719 <     *
719 >     *
720       * <p>This method acts as bridge between array-based and collection-based
721       * APIs.
722       *
723       * @return an array containing all of the elements in this deque
724       */
725      public Object[] toArray() {
726 <        return copyElements(new Object[size()]);
726 >        return copyElements(new Object[size()]);
727      }
728  
729      /**
# Line 682 | Line 748 | public class ArrayDeque<E> extends Abstr
748       * The following code can be used to dump the deque into a newly
749       * allocated array of <tt>String</tt>:
750       *
751 <     * <pre>
686 <     *     String[] y = x.toArray(new String[0]);</pre>
751 >     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
752       *
753       * Note that <tt>toArray(new Object[0])</tt> is identical in function to
754       * <tt>toArray()</tt>.
# Line 702 | Line 767 | public class ArrayDeque<E> extends Abstr
767          if (a.length < size)
768              a = (T[])java.lang.reflect.Array.newInstance(
769                      a.getClass().getComponentType(), size);
770 <        copyElements(a);
770 >        copyElements(a);
771          if (a.length > size)
772              a[size] = null;
773          return a;
# Line 718 | Line 783 | public class ArrayDeque<E> extends Abstr
783      public ArrayDeque<E> clone() {
784          try {
785              ArrayDeque<E> result = (ArrayDeque<E>) super.clone();
786 <            // These two lines are currently faster than cloning the array:
722 <            result.elements = (E[]) new Object[elements.length];
723 <            System.arraycopy(elements, 0, result.elements, 0, elements.length);
786 >            result.elements = Arrays.copyOf(elements, elements.length);
787              return result;
788  
789          } catch (CloneNotSupportedException e) {
# Line 740 | Line 803 | public class ArrayDeque<E> extends Abstr
803       * followed by all of its elements (each an object reference) in
804       * first-to-last order.
805       */
806 <    private void writeObject(ObjectOutputStream s) throws IOException {
806 >    private void writeObject(java.io.ObjectOutputStream s)
807 >            throws java.io.IOException {
808          s.defaultWriteObject();
809  
810          // Write out size
811 <        int size = size();
748 <        s.writeInt(size);
811 >        s.writeInt(size());
812  
813          // Write out elements in order.
751        int i = head;
814          int mask = elements.length - 1;
815 <        for (int j = 0; j < size; j++) {
815 >        for (int i = head; i != tail; i = (i + 1) & mask)
816              s.writeObject(elements[i]);
755            i = (i + 1) & mask;
756        }
817      }
818  
819      /**
820       * Deserialize this deque.
821       */
822 <    private void readObject(ObjectInputStream s)
823 <            throws IOException, ClassNotFoundException {
822 >    private void readObject(java.io.ObjectInputStream s)
823 >            throws java.io.IOException, ClassNotFoundException {
824          s.defaultReadObject();
825  
826          // Read in size and allocate array
# Line 772 | Line 832 | public class ArrayDeque<E> extends Abstr
832          // Read in all elements in the proper order.
833          for (int i = 0; i < size; i++)
834              elements[i] = (E)s.readObject();
775
835      }
836   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines