512 * @return the element that was removed from the list |
512 * @return the element that was removed from the list |
513 * @throws IndexOutOfBoundsException {@inheritDoc} |
513 * @throws IndexOutOfBoundsException {@inheritDoc} |
514 */ |
514 */ |
515 public E remove(int index) { |
515 public E remove(int index) { |
516 Objects.checkIndex(index, size); |
516 Objects.checkIndex(index, size); |
517 |
517 final Object[] es = elementData; |
518 modCount++; |
518 |
519 E oldValue = elementData(index); |
519 @SuppressWarnings("unchecked") E oldValue = (E) es[index]; |
520 |
520 fastRemove(es, index); |
521 int numMoved = size - index - 1; |
|
522 if (numMoved > 0) |
|
523 System.arraycopy(elementData, index+1, elementData, index, |
|
524 numMoved); |
|
525 elementData[--size] = null; // clear to let GC do its work |
|
526 |
521 |
527 return oldValue; |
522 return oldValue; |
528 } |
523 } |
529 |
524 |
530 /** |
525 /** |
539 * |
534 * |
540 * @param o element to be removed from this list, if present |
535 * @param o element to be removed from this list, if present |
541 * @return {@code true} if this list contained the specified element |
536 * @return {@code true} if this list contained the specified element |
542 */ |
537 */ |
543 public boolean remove(Object o) { |
538 public boolean remove(Object o) { |
544 if (o == null) { |
539 final Object[] es = elementData; |
545 for (int index = 0; index < size; index++) |
540 final int size = this.size; |
546 if (elementData[index] == null) { |
541 int i = 0; |
547 fastRemove(index); |
542 found: { |
548 return true; |
543 if (o == null) { |
549 } |
544 for (; i < size; i++) |
550 } else { |
545 if (es[i] == null) |
551 for (int index = 0; index < size; index++) |
546 break found; |
552 if (o.equals(elementData[index])) { |
547 } else { |
553 fastRemove(index); |
548 for (; i < size; i++) |
554 return true; |
549 if (o.equals(es[i])) |
555 } |
550 break found; |
556 } |
551 } |
557 return false; |
552 return false; |
|
553 } |
|
554 fastRemove(es, i); |
|
555 return true; |
558 } |
556 } |
559 |
557 |
560 /** |
558 /** |
561 * Private remove method that skips bounds checking and does not |
559 * Private remove method that skips bounds checking and does not |
562 * return the value removed. |
560 * return the value removed. |
563 */ |
561 */ |
564 private void fastRemove(int index) { |
562 private void fastRemove(Object[] es, int i) { |
565 modCount++; |
563 modCount++; |
566 int numMoved = size - index - 1; |
564 final int newSize; |
567 if (numMoved > 0) |
565 if ((newSize = size - 1) > i) |
568 System.arraycopy(elementData, index+1, elementData, index, |
566 System.arraycopy(es, i + 1, es, i, newSize - i); |
569 numMoved); |
567 es[size = newSize] = null; |
570 elementData[--size] = null; // clear to let GC do its work |
|
571 } |
568 } |
572 |
569 |
573 /** |
570 /** |
574 * Removes all of the elements from this list. The list will |
571 * Removes all of the elements from this list. The list will |
575 * be empty after this call returns. |
572 * be empty after this call returns. |
741 |
738 |
742 boolean batchRemove(Collection<?> c, boolean complement, |
739 boolean batchRemove(Collection<?> c, boolean complement, |
743 final int from, final int end) { |
740 final int from, final int end) { |
744 Objects.requireNonNull(c); |
741 Objects.requireNonNull(c); |
745 final Object[] es = elementData; |
742 final Object[] es = elementData; |
746 final boolean modified; |
|
747 int r; |
743 int r; |
748 // Optimize for initial run of survivors |
744 // Optimize for initial run of survivors |
749 for (r = from; r < end && c.contains(es[r]) == complement; r++) |
745 for (r = from;; r++) { |
750 ; |
746 if (r == end) |
751 if (modified = (r < end)) { |
747 return false; |
752 int w = r++; |
748 if (c.contains(es[r]) != complement) |
753 try { |
749 break; |
754 for (Object e; r < end; r++) |
750 } |
755 if (c.contains(e = es[r]) == complement) |
751 int w = r++; |
756 es[w++] = e; |
752 try { |
757 } catch (Throwable ex) { |
753 for (Object e; r < end; r++) |
758 // Preserve behavioral compatibility with AbstractCollection, |
754 if (c.contains(e = es[r]) == complement) |
759 // even if c.contains() throws. |
755 es[w++] = e; |
760 System.arraycopy(es, r, es, w, end - r); |
756 } catch (Throwable ex) { |
761 w += end - r; |
757 // Preserve behavioral compatibility with AbstractCollection, |
762 throw ex; |
758 // even if c.contains() throws. |
763 } finally { |
759 System.arraycopy(es, r, es, w, end - r); |
764 modCount += end - w; |
760 w += end - r; |
765 shiftTailOverGap(es, w, end); |
761 throw ex; |
766 } |
762 } finally { |
767 } |
763 modCount += end - w; |
768 return modified; |
764 shiftTailOverGap(es, w, end); |
|
765 } |
|
766 return true; |
769 } |
767 } |
770 |
768 |
771 /** |
769 /** |
772 * Saves the state of the {@code ArrayList} instance to a stream |
770 * Saves the state of the {@code ArrayList} instance to a stream |
773 * (that is, serializes it). |
771 * (that is, serializes it). |
782 throws java.io.IOException { |
780 throws java.io.IOException { |
783 // Write out element count, and any hidden stuff |
781 // Write out element count, and any hidden stuff |
784 int expectedModCount = modCount; |
782 int expectedModCount = modCount; |
785 s.defaultWriteObject(); |
783 s.defaultWriteObject(); |
786 |
784 |
787 // Write out size as capacity for behavioural compatibility with clone() |
785 // Write out size as capacity for behavioral compatibility with clone() |
788 s.writeInt(size); |
786 s.writeInt(size); |
789 |
787 |
790 // Write out all elements in the proper order. |
788 // Write out all elements in the proper order. |
791 for (int i=0; i<size; i++) { |
789 for (int i=0; i<size; i++) { |
792 s.writeObject(elementData[i]); |
790 s.writeObject(elementData[i]); |