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.9 by jsr166, Mon May 16 06:16:12 2005 UTC vs.
Revision 1.37 by jsr166, Tue Dec 6 04:37:55 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 64 | Line 63 | public class ArrayDeque<E> extends Abstr
63       * other.  We also guarantee that all array cells not holding
64       * deque elements are always null.
65       */
66 <    private transient E[] elements;
66 >    private transient Object[] elements;
67  
68      /**
69       * The index of the element at the head of the deque (which is the
# Line 108 | Line 107 | public class ArrayDeque<E> extends Abstr
107              if (initialCapacity < 0)   // Too many elements, must back off
108                  initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
109          }
110 <        elements = (E[]) new Object[initialCapacity];
110 >        elements = new Object[initialCapacity];
111      }
112  
113      /**
# Line 126 | Line 125 | public class ArrayDeque<E> extends Abstr
125          Object[] a = new Object[newCapacity];
126          System.arraycopy(elements, p, a, 0, r);
127          System.arraycopy(elements, 0, a, r, p);
128 <        elements = (E[])a;
128 >        elements = a;
129          head = 0;
130          tail = n;
131      }
# Line 154 | Line 153 | public class ArrayDeque<E> extends Abstr
153       * sufficient to hold 16 elements.
154       */
155      public ArrayDeque() {
156 <        elements = (E[]) new Object[16];
156 >        elements = new Object[16];
157      }
158  
159      /**
# 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 261 | Line 261 | public class ArrayDeque<E> extends Abstr
261  
262      public E pollFirst() {
263          int h = head;
264 <        E result = elements[h]; // Element is null if deque empty
264 >        @SuppressWarnings("unchecked")
265 >        E result = (E) elements[h];
266 >        // Element is null if deque empty
267          if (result == null)
268              return null;
269          elements[h] = null;     // Must null out slot
# Line 271 | Line 273 | public class ArrayDeque<E> extends Abstr
273  
274      public E pollLast() {
275          int t = (tail - 1) & (elements.length - 1);
276 <        E result = elements[t];
276 >        @SuppressWarnings("unchecked")
277 >        E result = (E) elements[t];
278          if (result == null)
279              return null;
280          elements[t] = null;
# Line 283 | Line 286 | public class ArrayDeque<E> extends Abstr
286       * @throws NoSuchElementException {@inheritDoc}
287       */
288      public E getFirst() {
289 <        E x = elements[head];
290 <        if (x == null)
289 >        @SuppressWarnings("unchecked")
290 >        E result = (E) elements[head];
291 >        if (result == null)
292              throw new NoSuchElementException();
293 <        return x;
293 >        return result;
294      }
295  
296      /**
297       * @throws NoSuchElementException {@inheritDoc}
298       */
299      public E getLast() {
300 <        E x = elements[(tail - 1) & (elements.length - 1)];
301 <        if (x == null)
300 >        @SuppressWarnings("unchecked")
301 >        E result = (E) elements[(tail - 1) & (elements.length - 1)];
302 >        if (result == null)
303              throw new NoSuchElementException();
304 <        return x;
304 >        return result;
305      }
306  
307 +    @SuppressWarnings("unchecked")
308      public E peekFirst() {
309 <        return elements[head]; // elements[head] is null if deque empty
309 >        // elements[head] is null if deque empty
310 >        return (E) elements[head];
311      }
312  
313 +    @SuppressWarnings("unchecked")
314      public E peekLast() {
315 <        return elements[(tail - 1) & (elements.length - 1)];
315 >        return (E) elements[(tail - 1) & (elements.length - 1)];
316      }
317  
318      /**
# Line 313 | Line 321 | public class ArrayDeque<E> extends Abstr
321       * If the deque does not contain the element, it is unchanged.
322       * More formally, removes the first element <tt>e</tt> such that
323       * <tt>o.equals(e)</tt> (if such an element exists).
324 <     * Returns true if this deque contained the specified element (or
325 <     * equivalently, if this deque changed as a result of the call).
324 >     * Returns <tt>true</tt> if this deque contained the specified element
325 >     * (or equivalently, if this deque changed as a result of the call).
326       *
327       * @param o element to be removed from this deque, if present
328       * @return <tt>true</tt> if the deque contained the specified element
# Line 324 | Line 332 | public class ArrayDeque<E> extends Abstr
332              return false;
333          int mask = elements.length - 1;
334          int i = head;
335 <        E x;
335 >        Object x;
336          while ( (x = elements[i]) != null) {
337              if (o.equals(x)) {
338                  delete(i);
# Line 341 | Line 349 | public class ArrayDeque<E> extends Abstr
349       * If the deque does not contain the element, it is unchanged.
350       * More formally, removes the last element <tt>e</tt> such that
351       * <tt>o.equals(e)</tt> (if such an element exists).
352 <     * Returns true if this deque contained the specified element (or
353 <     * equivalently, if this deque changed as a result of the call).
352 >     * Returns <tt>true</tt> if this deque contained the specified element
353 >     * (or equivalently, if this deque changed as a result of the call).
354       *
355       * @param o element to be removed from this deque, if present
356       * @return <tt>true</tt> if the deque contained the specified element
# Line 352 | Line 360 | public class ArrayDeque<E> extends Abstr
360              return false;
361          int mask = elements.length - 1;
362          int i = (tail - 1) & mask;
363 <        E x;
363 >        Object x;
364          while ( (x = elements[i]) != null) {
365              if (o.equals(x)) {
366                  delete(i);
# Line 371 | Line 379 | public class ArrayDeque<E> extends Abstr
379       * <p>This method is equivalent to {@link #addLast}.
380       *
381       * @param e the element to add
382 <     * @return <tt>true</tt> (as per the spec for {@link Collection#add})
382 >     * @return <tt>true</tt> (as specified by {@link Collection#add})
383       * @throws NullPointerException if the specified element is null
384       */
385      public boolean add(E e) {
# Line 385 | Line 393 | public class ArrayDeque<E> extends Abstr
393       * <p>This method is equivalent to {@link #offerLast}.
394       *
395       * @param e the element to add
396 <     * @return <tt>true</tt> (as per the spec for {@link Queue#offer})
396 >     * @return <tt>true</tt> (as specified by {@link Queue#offer})
397       * @throws NullPointerException if the specified element is null
398       */
399      public boolean offer(E e) {
# Line 394 | Line 402 | public class ArrayDeque<E> extends Abstr
402  
403      /**
404       * Retrieves and removes the head of the queue represented by this deque.
405 <     * This method differs from {@link #poll} only in that it throws an
405 >     *
406 >     * This method differs from {@link #poll poll} only in that it throws an
407       * exception if this deque is empty.
408       *
409       * <p>This method is equivalent to {@link #removeFirst}.
# Line 422 | Line 431 | public class ArrayDeque<E> extends Abstr
431  
432      /**
433       * Retrieves, but does not remove, the head of the queue represented by
434 <     * this deque.  This method differs from {@link #peek} only in that it
435 <     * throws an exception if this deque is empty.
434 >     * this deque.  This method differs from {@link #peek peek} only in
435 >     * that it throws an exception if this deque is empty.
436       *
437       * <p>This method is equivalent to {@link #getFirst}.
438       *
# Line 476 | Line 485 | public class ArrayDeque<E> extends Abstr
485          return removeFirst();
486      }
487  
488 +    private void checkInvariants() {
489 +        assert elements[tail] == null;
490 +        assert head == tail ? elements[head] == null :
491 +            (elements[head] != null &&
492 +             elements[(tail - 1) & (elements.length - 1)] != null);
493 +        assert elements[(head - 1) & (elements.length - 1)] == null;
494 +    }
495 +
496      /**
497       * Removes the element at the specified position in the elements array,
498       * adjusting head and tail as necessary.  This can result in motion of
# Line 487 | Line 504 | public class ArrayDeque<E> extends Abstr
504       * @return true if elements moved backwards
505       */
506      private boolean delete(int i) {
507 <        int mask = elements.length - 1;
508 <
509 <        // Invariant: head <= i < tail mod circularity
510 <        if (((i - head) & mask) >= ((tail - head) & mask))
511 <            throw new ConcurrentModificationException();
512 <
513 <        // Case 1: Deque doesn't wrap
514 <        // Case 2: Deque does wrap and removed element is in the head portion
515 <        if (i >= head) {
516 <            System.arraycopy(elements, head, elements, head + 1, i - head);
517 <            elements[head] = null;
518 <            head = (head + 1) & mask;
507 >        checkInvariants();
508 >        final Object[] elements = this.elements;
509 >        final int mask = elements.length - 1;
510 >        final int h = head;
511 >        final int t = tail;
512 >        final int front = (i - h) & mask;
513 >        final int back  = (t - i) & mask;
514 >
515 >        // Invariant: head <= i < tail mod circularity
516 >        if (front >= ((t - h) & mask))
517 >            throw new ConcurrentModificationException();
518 >
519 >        // Optimize for least element motion
520 >        if (front < back) {
521 >            if (h <= i) {
522 >                System.arraycopy(elements, h, elements, h + 1, front);
523 >            } else { // Wrap around
524 >                System.arraycopy(elements, 0, elements, 1, i);
525 >                elements[0] = elements[mask];
526 >                System.arraycopy(elements, h, elements, h + 1, mask - h);
527 >            }
528 >            elements[h] = null;
529 >            head = (h + 1) & mask;
530              return false;
531 +        } else {
532 +            if (i < t) { // Copy the null tail as well
533 +                System.arraycopy(elements, i + 1, elements, i, back);
534 +                tail = t - 1;
535 +            } else { // Wrap around
536 +                System.arraycopy(elements, i + 1, elements, i, mask - i);
537 +                elements[mask] = elements[0];
538 +                System.arraycopy(elements, 1, elements, 0, t);
539 +                tail = (t - 1) & mask;
540 +            }
541 +            return true;
542          }
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;
543      }
544  
545      // *** Collection Methods ***
# Line 535 | Line 568 | public class ArrayDeque<E> extends Abstr
568       * order that elements would be dequeued (via successive calls to
569       * {@link #remove} or popped (via successive calls to {@link #pop}).
570       *
571 <     * @return an <tt>Iterator</tt> over the elements in this deque
571 >     * @return an iterator over the elements in this deque
572       */
573      public Iterator<E> iterator() {
574          return new DeqIterator();
575      }
576  
577 +    public Iterator<E> descendingIterator() {
578 +        return new DescendingIterator();
579 +    }
580 +
581      private class DeqIterator implements Iterator<E> {
582          /**
583           * Index of element to be returned by subsequent call to next.
# Line 564 | Line 601 | public class ArrayDeque<E> extends Abstr
601          }
602  
603          public E next() {
567            E result;
604              if (cursor == fence)
605                  throw new NoSuchElementException();
606 +            @SuppressWarnings("unchecked")
607 +            E result = (E) elements[cursor];
608              // This check doesn't catch all possible comodifications,
609              // but does catch the ones that corrupt traversal
610 <            if (tail != fence || (result = elements[cursor]) == null)
610 >            if (tail != fence || result == null)
611                  throw new ConcurrentModificationException();
612              lastRet = cursor;
613              cursor = (cursor + 1) & (elements.length - 1);
# Line 579 | Line 617 | public class ArrayDeque<E> extends Abstr
617          public void remove() {
618              if (lastRet < 0)
619                  throw new IllegalStateException();
620 <            if (delete(lastRet))
621 <                cursor--;
620 >            if (delete(lastRet)) { // if left-shifted, undo increment in next()
621 >                cursor = (cursor - 1) & (elements.length - 1);
622 >                fence = tail;
623 >            }
624 >            lastRet = -1;
625 >        }
626 >    }
627 >
628 >    private class DescendingIterator implements Iterator<E> {
629 >        /*
630 >         * This class is nearly a mirror-image of DeqIterator, using
631 >         * tail instead of head for initial cursor, and head instead of
632 >         * tail for fence.
633 >         */
634 >        private int cursor = tail;
635 >        private int fence = head;
636 >        private int lastRet = -1;
637 >
638 >        public boolean hasNext() {
639 >            return cursor != fence;
640 >        }
641 >
642 >        public E next() {
643 >            if (cursor == fence)
644 >                throw new NoSuchElementException();
645 >            cursor = (cursor - 1) & (elements.length - 1);
646 >            @SuppressWarnings("unchecked")
647 >            E result = (E) elements[cursor];
648 >            if (head != fence || result == null)
649 >                throw new ConcurrentModificationException();
650 >            lastRet = cursor;
651 >            return result;
652 >        }
653 >
654 >        public void remove() {
655 >            if (lastRet < 0)
656 >                throw new IllegalStateException();
657 >            if (!delete(lastRet)) {
658 >                cursor = (cursor + 1) & (elements.length - 1);
659 >                fence = head;
660 >            }
661              lastRet = -1;
585            fence = tail;
662          }
663      }
664  
# Line 599 | Line 675 | public class ArrayDeque<E> extends Abstr
675              return false;
676          int mask = elements.length - 1;
677          int i = head;
678 <        E x;
678 >        Object x;
679          while ( (x = elements[i]) != null) {
680              if (o.equals(x))
681                  return true;
# Line 613 | Line 689 | public class ArrayDeque<E> extends Abstr
689       * If the deque does not contain the element, it is unchanged.
690       * More formally, removes the first element <tt>e</tt> such that
691       * <tt>o.equals(e)</tt> (if such an element exists).
692 <     * Returns true if this deque contained the specified element (or
693 <     * equivalently, if this deque changed as a result of the call).
692 >     * Returns <tt>true</tt> if this deque contained the specified element
693 >     * (or equivalently, if this deque changed as a result of the call).
694       *
695       * <p>This method is equivalent to {@link #removeFirstOccurrence}.
696       *
# Line 645 | Line 721 | public class ArrayDeque<E> extends Abstr
721  
722      /**
723       * Returns an array containing all of the elements in this deque
724 <     * in the correct order.
724 >     * in proper sequence (from first to last element).
725 >     *
726 >     * <p>The returned array will be "safe" in that no references to it are
727 >     * maintained by this deque.  (In other words, this method must allocate
728 >     * a new array).  The caller is thus free to modify the returned array.
729 >     *
730 >     * <p>This method acts as bridge between array-based and collection-based
731 >     * APIs.
732       *
733       * @return an array containing all of the elements in this deque
651     *         in the correct order
734       */
735      public Object[] toArray() {
736 <        return copyElements(new Object[size()]);
736 >        return copyElements(new Object[size()]);
737      }
738  
739      /**
740 <     * Returns an array containing all of the elements in this deque in the
741 <     * correct order; the runtime type of the returned array is that of the
742 <     * specified array.  If the deque fits in the specified array, it is
743 <     * returned therein.  Otherwise, a new array is allocated with the runtime
744 <     * type of the specified array and the size of this deque.
740 >     * Returns an array containing all of the elements in this deque in
741 >     * proper sequence (from first to last element); the runtime type of the
742 >     * returned array is that of the specified array.  If the deque fits in
743 >     * the specified array, it is returned therein.  Otherwise, a new array
744 >     * is allocated with the runtime type of the specified array and the
745 >     * size of this deque.
746 >     *
747 >     * <p>If this deque fits in the specified array with room to spare
748 >     * (i.e., the array has more elements than this deque), the element in
749 >     * the array immediately following the end of the deque is set to
750 >     * <tt>null</tt>.
751 >     *
752 >     * <p>Like the {@link #toArray()} method, this method acts as bridge between
753 >     * array-based and collection-based APIs.  Further, this method allows
754 >     * precise control over the runtime type of the output array, and may,
755 >     * under certain circumstances, be used to save allocation costs.
756 >     *
757 >     * <p>Suppose <tt>x</tt> is a deque known to contain only strings.
758 >     * The following code can be used to dump the deque into a newly
759 >     * allocated array of <tt>String</tt>:
760 >     *
761 >     *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
762       *
763 <     * <p>If the deque fits in the specified array with room to spare (i.e.,
764 <     * the array has more elements than the deque), the element in the array
666 <     * immediately following the end of the collection is set to <tt>null</tt>.
763 >     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
764 >     * <tt>toArray()</tt>.
765       *
766       * @param a the array into which the elements of the deque are to
767       *          be stored, if it is big enough; otherwise, a new array of the
768       *          same runtime type is allocated for this purpose
769 <     * @return an array containing the elements of the deque
770 <     * @throws ArrayStoreException if the runtime type of a is not a supertype
771 <     *         of the runtime type of every element in this deque
769 >     * @return an array containing all of the elements in this deque
770 >     * @throws ArrayStoreException if the runtime type of the specified array
771 >     *         is not a supertype of the runtime type of every element in
772 >     *         this deque
773 >     * @throws NullPointerException if the specified array is null
774       */
775 +    @SuppressWarnings("unchecked")
776      public <T> T[] toArray(T[] a) {
777          int size = size();
778          if (a.length < size)
779              a = (T[])java.lang.reflect.Array.newInstance(
780                      a.getClass().getComponentType(), size);
781 <        copyElements(a);
781 >        copyElements(a);
782          if (a.length > size)
783              a[size] = null;
784          return a;
# Line 692 | Line 793 | public class ArrayDeque<E> extends Abstr
793       */
794      public ArrayDeque<E> clone() {
795          try {
796 +            @SuppressWarnings("unchecked")
797              ArrayDeque<E> result = (ArrayDeque<E>) super.clone();
798 <            // These two lines are currently faster than cloning the array:
697 <            result.elements = (E[]) new Object[elements.length];
698 <            System.arraycopy(elements, 0, result.elements, 0, elements.length);
798 >            result.elements = Arrays.copyOf(elements, elements.length);
799              return result;
700
800          } catch (CloneNotSupportedException e) {
801              throw new AssertionError();
802          }
# Line 715 | Line 814 | public class ArrayDeque<E> extends Abstr
814       * followed by all of its elements (each an object reference) in
815       * first-to-last order.
816       */
817 <    private void writeObject(ObjectOutputStream s) throws IOException {
817 >    private void writeObject(java.io.ObjectOutputStream s)
818 >            throws java.io.IOException {
819          s.defaultWriteObject();
820  
821          // Write out size
822 <        int size = size();
723 <        s.writeInt(size);
822 >        s.writeInt(size());
823  
824          // Write out elements in order.
726        int i = head;
825          int mask = elements.length - 1;
826 <        for (int j = 0; j < size; j++) {
826 >        for (int i = head; i != tail; i = (i + 1) & mask)
827              s.writeObject(elements[i]);
730            i = (i + 1) & mask;
731        }
828      }
829  
830      /**
831       * Deserialize this deque.
832       */
833 <    private void readObject(ObjectInputStream s)
834 <            throws IOException, ClassNotFoundException {
833 >    private void readObject(java.io.ObjectInputStream s)
834 >            throws java.io.IOException, ClassNotFoundException {
835          s.defaultReadObject();
836  
837          // Read in size and allocate array
# Line 746 | Line 842 | public class ArrayDeque<E> extends Abstr
842  
843          // Read in all elements in the proper order.
844          for (int i = 0; i < size; i++)
845 <            elements[i] = (E)s.readObject();
750 <
845 >            elements[i] = s.readObject();
846      }
847   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines