1 7 8 package java.util; 9 import java.io.*; 10 11 56 public class ArrayDeque<E> extends AbstractCollection <E> 57 implements Deque <E>, Cloneable , Serializable 58 { 59 69 private transient E[] elements; 70 71 76 private transient int head; 77 78 82 private transient int tail; 83 84 88 private static final int MIN_INITIAL_CAPACITY = 8; 89 90 92 97 private void allocateElements(int numElements) { 98 int initialCapacity = MIN_INITIAL_CAPACITY; 99 if (numElements >= initialCapacity) { 102 initialCapacity = numElements; 103 initialCapacity |= (initialCapacity >>> 1); 104 initialCapacity |= (initialCapacity >>> 2); 105 initialCapacity |= (initialCapacity >>> 4); 106 initialCapacity |= (initialCapacity >>> 8); 107 initialCapacity |= (initialCapacity >>> 16); 108 initialCapacity++; 109 110 if (initialCapacity < 0) initialCapacity >>>= 1; } 113 elements = (E[]) new Object [initialCapacity]; 114 } 115 116 120 private void doubleCapacity() { 121 assert head == tail; 122 int p = head; 123 int n = elements.length; 124 int r = n - p; int newCapacity = n << 1; 126 if (newCapacity < 0) 127 throw new IllegalStateException ("Sorry, deque too big"); 128 Object [] a = new Object [newCapacity]; 129 System.arraycopy(elements, p, a, 0, r); 130 System.arraycopy(elements, 0, a, r, p); 131 elements = (E[])a; 132 head = 0; 133 tail = n; 134 } 135 136 143 private <T> T[] copyElements(T[] a) { 144 if (head < tail) { 145 System.arraycopy(elements, head, a, 0, size()); 146 } else if (head > tail) { 147 int headPortionLen = elements.length - head; 148 System.arraycopy(elements, head, a, 0, headPortionLen); 149 System.arraycopy(elements, 0, a, headPortionLen, tail); 150 } 151 return a; 152 } 153 154 158 public ArrayDeque() { 159 elements = (E[]) new Object [16]; 160 } 161 162 168 public ArrayDeque(int numElements) { 169 allocateElements(numElements); 170 } 171 172 182 public ArrayDeque(Collection <? extends E> c) { 183 allocateElements(c.size()); 184 addAll(c); 185 } 186 187 191 197 public void addFirst(E e) { 198 if (e == null) 199 throw new NullPointerException (); 200 elements[head = (head - 1) & (elements.length - 1)] = e; 201 if (head == tail) 202 doubleCapacity(); 203 } 204 205 213 public void addLast(E e) { 214 if (e == null) 215 throw new NullPointerException (); 216 elements[tail] = e; 217 if ( (tail = (tail + 1) & (elements.length - 1)) == head) 218 doubleCapacity(); 219 } 220 221 228 public boolean offerFirst(E e) { 229 addFirst(e); 230 return true; 231 } 232 233 240 public boolean offerLast(E e) { 241 addLast(e); 242 return true; 243 } 244 245 248 public E removeFirst() { 249 E x = pollFirst(); 250 if (x == null) 251 throw new NoSuchElementException (); 252 return x; 253 } 254 255 258 public E removeLast() { 259 E x = pollLast(); 260 if (x == null) 261 throw new NoSuchElementException (); 262 return x; 263 } 264 265 public E pollFirst() { 266 int h = head; 267 E result = elements[h]; if (result == null) 269 return null; 270 elements[h] = null; head = (h + 1) & (elements.length - 1); 272 return result; 273 } 274 275 public E pollLast() { 276 int t = (tail - 1) & (elements.length - 1); 277 E result = elements[t]; 278 if (result == null) 279 return null; 280 elements[t] = null; 281 tail = t; 282 return result; 283 } 284 285 288 public E getFirst() { 289 E x = elements[head]; 290 if (x == null) 291 throw new NoSuchElementException (); 292 return x; 293 } 294 295 298 public E getLast() { 299 E x = elements[(tail - 1) & (elements.length - 1)]; 300 if (x == null) 301 throw new NoSuchElementException (); 302 return x; 303 } 304 305 public E peekFirst() { 306 return elements[head]; } 308 309 public E peekLast() { 310 return elements[(tail - 1) & (elements.length - 1)]; 311 } 312 313 325 public boolean removeFirstOccurrence(Object o) { 326 if (o == null) 327 return false; 328 int mask = elements.length - 1; 329 int i = head; 330 E x; 331 while ( (x = elements[i]) != null) { 332 if (o.equals(x)) { 333 delete(i); 334 return true; 335 } 336 i = (i + 1) & mask; 337 } 338 return false; 339 } 340 341 353 public boolean removeLastOccurrence(Object o) { 354 if (o == null) 355 return false; 356 int mask = elements.length - 1; 357 int i = (tail - 1) & mask; 358 E x; 359 while ( (x = elements[i]) != null) { 360 if (o.equals(x)) { 361 delete(i); 362 return true; 363 } 364 i = (i - 1) & mask; 365 } 366 return false; 367 } 368 369 371 380 public boolean add(E e) { 381 addLast(e); 382 return true; 383 } 384 385 394 public boolean offer(E e) { 395 return offerLast(e); 396 } 397 398 409 public E remove() { 410 return removeFirst(); 411 } 412 413 423 public E poll() { 424 return pollFirst(); 425 } 426 427 437 public E element() { 438 return getFirst(); 439 } 440 441 450 public E peek() { 451 return peekFirst(); 452 } 453 454 456 465 public void push(E e) { 466 addFirst(e); 467 } 468 469 479 public E pop() { 480 return removeFirst(); 481 } 482 483 private void checkInvariants() { 484 assert elements[tail] == null; 485 assert head == tail ? elements[head] == null : 486 (elements[head] != null && 487 elements[(tail - 1) & (elements.length - 1)] != null); 488 assert elements[(head - 1) & (elements.length - 1)] == null; 489 } 490 491 501 private boolean delete(int i) { 502 checkInvariants(); 503 final E[] elements = this.elements; 504 final int mask = elements.length - 1; 505 final int h = head; 506 final int t = tail; 507 final int front = (i - h) & mask; 508 final int back = (t - i) & mask; 509 510 if (front >= ((t - h) & mask)) 512 throw new ConcurrentModificationException (); 513 514 if (front < back) { 516 if (h <= i) { 517 System.arraycopy(elements, h, elements, h + 1, front); 518 } else { System.arraycopy(elements, 0, elements, 1, i); 520 elements[0] = elements[mask]; 521 System.arraycopy(elements, h, elements, h + 1, mask - h); 522 } 523 elements[h] = null; 524 head = (h + 1) & mask; 525 return false; 526 } else { 527 if (i < t) { System.arraycopy(elements, i + 1, elements, i, back); 529 tail = t - 1; 530 } else { System.arraycopy(elements, i + 1, elements, i, mask - i); 532 elements[mask] = elements[0]; 533 System.arraycopy(elements, 1, elements, 0, t); 534 tail = (t - 1) & mask; 535 } 536 return true; 537 } 538 } 539 540 542 547 public int size() { 548 return (tail - head) & (elements.length - 1); 549 } 550 551 556 public boolean isEmpty() { 557 return head == tail; 558 } 559 560 568 public Iterator <E> iterator() { 569 return new DeqIterator(); 570 } 571 572 public Iterator <E> descendingIterator() { 573 return new DescendingIterator(); 574 } 575 576 private class DeqIterator implements Iterator <E> { 577 580 private int cursor = head; 581 582 586 private int fence = tail; 587 588 592 private int lastRet = -1; 593 594 public boolean hasNext() { 595 return cursor != fence; 596 } 597 598 public E next() { 599 if (cursor == fence) 600 throw new NoSuchElementException (); 601 E result = elements[cursor]; 602 if (tail != fence || result == null) 605 throw new ConcurrentModificationException (); 606 lastRet = cursor; 607 cursor = (cursor + 1) & (elements.length - 1); 608 return result; 609 } 610 611 public void remove() { 612 if (lastRet < 0) 613 throw new IllegalStateException (); 614 if (delete(lastRet)) { cursor = (cursor - 1) & (elements.length - 1); 616 fence = tail; 617 } 618 lastRet = -1; 619 } 620 } 621 622 private class DescendingIterator implements Iterator <E> { 623 628 private int cursor = tail; 629 private int fence = head; 630 private int lastRet = -1; 631 632 public boolean hasNext() { 633 return cursor != fence; 634 } 635 636 public E next() { 637 if (cursor == fence) 638 throw new NoSuchElementException (); 639 cursor = (cursor - 1) & (elements.length - 1); 640 E result = elements[cursor]; 641 if (head != fence || result == null) 642 throw new ConcurrentModificationException (); 643 lastRet = cursor; 644 return result; 645 } 646 647 public void remove() { 648 if (lastRet < 0) 649 throw new IllegalStateException (); 650 if (!delete(lastRet)) { 651 cursor = (cursor + 1) & (elements.length - 1); 652 fence = head; 653 } 654 lastRet = -1; 655 } 656 } 657 658 666 public boolean contains(Object o) { 667 if (o == null) 668 return false; 669 int mask = elements.length - 1; 670 int i = head; 671 E x; 672 while ( (x = elements[i]) != null) { 673 if (o.equals(x)) 674 return true; 675 i = (i + 1) & mask; 676 } 677 return false; 678 } 679 680 693 public boolean remove(Object o) { 694 return removeFirstOccurrence(o); 695 } 696 697 701 public void clear() { 702 int h = head; 703 int t = tail; 704 if (h != t) { head = tail = 0; 706 int i = h; 707 int mask = elements.length - 1; 708 do { 709 elements[i] = null; 710 i = (i + 1) & mask; 711 } while (i != t); 712 } 713 } 714 715 728 public Object [] toArray() { 729 return copyElements(new Object [size()]); 730 } 731 732 769 public <T> T[] toArray(T[] a) { 770 int size = size(); 771 if (a.length < size) 772 a = (T[])java.lang.reflect.Array.newInstance( 773 a.getClass().getComponentType(), size); 774 copyElements(a); 775 if (a.length > size) 776 a[size] = null; 777 return a; 778 } 779 780 782 787 public ArrayDeque <E> clone() { 788 try { 789 ArrayDeque <E> result = (ArrayDeque <E>) super.clone(); 790 result.elements = Arrays.copyOf(elements, elements.length); 791 return result; 792 793 } catch (CloneNotSupportedException e) { 794 throw new AssertionError (); 795 } 796 } 797 798 801 private static final long serialVersionUID = 2340985798034038923L; 802 803 810 private void writeObject(ObjectOutputStream s) throws IOException { 811 s.defaultWriteObject(); 812 813 s.writeInt(size()); 815 816 int mask = elements.length - 1; 818 for (int i = head; i != tail; i = (i + 1) & mask) 819 s.writeObject(elements[i]); 820 } 821 822 825 private void readObject(ObjectInputStream s) 826 throws IOException, ClassNotFoundException { 827 s.defaultReadObject(); 828 829 int size = s.readInt(); 831 allocateElements(size); 832 head = 0; 833 tail = size; 834 835 for (int i = 0; i < size; i++) 837 elements[i] = (E)s.readObject(); 838 } 839 } 840 | Popular Tags |