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

Comparing jsr166/src/main/java/util/ArrayList.java (file contents):
Revision 1.41 by jsr166, Sun Nov 13 21:07:40 2016 UTC vs.
Revision 1.62 by jsr166, Tue May 22 15:51:31 2018 UTC

# Line 1 | Line 1
1   /*
2 < * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
2 > * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
3   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4   *
5   * This code is free software; you can redistribute it and/or modify it
# Line 28 | Line 28 | package java.util;
28   import java.util.function.Consumer;
29   import java.util.function.Predicate;
30   import java.util.function.UnaryOperator;
31 + import jdk.internal.misc.SharedSecrets;
32  
33   /**
34   * Resizable-array implementation of the {@code List} interface.  Implements
# Line 91 | Line 92 | import java.util.function.UnaryOperator;
92   * should be used only to detect bugs.</i>
93   *
94   * <p>This class is a member of the
95 < * <a href="{@docRoot}/../technotes/guides/collections/index.html">
95 > * <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
96   * Java Collections Framework</a>.
97   *
98   * @param <E> the type of elements in this list
# Line 313 | Line 314 | public class ArrayList<E> extends Abstra
314       * or -1 if there is no such index.
315       */
316      public int indexOf(Object o) {
317 +        return indexOfRange(o, 0, size);
318 +    }
319 +
320 +    int indexOfRange(Object o, int start, int end) {
321 +        Object[] es = elementData;
322          if (o == null) {
323 <            for (int i = 0; i < size; i++)
324 <                if (elementData[i]==null)
323 >            for (int i = start; i < end; i++) {
324 >                if (es[i] == null) {
325                      return i;
326 +                }
327 +            }
328          } else {
329 <            for (int i = 0; i < size; i++)
330 <                if (o.equals(elementData[i]))
329 >            for (int i = start; i < end; i++) {
330 >                if (o.equals(es[i])) {
331                      return i;
332 +                }
333 +            }
334          }
335          return -1;
336      }
# Line 333 | Line 343 | public class ArrayList<E> extends Abstra
343       * or -1 if there is no such index.
344       */
345      public int lastIndexOf(Object o) {
346 +        return lastIndexOfRange(o, 0, size);
347 +    }
348 +
349 +    int lastIndexOfRange(Object o, int start, int end) {
350 +        Object[] es = elementData;
351          if (o == null) {
352 <            for (int i = size-1; i >= 0; i--)
353 <                if (elementData[i]==null)
352 >            for (int i = end - 1; i >= start; i--) {
353 >                if (es[i] == null) {
354                      return i;
355 +                }
356 +            }
357          } else {
358 <            for (int i = size-1; i >= 0; i--)
359 <                if (o.equals(elementData[i]))
358 >            for (int i = end - 1; i >= start; i--) {
359 >                if (o.equals(es[i])) {
360                      return i;
361 +                }
362 +            }
363          }
364          return -1;
365      }
# Line 515 | Line 534 | public class ArrayList<E> extends Abstra
534       */
535      public E remove(int index) {
536          Objects.checkIndex(index, size);
537 +        final Object[] es = elementData;
538  
539 <        modCount++;
540 <        E oldValue = elementData(index);
521 <
522 <        int numMoved = size - index - 1;
523 <        if (numMoved > 0)
524 <            System.arraycopy(elementData, index+1, elementData, index,
525 <                             numMoved);
526 <        elementData[--size] = null; // clear to let GC do its work
539 >        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
540 >        fastRemove(es, index);
541  
542          // checkInvariants();
543          return oldValue;
544      }
545  
546      /**
547 +     * {@inheritDoc}
548 +     */
549 +    public boolean equals(Object o) {
550 +        if (o == this) {
551 +            return true;
552 +        }
553 +
554 +        if (!(o instanceof List)) {
555 +            return false;
556 +        }
557 +
558 +        final int expectedModCount = modCount;
559 +        // ArrayList can be subclassed and given arbitrary behavior, but we can
560 +        // still deal with the common case where o is ArrayList precisely
561 +        boolean equal = (o.getClass() == ArrayList.class)
562 +            ? equalsArrayList((ArrayList<?>) o)
563 +            : equalsRange((List<?>) o, 0, size);
564 +
565 +        checkForComodification(expectedModCount);
566 +        return equal;
567 +    }
568 +
569 +    boolean equalsRange(List<?> other, int from, int to) {
570 +        final Object[] es = elementData;
571 +        if (to > es.length) {
572 +            throw new ConcurrentModificationException();
573 +        }
574 +        Iterator<?> oit = other.iterator();
575 +        for (; from < to; from++) {
576 +            if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) {
577 +                return false;
578 +            }
579 +        }
580 +        return !oit.hasNext();
581 +    }
582 +
583 +    private boolean equalsArrayList(ArrayList<?> other) {
584 +        final int otherModCount = other.modCount;
585 +        final int s = size;
586 +        boolean equal;
587 +        if (equal = (s == other.size)) {
588 +            final Object[] otherEs = other.elementData;
589 +            final Object[] es = elementData;
590 +            if (s > es.length || s > otherEs.length) {
591 +                throw new ConcurrentModificationException();
592 +            }
593 +            for (int i = 0; i < s; i++) {
594 +                if (!Objects.equals(es[i], otherEs[i])) {
595 +                    equal = false;
596 +                    break;
597 +                }
598 +            }
599 +        }
600 +        other.checkForComodification(otherModCount);
601 +        return equal;
602 +    }
603 +
604 +    private void checkForComodification(final int expectedModCount) {
605 +        if (modCount != expectedModCount) {
606 +            throw new ConcurrentModificationException();
607 +        }
608 +    }
609 +
610 +    /**
611 +     * {@inheritDoc}
612 +     */
613 +    public int hashCode() {
614 +        int expectedModCount = modCount;
615 +        int hash = hashCodeRange(0, size);
616 +        checkForComodification(expectedModCount);
617 +        return hash;
618 +    }
619 +
620 +    int hashCodeRange(int from, int to) {
621 +        final Object[] es = elementData;
622 +        if (to > es.length) {
623 +            throw new ConcurrentModificationException();
624 +        }
625 +        int hashCode = 1;
626 +        for (int i = from; i < to; i++) {
627 +            Object e = es[i];
628 +            hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
629 +        }
630 +        return hashCode;
631 +    }
632 +
633 +    /**
634       * Removes the first occurrence of the specified element from this list,
635       * if it is present.  If the list does not contain the element, it is
636       * unchanged.  More formally, removes the element with the lowest index
# Line 543 | Line 644 | public class ArrayList<E> extends Abstra
644       * @return {@code true} if this list contained the specified element
645       */
646      public boolean remove(Object o) {
647 <        if (o == null) {
648 <            for (int index = 0; index < size; index++)
649 <                if (elementData[index] == null) {
650 <                    fastRemove(index);
651 <                    return true;
652 <                }
653 <        } else {
654 <            for (int index = 0; index < size; index++)
655 <                if (o.equals(elementData[index])) {
656 <                    fastRemove(index);
657 <                    return true;
658 <                }
647 >        final Object[] es = elementData;
648 >        final int size = this.size;
649 >        int i = 0;
650 >        found: {
651 >            if (o == null) {
652 >                for (; i < size; i++)
653 >                    if (es[i] == null)
654 >                        break found;
655 >            } else {
656 >                for (; i < size; i++)
657 >                    if (o.equals(es[i]))
658 >                        break found;
659 >            }
660 >            return false;
661          }
662 <        return false;
662 >        fastRemove(es, i);
663 >        return true;
664      }
665  
666      /**
667       * Private remove method that skips bounds checking and does not
668       * return the value removed.
669       */
670 <    private void fastRemove(int index) {
670 >    private void fastRemove(Object[] es, int i) {
671          modCount++;
672 <        int numMoved = size - index - 1;
673 <        if (numMoved > 0)
674 <            System.arraycopy(elementData, index+1, elementData, index,
675 <                             numMoved);
572 <        elementData[--size] = null; // clear to let GC do its work
672 >        final int newSize;
673 >        if ((newSize = size - 1) > i)
674 >            System.arraycopy(es, i + 1, es, i, newSize - i);
675 >        es[size = newSize] = null;
676      }
677  
678      /**
# Line 578 | Line 681 | public class ArrayList<E> extends Abstra
681       */
682      public void clear() {
683          modCount++;
684 <        Arrays.fill(elementData, 0, size, null);
685 <        size = 0;
684 >        final Object[] es = elementData;
685 >        for (int to = size, i = size = 0; i < to; i++)
686 >            es[i] = null;
687      }
688  
689      /**
# Line 669 | Line 773 | public class ArrayList<E> extends Abstra
773                      outOfBoundsMsg(fromIndex, toIndex));
774          }
775          modCount++;
776 <        final Object[] es = elementData;
673 <        final int oldSize = size;
674 <        System.arraycopy(es, toIndex, es, fromIndex, oldSize - toIndex);
675 <        Arrays.fill(es, size -= (toIndex - fromIndex), oldSize, null);
776 >        shiftTailOverGap(elementData, fromIndex, toIndex);
777          // checkInvariants();
778      }
779  
780 +    /** Erases the gap from lo to hi, by sliding down following elements. */
781 +    private void shiftTailOverGap(Object[] es, int lo, int hi) {
782 +        System.arraycopy(es, hi, es, lo, size - hi);
783 +        for (int to = size, i = (size -= hi - lo); i < to; i++)
784 +            es[i] = null;
785 +    }
786 +
787      /**
788       * A version of rangeCheck used by add and addAll.
789       */
# Line 743 | Line 851 | public class ArrayList<E> extends Abstra
851                          final int from, final int end) {
852          Objects.requireNonNull(c);
853          final Object[] es = elementData;
746        final boolean modified;
854          int r;
855          // Optimize for initial run of survivors
856 <        for (r = from; r < end && c.contains(es[r]) == complement; r++)
857 <            ;
858 <        if (modified = (r < end)) {
859 <            int w = r++;
860 <            try {
861 <                for (Object e; r < end; r++)
862 <                    if (c.contains(e = es[r]) == complement)
863 <                        es[w++] = e;
864 <            } catch (Throwable ex) {
865 <                // Preserve behavioral compatibility with AbstractCollection,
866 <                // even if c.contains() throws.
867 <                System.arraycopy(es, r, es, w, end - r);
868 <                w += end - r;
869 <                throw ex;
870 <            } finally {
871 <                final int oldSize = size, deleted = end - w;
872 <                modCount += deleted;
873 <                System.arraycopy(es, end, es, w, oldSize - end);
874 <                Arrays.fill(es, size -= deleted, oldSize, null);
875 <            }
856 >        for (r = from;; r++) {
857 >            if (r == end)
858 >                return false;
859 >            if (c.contains(es[r]) != complement)
860 >                break;
861 >        }
862 >        int w = r++;
863 >        try {
864 >            for (Object e; r < end; r++)
865 >                if (c.contains(e = es[r]) == complement)
866 >                    es[w++] = e;
867 >        } catch (Throwable ex) {
868 >            // Preserve behavioral compatibility with AbstractCollection,
869 >            // even if c.contains() throws.
870 >            System.arraycopy(es, r, es, w, end - r);
871 >            w += end - r;
872 >            throw ex;
873 >        } finally {
874 >            modCount += end - w;
875 >            shiftTailOverGap(es, w, end);
876          }
877          // checkInvariants();
878 <        return modified;
878 >        return true;
879      }
880  
881      /**
882 <     * Save the state of the {@code ArrayList} instance to a stream (that
883 <     * is, serialize it).
882 >     * Saves the state of the {@code ArrayList} instance to a stream
883 >     * (that is, serializes it).
884       *
885 +     * @param s the stream
886 +     * @throws java.io.IOException if an I/O error occurs
887       * @serialData The length of the array backing the {@code ArrayList}
888       *             instance is emitted (int), followed by all of its elements
889       *             (each an {@code Object}) in the proper order.
890       */
891      private void writeObject(java.io.ObjectOutputStream s)
892 <        throws java.io.IOException{
892 >        throws java.io.IOException {
893          // Write out element count, and any hidden stuff
894          int expectedModCount = modCount;
895          s.defaultWriteObject();
896  
897 <        // Write out size as capacity for behavioural compatibility with clone()
897 >        // Write out size as capacity for behavioral compatibility with clone()
898          s.writeInt(size);
899  
900          // Write out all elements in the proper order.
# Line 799 | Line 908 | public class ArrayList<E> extends Abstra
908      }
909  
910      /**
911 <     * Reconstitute the {@code ArrayList} instance from a stream (that is,
912 <     * deserialize it).
911 >     * Reconstitutes the {@code ArrayList} instance from a stream (that is,
912 >     * deserializes it).
913 >     * @param s the stream
914 >     * @throws ClassNotFoundException if the class of a serialized object
915 >     *         could not be found
916 >     * @throws java.io.IOException if an I/O error occurs
917       */
918      private void readObject(java.io.ObjectInputStream s)
919          throws java.io.IOException, ClassNotFoundException {
# Line 813 | Line 926 | public class ArrayList<E> extends Abstra
926  
927          if (size > 0) {
928              // like clone(), allocate array based upon size not capacity
929 +            SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size);
930              Object[] elements = new Object[size];
931  
932              // Read in all elements in the proper order.
# Line 912 | Line 1026 | public class ArrayList<E> extends Abstra
1026          }
1027  
1028          @Override
1029 <        @SuppressWarnings("unchecked")
1030 <        public void forEachRemaining(Consumer<? super E> consumer) {
917 <            Objects.requireNonNull(consumer);
1029 >        public void forEachRemaining(Consumer<? super E> action) {
1030 >            Objects.requireNonNull(action);
1031              final int size = ArrayList.this.size;
1032              int i = cursor;
1033 <            if (i >= size) {
1034 <                return;
1035 <            }
1036 <            final Object[] elementData = ArrayList.this.elementData;
1037 <            if (i >= elementData.length) {
1038 <                throw new ConcurrentModificationException();
1039 <            }
1040 <            while (i != size && modCount == expectedModCount) {
1041 <                consumer.accept((E) elementData[i++]);
1033 >            if (i < size) {
1034 >                final Object[] es = elementData;
1035 >                if (i >= es.length)
1036 >                    throw new ConcurrentModificationException();
1037 >                for (; i < size && modCount == expectedModCount; i++)
1038 >                    action.accept(elementAt(es, i));
1039 >                // update once at end to reduce heap write traffic
1040 >                cursor = i;
1041 >                lastRet = i - 1;
1042 >                checkForComodification();
1043              }
930            // update once at end of iteration to reduce heap write traffic
931            cursor = i;
932            lastRet = i - 1;
933            checkForComodification();
1044          }
1045  
1046          final void checkForComodification() {
# Line 1117 | Line 1227 | public class ArrayList<E> extends Abstra
1227              return true;
1228          }
1229  
1230 +        public void replaceAll(UnaryOperator<E> operator) {
1231 +            root.replaceAllRange(operator, offset, offset + size);
1232 +        }
1233 +
1234          public boolean removeAll(Collection<?> c) {
1235              return batchRemove(c, false);
1236          }
# Line 1144 | Line 1258 | public class ArrayList<E> extends Abstra
1258              return modified;
1259          }
1260  
1261 +        public Object[] toArray() {
1262 +            checkForComodification();
1263 +            return Arrays.copyOfRange(root.elementData, offset, offset + size);
1264 +        }
1265 +
1266 +        @SuppressWarnings("unchecked")
1267 +        public <T> T[] toArray(T[] a) {
1268 +            checkForComodification();
1269 +            if (a.length < size)
1270 +                return (T[]) Arrays.copyOfRange(
1271 +                        root.elementData, offset, offset + size, a.getClass());
1272 +            System.arraycopy(root.elementData, offset, a, 0, size);
1273 +            if (a.length > size)
1274 +                a[size] = null;
1275 +            return a;
1276 +        }
1277 +
1278 +        public boolean equals(Object o) {
1279 +            if (o == this) {
1280 +                return true;
1281 +            }
1282 +
1283 +            if (!(o instanceof List)) {
1284 +                return false;
1285 +            }
1286 +
1287 +            boolean equal = root.equalsRange((List<?>)o, offset, offset + size);
1288 +            checkForComodification();
1289 +            return equal;
1290 +        }
1291 +
1292 +        public int hashCode() {
1293 +            int hash = root.hashCodeRange(offset, offset + size);
1294 +            checkForComodification();
1295 +            return hash;
1296 +        }
1297 +
1298 +        public int indexOf(Object o) {
1299 +            int index = root.indexOfRange(o, offset, offset + size);
1300 +            checkForComodification();
1301 +            return index >= 0 ? index - offset : -1;
1302 +        }
1303 +
1304 +        public int lastIndexOf(Object o) {
1305 +            int index = root.lastIndexOfRange(o, offset, offset + size);
1306 +            checkForComodification();
1307 +            return index >= 0 ? index - offset : -1;
1308 +        }
1309 +
1310 +        public boolean contains(Object o) {
1311 +            return indexOf(o) >= 0;
1312 +        }
1313 +
1314          public Iterator<E> iterator() {
1315              return listIterator();
1316          }
# Line 1191 | Line 1358 | public class ArrayList<E> extends Abstra
1358                      return (E) elementData[offset + (lastRet = i)];
1359                  }
1360  
1361 <                @SuppressWarnings("unchecked")
1362 <                public void forEachRemaining(Consumer<? super E> consumer) {
1196 <                    Objects.requireNonNull(consumer);
1361 >                public void forEachRemaining(Consumer<? super E> action) {
1362 >                    Objects.requireNonNull(action);
1363                      final int size = SubList.this.size;
1364                      int i = cursor;
1365 <                    if (i >= size) {
1366 <                        return;
1367 <                    }
1368 <                    final Object[] elementData = root.elementData;
1369 <                    if (offset + i >= elementData.length) {
1370 <                        throw new ConcurrentModificationException();
1371 <                    }
1372 <                    while (i != size && modCount == expectedModCount) {
1373 <                        consumer.accept((E) elementData[offset + (i++)]);
1365 >                    if (i < size) {
1366 >                        final Object[] es = root.elementData;
1367 >                        if (offset + i >= es.length)
1368 >                            throw new ConcurrentModificationException();
1369 >                        for (; i < size && modCount == expectedModCount; i++)
1370 >                            action.accept(elementAt(es, offset + i));
1371 >                        // update once at end to reduce heap write traffic
1372 >                        cursor = i;
1373 >                        lastRet = i - 1;
1374 >                        checkForComodification();
1375                      }
1209                    // update once at end of iteration to reduce heap write traffic
1210                    lastRet = cursor = i;
1211                    checkForComodification();
1376                  }
1377  
1378                  public int nextIndex() {
# Line 1298 | Line 1462 | public class ArrayList<E> extends Abstra
1462          public Spliterator<E> spliterator() {
1463              checkForComodification();
1464  
1465 <            // ArrayListSpliterator is not used because late-binding logic
1466 <            // is different here
1303 <            return new Spliterator<>() {
1465 >            // ArrayListSpliterator not used here due to late-binding
1466 >            return new Spliterator<E>() {
1467                  private int index = offset; // current index, modified on advance/split
1468                  private int fence = -1; // -1 until used; then one past last index
1469                  private int expectedModCount; // initialized when fence set
# Line 1314 | Line 1477 | public class ArrayList<E> extends Abstra
1477                      return hi;
1478                  }
1479  
1480 <                public ArrayListSpliterator<E> trySplit() {
1480 >                public ArrayList<E>.ArrayListSpliterator trySplit() {
1481                      int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
1482 <                    // ArrayListSpliterator could be used here as the source is already bound
1482 >                    // ArrayListSpliterator can be used here as the source is already bound
1483                      return (lo >= mid) ? null : // divide range in half unless too small
1484 <                        new ArrayListSpliterator<>(root, lo, index = mid,
1322 <                                                   expectedModCount);
1484 >                        root.new ArrayListSpliterator(lo, index = mid, expectedModCount);
1485                  }
1486  
1487                  public boolean tryAdvance(Consumer<? super E> action) {
# Line 1361 | Line 1523 | public class ArrayList<E> extends Abstra
1523                  }
1524  
1525                  public long estimateSize() {
1526 <                    return (long) (getFence() - index);
1526 >                    return getFence() - index;
1527                  }
1528  
1529                  public int characteristics() {
# Line 1371 | Line 1533 | public class ArrayList<E> extends Abstra
1533          }
1534      }
1535  
1536 +    /**
1537 +     * @throws NullPointerException {@inheritDoc}
1538 +     */
1539      @Override
1540      public void forEach(Consumer<? super E> action) {
1541          Objects.requireNonNull(action);
# Line 1398 | Line 1563 | public class ArrayList<E> extends Abstra
1563       */
1564      @Override
1565      public Spliterator<E> spliterator() {
1566 <        return new ArrayListSpliterator<>(this, 0, -1, 0);
1566 >        return new ArrayListSpliterator(0, -1, 0);
1567      }
1568  
1569      /** Index-based split-by-two, lazily initialized Spliterator */
1570 <    static final class ArrayListSpliterator<E> implements Spliterator<E> {
1570 >    final class ArrayListSpliterator implements Spliterator<E> {
1571  
1572          /*
1573           * If ArrayLists were immutable, or structurally immutable (no
# Line 1436 | Line 1601 | public class ArrayList<E> extends Abstra
1601           * these streamlinings.
1602           */
1603  
1439        private final ArrayList<E> list;
1604          private int index; // current index, modified on advance/split
1605          private int fence; // -1 until used; then one past last index
1606          private int expectedModCount; // initialized when fence set
1607  
1608 <        /** Create new spliterator covering the given range */
1609 <        ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
1446 <                             int expectedModCount) {
1447 <            this.list = list; // OK if null unless traversed
1608 >        /** Creates new spliterator covering the given range. */
1609 >        ArrayListSpliterator(int origin, int fence, int expectedModCount) {
1610              this.index = origin;
1611              this.fence = fence;
1612              this.expectedModCount = expectedModCount;
# Line 1452 | Line 1614 | public class ArrayList<E> extends Abstra
1614  
1615          private int getFence() { // initialize fence to size on first use
1616              int hi; // (a specialized variant appears in method forEach)
1455            ArrayList<E> lst;
1617              if ((hi = fence) < 0) {
1618 <                if ((lst = list) == null)
1619 <                    hi = fence = 0;
1459 <                else {
1460 <                    expectedModCount = lst.modCount;
1461 <                    hi = fence = lst.size;
1462 <                }
1618 >                expectedModCount = modCount;
1619 >                hi = fence = size;
1620              }
1621              return hi;
1622          }
1623  
1624 <        public ArrayListSpliterator<E> trySplit() {
1624 >        public ArrayListSpliterator trySplit() {
1625              int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
1626              return (lo >= mid) ? null : // divide range in half unless too small
1627 <                new ArrayListSpliterator<>(list, lo, index = mid,
1471 <                                           expectedModCount);
1627 >                new ArrayListSpliterator(lo, index = mid, expectedModCount);
1628          }
1629  
1630          public boolean tryAdvance(Consumer<? super E> action) {
# Line 1477 | Line 1633 | public class ArrayList<E> extends Abstra
1633              int hi = getFence(), i = index;
1634              if (i < hi) {
1635                  index = i + 1;
1636 <                @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
1636 >                @SuppressWarnings("unchecked") E e = (E)elementData[i];
1637                  action.accept(e);
1638 <                if (list.modCount != expectedModCount)
1638 >                if (modCount != expectedModCount)
1639                      throw new ConcurrentModificationException();
1640                  return true;
1641              }
# Line 1488 | Line 1644 | public class ArrayList<E> extends Abstra
1644  
1645          public void forEachRemaining(Consumer<? super E> action) {
1646              int i, hi, mc; // hoist accesses and checks from loop
1647 <            ArrayList<E> lst; Object[] a;
1647 >            Object[] a;
1648              if (action == null)
1649                  throw new NullPointerException();
1650 <            if ((lst = list) != null && (a = lst.elementData) != null) {
1650 >            if ((a = elementData) != null) {
1651                  if ((hi = fence) < 0) {
1652 <                    mc = lst.modCount;
1653 <                    hi = lst.size;
1652 >                    mc = modCount;
1653 >                    hi = size;
1654                  }
1655                  else
1656                      mc = expectedModCount;
# Line 1503 | Line 1659 | public class ArrayList<E> extends Abstra
1659                          @SuppressWarnings("unchecked") E e = (E) a[i];
1660                          action.accept(e);
1661                      }
1662 <                    if (lst.modCount == mc)
1662 >                    if (modCount == mc)
1663                          return;
1664                  }
1665              }
# Line 1511 | Line 1667 | public class ArrayList<E> extends Abstra
1667          }
1668  
1669          public long estimateSize() {
1670 <            return (long) (getFence() - index);
1670 >            return getFence() - index;
1671          }
1672  
1673          public int characteristics() {
# Line 1531 | Line 1687 | public class ArrayList<E> extends Abstra
1687          return (bits[i >> 6] & (1L << i)) == 0;
1688      }
1689  
1690 +    /**
1691 +     * @throws NullPointerException {@inheritDoc}
1692 +     */
1693      @Override
1694      public boolean removeIf(Predicate<? super E> filter) {
1695          return removeIf(filter, 0, size);
1696      }
1697  
1698 <    boolean removeIf(Predicate<? super E> filter,
1699 <                     final int from, final int end) {
1698 >    /**
1699 >     * Removes all elements satisfying the given predicate, from index
1700 >     * i (inclusive) to index end (exclusive).
1701 >     */
1702 >    boolean removeIf(Predicate<? super E> filter, int i, final int end) {
1703          Objects.requireNonNull(filter);
1704          int expectedModCount = modCount;
1705          final Object[] es = elementData;
1544        final boolean modified;
1545        int i;
1706          // Optimize for initial run of survivors
1707 <        for (i = from; i < end && !filter.test(elementAt(es, i)); i++)
1707 >        for (; i < end && !filter.test(elementAt(es, i)); i++)
1708              ;
1709          // Tolerate predicates that reentrantly access the collection for
1710          // read (but writers still get CME), so traverse once to find
1711          // elements to delete, a second pass to physically expunge.
1712 <        if (modified = (i < end)) {
1553 <            expectedModCount++;
1554 <            modCount++;
1712 >        if (i < end) {
1713              final int beg = i;
1714              final long[] deathRow = nBits(end - beg);
1715              deathRow[0] = 1L;   // set bit 0
# Line 1560 | Line 1718 | public class ArrayList<E> extends Abstra
1718                      setBit(deathRow, i - beg);
1719              if (modCount != expectedModCount)
1720                  throw new ConcurrentModificationException();
1721 +            modCount++;
1722              int w = beg;
1723              for (i = beg; i < end; i++)
1724                  if (isClear(deathRow, i - beg))
1725                      es[w++] = es[i];
1726 <            final int oldSize = size;
1727 <            System.arraycopy(es, end, es, w, oldSize - end);
1728 <            Arrays.fill(es, size -= (end - w), oldSize, null);
1726 >            shiftTailOverGap(es, w, end);
1727 >            // checkInvariants();
1728 >            return true;
1729 >        } else {
1730 >            if (modCount != expectedModCount)
1731 >                throw new ConcurrentModificationException();
1732 >            // checkInvariants();
1733 >            return false;
1734          }
1571        if (modCount != expectedModCount)
1572            throw new ConcurrentModificationException();
1573        // checkInvariants();
1574        return modified;
1735      }
1736  
1737      @Override
1738      public void replaceAll(UnaryOperator<E> operator) {
1739 +        replaceAllRange(operator, 0, size);
1740 +        modCount++;
1741 +    }
1742 +
1743 +    private void replaceAllRange(UnaryOperator<E> operator, int i, int end) {
1744          Objects.requireNonNull(operator);
1745          final int expectedModCount = modCount;
1746          final Object[] es = elementData;
1747 <        final int size = this.size;
1583 <        for (int i = 0; modCount == expectedModCount && i < size; i++)
1747 >        for (; modCount == expectedModCount && i < end; i++)
1748              es[i] = operator.apply(elementAt(es, i));
1749          if (modCount != expectedModCount)
1750              throw new ConcurrentModificationException();
1587        modCount++;
1751          // checkInvariants();
1752      }
1753  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines