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.40 by jsr166, Sun Nov 13 20:03:11 2016 UTC vs.
Revision 1.70 by jsr166, Fri Jan 10 21:32:08 2020 UTC

# Line 1 | Line 1
1   /*
2 < * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
2 > * Copyright (c) 1997, 2019, 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 + // OPENJDK import jdk.internal.access.SharedSecrets;
32 + import jdk.internal.util.ArraysSupport;
33  
34   /**
35   * Resizable-array implementation of the {@code List} interface.  Implements
# Line 91 | Line 93 | import java.util.function.UnaryOperator;
93   * should be used only to detect bugs.</i>
94   *
95   * <p>This class is a member of the
96 < * <a href="{@docRoot}/../technotes/guides/collections/index.html">
96 > * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
97   * Java Collections Framework</a>.
98   *
99   * @param <E> the type of elements in this list
# Line 107 | Line 109 | import java.util.function.UnaryOperator;
109   public class ArrayList<E> extends AbstractList<E>
110          implements List<E>, RandomAccess, Cloneable, java.io.Serializable
111   {
112 +    // OPENJDK @java.io.Serial
113      private static final long serialVersionUID = 8683452581122892189L;
114  
115      /**
# Line 218 | Line 221 | public class ArrayList<E> extends Abstra
221      }
222  
223      /**
221     * The maximum size of array to allocate (unless necessary).
222     * Some VMs reserve some header words in an array.
223     * Attempts to allocate larger arrays may result in
224     * OutOfMemoryError: Requested array size exceeds VM limit
225     */
226    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
227
228    /**
224       * Increases the capacity to ensure that it can hold at least the
225       * number of elements specified by the minimum capacity argument.
226       *
# Line 233 | Line 228 | public class ArrayList<E> extends Abstra
228       * @throws OutOfMemoryError if minCapacity is less than zero
229       */
230      private Object[] grow(int minCapacity) {
231 <        return elementData = Arrays.copyOf(elementData,
232 <                                           newCapacity(minCapacity));
231 >        int oldCapacity = elementData.length;
232 >        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
233 >            int newCapacity = ArraysSupport.newLength(oldCapacity,
234 >                    minCapacity - oldCapacity, /* minimum growth */
235 >                    oldCapacity >> 1           /* preferred growth */);
236 >            return elementData = Arrays.copyOf(elementData, newCapacity);
237 >        } else {
238 >            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
239 >        }
240      }
241  
242      private Object[] grow() {
# Line 242 | Line 244 | public class ArrayList<E> extends Abstra
244      }
245  
246      /**
245     * Returns a capacity at least as large as the given minimum capacity.
246     * Returns the current capacity increased by 50% if that suffices.
247     * Will not return a capacity greater than MAX_ARRAY_SIZE unless
248     * the given minimum capacity is greater than MAX_ARRAY_SIZE.
249     *
250     * @param minCapacity the desired minimum capacity
251     * @throws OutOfMemoryError if minCapacity is less than zero
252     */
253    private int newCapacity(int minCapacity) {
254        // overflow-conscious code
255        int oldCapacity = elementData.length;
256        int newCapacity = oldCapacity + (oldCapacity >> 1);
257        if (newCapacity - minCapacity <= 0) {
258            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
259                return Math.max(DEFAULT_CAPACITY, minCapacity);
260            if (minCapacity < 0) // overflow
261                throw new OutOfMemoryError();
262            return minCapacity;
263        }
264        return (newCapacity - MAX_ARRAY_SIZE <= 0)
265            ? newCapacity
266            : hugeCapacity(minCapacity);
267    }
268
269    private static int hugeCapacity(int minCapacity) {
270        if (minCapacity < 0) // overflow
271            throw new OutOfMemoryError();
272        return (minCapacity > MAX_ARRAY_SIZE)
273            ? Integer.MAX_VALUE
274            : MAX_ARRAY_SIZE;
275    }
276
277    /**
247       * Returns the number of elements in this list.
248       *
249       * @return the number of elements in this list
# Line 313 | Line 282 | public class ArrayList<E> extends Abstra
282       * or -1 if there is no such index.
283       */
284      public int indexOf(Object o) {
285 +        return indexOfRange(o, 0, size);
286 +    }
287 +
288 +    int indexOfRange(Object o, int start, int end) {
289 +        Object[] es = elementData;
290          if (o == null) {
291 <            for (int i = 0; i < size; i++)
292 <                if (elementData[i]==null)
291 >            for (int i = start; i < end; i++) {
292 >                if (es[i] == null) {
293                      return i;
294 +                }
295 +            }
296          } else {
297 <            for (int i = 0; i < size; i++)
298 <                if (o.equals(elementData[i]))
297 >            for (int i = start; i < end; i++) {
298 >                if (o.equals(es[i])) {
299                      return i;
300 +                }
301 +            }
302          }
303          return -1;
304      }
# Line 333 | Line 311 | public class ArrayList<E> extends Abstra
311       * or -1 if there is no such index.
312       */
313      public int lastIndexOf(Object o) {
314 +        return lastIndexOfRange(o, 0, size);
315 +    }
316 +
317 +    int lastIndexOfRange(Object o, int start, int end) {
318 +        Object[] es = elementData;
319          if (o == null) {
320 <            for (int i = size-1; i >= 0; i--)
321 <                if (elementData[i]==null)
320 >            for (int i = end - 1; i >= start; i--) {
321 >                if (es[i] == null) {
322                      return i;
323 +                }
324 +            }
325          } else {
326 <            for (int i = size-1; i >= 0; i--)
327 <                if (o.equals(elementData[i]))
326 >            for (int i = end - 1; i >= start; i--) {
327 >                if (o.equals(es[i])) {
328                      return i;
329 +                }
330 +            }
331          }
332          return -1;
333      }
# Line 501 | Line 488 | public class ArrayList<E> extends Abstra
488                           s - index);
489          elementData[index] = element;
490          size = s + 1;
491 +        // checkInvariants();
492      }
493  
494      /**
# Line 514 | Line 502 | public class ArrayList<E> extends Abstra
502       */
503      public E remove(int index) {
504          Objects.checkIndex(index, size);
505 +        final Object[] es = elementData;
506  
507 <        modCount++;
508 <        E oldValue = elementData(index);
520 <
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
507 >        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
508 >        fastRemove(es, index);
509  
510 +        // checkInvariants();
511          return oldValue;
512      }
513  
514      /**
515 +     * {@inheritDoc}
516 +     */
517 +    public boolean equals(Object o) {
518 +        if (o == this) {
519 +            return true;
520 +        }
521 +
522 +        if (!(o instanceof List)) {
523 +            return false;
524 +        }
525 +
526 +        final int expectedModCount = modCount;
527 +        // ArrayList can be subclassed and given arbitrary behavior, but we can
528 +        // still deal with the common case where o is ArrayList precisely
529 +        boolean equal = (o.getClass() == ArrayList.class)
530 +            ? equalsArrayList((ArrayList<?>) o)
531 +            : equalsRange((List<?>) o, 0, size);
532 +
533 +        checkForComodification(expectedModCount);
534 +        return equal;
535 +    }
536 +
537 +    boolean equalsRange(List<?> other, int from, int to) {
538 +        final Object[] es = elementData;
539 +        if (to > es.length) {
540 +            throw new ConcurrentModificationException();
541 +        }
542 +        var oit = other.iterator();
543 +        for (; from < to; from++) {
544 +            if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) {
545 +                return false;
546 +            }
547 +        }
548 +        return !oit.hasNext();
549 +    }
550 +
551 +    private boolean equalsArrayList(ArrayList<?> other) {
552 +        final int otherModCount = other.modCount;
553 +        final int s = size;
554 +        boolean equal;
555 +        if (equal = (s == other.size)) {
556 +            final Object[] otherEs = other.elementData;
557 +            final Object[] es = elementData;
558 +            if (s > es.length || s > otherEs.length) {
559 +                throw new ConcurrentModificationException();
560 +            }
561 +            for (int i = 0; i < s; i++) {
562 +                if (!Objects.equals(es[i], otherEs[i])) {
563 +                    equal = false;
564 +                    break;
565 +                }
566 +            }
567 +        }
568 +        other.checkForComodification(otherModCount);
569 +        return equal;
570 +    }
571 +
572 +    private void checkForComodification(final int expectedModCount) {
573 +        if (modCount != expectedModCount) {
574 +            throw new ConcurrentModificationException();
575 +        }
576 +    }
577 +
578 +    /**
579 +     * {@inheritDoc}
580 +     */
581 +    public int hashCode() {
582 +        int expectedModCount = modCount;
583 +        int hash = hashCodeRange(0, size);
584 +        checkForComodification(expectedModCount);
585 +        return hash;
586 +    }
587 +
588 +    int hashCodeRange(int from, int to) {
589 +        final Object[] es = elementData;
590 +        if (to > es.length) {
591 +            throw new ConcurrentModificationException();
592 +        }
593 +        int hashCode = 1;
594 +        for (int i = from; i < to; i++) {
595 +            Object e = es[i];
596 +            hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
597 +        }
598 +        return hashCode;
599 +    }
600 +
601 +    /**
602       * Removes the first occurrence of the specified element from this list,
603       * if it is present.  If the list does not contain the element, it is
604       * unchanged.  More formally, removes the element with the lowest index
# Line 541 | Line 612 | public class ArrayList<E> extends Abstra
612       * @return {@code true} if this list contained the specified element
613       */
614      public boolean remove(Object o) {
615 <        if (o == null) {
616 <            for (int index = 0; index < size; index++)
617 <                if (elementData[index] == null) {
618 <                    fastRemove(index);
619 <                    return true;
620 <                }
621 <        } else {
622 <            for (int index = 0; index < size; index++)
623 <                if (o.equals(elementData[index])) {
624 <                    fastRemove(index);
625 <                    return true;
626 <                }
615 >        final Object[] es = elementData;
616 >        final int size = this.size;
617 >        int i = 0;
618 >        found: {
619 >            if (o == null) {
620 >                for (; i < size; i++)
621 >                    if (es[i] == null)
622 >                        break found;
623 >            } else {
624 >                for (; i < size; i++)
625 >                    if (o.equals(es[i]))
626 >                        break found;
627 >            }
628 >            return false;
629          }
630 <        return false;
630 >        fastRemove(es, i);
631 >        return true;
632      }
633  
634 <    /*
634 >    /**
635       * Private remove method that skips bounds checking and does not
636       * return the value removed.
637       */
638 <    private void fastRemove(int index) {
638 >    private void fastRemove(Object[] es, int i) {
639          modCount++;
640 <        int numMoved = size - index - 1;
641 <        if (numMoved > 0)
642 <            System.arraycopy(elementData, index+1, elementData, index,
643 <                             numMoved);
570 <        elementData[--size] = null; // clear to let GC do its work
640 >        final int newSize;
641 >        if ((newSize = size - 1) > i)
642 >            System.arraycopy(es, i + 1, es, i, newSize - i);
643 >        es[size = newSize] = null;
644      }
645  
646      /**
# Line 576 | Line 649 | public class ArrayList<E> extends Abstra
649       */
650      public void clear() {
651          modCount++;
652 <
653 <        // clear to let GC do its work
654 <        for (int i = 0; i < size; i++)
582 <            elementData[i] = null;
583 <
584 <        size = 0;
652 >        final Object[] es = elementData;
653 >        for (int to = size, i = size = 0; i < to; i++)
654 >            es[i] = null;
655      }
656  
657      /**
# Line 609 | Line 679 | public class ArrayList<E> extends Abstra
679              elementData = grow(s + numNew);
680          System.arraycopy(a, 0, elementData, s, numNew);
681          size = s + numNew;
682 +        // checkInvariants();
683          return true;
684      }
685  
# Line 647 | Line 718 | public class ArrayList<E> extends Abstra
718                               numMoved);
719          System.arraycopy(a, 0, elementData, index, numNew);
720          size = s + numNew;
721 +        // checkInvariants();
722          return true;
723      }
724  
# Line 669 | Line 741 | public class ArrayList<E> extends Abstra
741                      outOfBoundsMsg(fromIndex, toIndex));
742          }
743          modCount++;
744 <        int numMoved = size - toIndex;
745 <        System.arraycopy(elementData, toIndex, elementData, fromIndex,
746 <                         numMoved);
747 <
748 <        // clear to let GC do its work
749 <        int newSize = size - (toIndex-fromIndex);
750 <        for (int i = newSize; i < size; i++) {
751 <            elementData[i] = null;
752 <        }
681 <        size = newSize;
744 >        shiftTailOverGap(elementData, fromIndex, toIndex);
745 >        // checkInvariants();
746 >    }
747 >
748 >    /** Erases the gap from lo to hi, by sliding down following elements. */
749 >    private void shiftTailOverGap(Object[] es, int lo, int hi) {
750 >        System.arraycopy(es, hi, es, lo, size - hi);
751 >        for (int to = size, i = (size -= hi - lo); i < to; i++)
752 >            es[i] = null;
753      }
754  
755      /**
# Line 748 | Line 819 | public class ArrayList<E> extends Abstra
819                          final int from, final int end) {
820          Objects.requireNonNull(c);
821          final Object[] es = elementData;
751        final boolean modified;
822          int r;
823          // Optimize for initial run of survivors
824 <        for (r = from; r < end && c.contains(es[r]) == complement; r++)
825 <            ;
826 <        if (modified = (r < end)) {
827 <            int w = r++;
828 <            try {
829 <                for (Object e; r < end; r++)
830 <                    if (c.contains(e = es[r]) == complement)
831 <                        es[w++] = e;
832 <            } catch (Throwable ex) {
833 <                // Preserve behavioral compatibility with AbstractCollection,
834 <                // even if c.contains() throws.
835 <                System.arraycopy(es, r, es, w, end - r);
836 <                w += end - r;
837 <                throw ex;
838 <            } finally {
839 <                final int oldSize = size, deleted = end - w;
840 <                modCount += deleted;
841 <                System.arraycopy(es, end, es, w, oldSize - end);
842 <                Arrays.fill(es, size -= deleted, oldSize, null);
843 <            }
824 >        for (r = from;; r++) {
825 >            if (r == end)
826 >                return false;
827 >            if (c.contains(es[r]) != complement)
828 >                break;
829 >        }
830 >        int w = r++;
831 >        try {
832 >            for (Object e; r < end; r++)
833 >                if (c.contains(e = es[r]) == complement)
834 >                    es[w++] = e;
835 >        } catch (Throwable ex) {
836 >            // Preserve behavioral compatibility with AbstractCollection,
837 >            // even if c.contains() throws.
838 >            System.arraycopy(es, r, es, w, end - r);
839 >            w += end - r;
840 >            throw ex;
841 >        } finally {
842 >            modCount += end - w;
843 >            shiftTailOverGap(es, w, end);
844          }
845 <        return modified;
845 >        // checkInvariants();
846 >        return true;
847      }
848  
849      /**
850 <     * Save the state of the {@code ArrayList} instance to a stream (that
851 <     * is, serialize it).
850 >     * Saves the state of the {@code ArrayList} instance to a stream
851 >     * (that is, serializes it).
852       *
853 +     * @param s the stream
854 +     * @throws java.io.IOException if an I/O error occurs
855       * @serialData The length of the array backing the {@code ArrayList}
856       *             instance is emitted (int), followed by all of its elements
857       *             (each an {@code Object}) in the proper order.
858       */
859 +    // OPENJDK @java.io.Serial
860      private void writeObject(java.io.ObjectOutputStream s)
861 <        throws java.io.IOException{
861 >        throws java.io.IOException {
862          // Write out element count, and any hidden stuff
863          int expectedModCount = modCount;
864          s.defaultWriteObject();
865  
866 <        // Write out size as capacity for behavioural compatibility with clone()
866 >        // Write out size as capacity for behavioral compatibility with clone()
867          s.writeInt(size);
868  
869          // Write out all elements in the proper order.
# Line 803 | Line 877 | public class ArrayList<E> extends Abstra
877      }
878  
879      /**
880 <     * Reconstitute the {@code ArrayList} instance from a stream (that is,
881 <     * deserialize it).
880 >     * Reconstitutes the {@code ArrayList} instance from a stream (that is,
881 >     * deserializes it).
882 >     * @param s the stream
883 >     * @throws ClassNotFoundException if the class of a serialized object
884 >     *         could not be found
885 >     * @throws java.io.IOException if an I/O error occurs
886       */
887 +    // OPENJDK @java.io.Serial
888      private void readObject(java.io.ObjectInputStream s)
889          throws java.io.IOException, ClassNotFoundException {
890  
# Line 817 | Line 896 | public class ArrayList<E> extends Abstra
896  
897          if (size > 0) {
898              // like clone(), allocate array based upon size not capacity
899 +            jsr166.Platform.checkArray(s, Object[].class, size);
900              Object[] elements = new Object[size];
901  
902              // Read in all elements in the proper order.
# Line 916 | Line 996 | public class ArrayList<E> extends Abstra
996          }
997  
998          @Override
999 <        @SuppressWarnings("unchecked")
1000 <        public void forEachRemaining(Consumer<? super E> consumer) {
921 <            Objects.requireNonNull(consumer);
999 >        public void forEachRemaining(Consumer<? super E> action) {
1000 >            Objects.requireNonNull(action);
1001              final int size = ArrayList.this.size;
1002              int i = cursor;
1003 <            if (i >= size) {
1004 <                return;
1005 <            }
1006 <            final Object[] elementData = ArrayList.this.elementData;
1007 <            if (i >= elementData.length) {
1008 <                throw new ConcurrentModificationException();
1009 <            }
1010 <            while (i != size && modCount == expectedModCount) {
1011 <                consumer.accept((E) elementData[i++]);
1003 >            if (i < size) {
1004 >                final Object[] es = elementData;
1005 >                if (i >= es.length)
1006 >                    throw new ConcurrentModificationException();
1007 >                for (; i < size && modCount == expectedModCount; i++)
1008 >                    action.accept(elementAt(es, i));
1009 >                // update once at end to reduce heap write traffic
1010 >                cursor = i;
1011 >                lastRet = i - 1;
1012 >                checkForComodification();
1013              }
934            // update once at end of iteration to reduce heap write traffic
935            cursor = i;
936            lastRet = i - 1;
937            checkForComodification();
1014          }
1015  
1016          final void checkForComodification() {
# Line 1063 | Line 1139 | public class ArrayList<E> extends Abstra
1139              this.parent = parent;
1140              this.offset = parent.offset + fromIndex;
1141              this.size = toIndex - fromIndex;
1142 <            this.modCount = root.modCount;
1142 >            this.modCount = parent.modCount;
1143          }
1144  
1145          public E set(int index, E element) {
# Line 1121 | Line 1197 | public class ArrayList<E> extends Abstra
1197              return true;
1198          }
1199  
1200 +        public void replaceAll(UnaryOperator<E> operator) {
1201 +            root.replaceAllRange(operator, offset, offset + size);
1202 +        }
1203 +
1204          public boolean removeAll(Collection<?> c) {
1205              return batchRemove(c, false);
1206          }
1207 +
1208          public boolean retainAll(Collection<?> c) {
1209              return batchRemove(c, true);
1210          }
# Line 1147 | Line 1228 | public class ArrayList<E> extends Abstra
1228              return modified;
1229          }
1230  
1231 +        public Object[] toArray() {
1232 +            checkForComodification();
1233 +            return Arrays.copyOfRange(root.elementData, offset, offset + size);
1234 +        }
1235 +
1236 +        @SuppressWarnings("unchecked")
1237 +        public <T> T[] toArray(T[] a) {
1238 +            checkForComodification();
1239 +            if (a.length < size)
1240 +                return (T[]) Arrays.copyOfRange(
1241 +                        root.elementData, offset, offset + size, a.getClass());
1242 +            System.arraycopy(root.elementData, offset, a, 0, size);
1243 +            if (a.length > size)
1244 +                a[size] = null;
1245 +            return a;
1246 +        }
1247 +
1248 +        public boolean equals(Object o) {
1249 +            if (o == this) {
1250 +                return true;
1251 +            }
1252 +
1253 +            if (!(o instanceof List)) {
1254 +                return false;
1255 +            }
1256 +
1257 +            boolean equal = root.equalsRange((List<?>)o, offset, offset + size);
1258 +            checkForComodification();
1259 +            return equal;
1260 +        }
1261 +
1262 +        public int hashCode() {
1263 +            int hash = root.hashCodeRange(offset, offset + size);
1264 +            checkForComodification();
1265 +            return hash;
1266 +        }
1267 +
1268 +        public int indexOf(Object o) {
1269 +            int index = root.indexOfRange(o, offset, offset + size);
1270 +            checkForComodification();
1271 +            return index >= 0 ? index - offset : -1;
1272 +        }
1273 +
1274 +        public int lastIndexOf(Object o) {
1275 +            int index = root.lastIndexOfRange(o, offset, offset + size);
1276 +            checkForComodification();
1277 +            return index >= 0 ? index - offset : -1;
1278 +        }
1279 +
1280 +        public boolean contains(Object o) {
1281 +            return indexOf(o) >= 0;
1282 +        }
1283 +
1284          public Iterator<E> iterator() {
1285              return listIterator();
1286          }
# Line 1158 | Line 1292 | public class ArrayList<E> extends Abstra
1292              return new ListIterator<E>() {
1293                  int cursor = index;
1294                  int lastRet = -1;
1295 <                int expectedModCount = root.modCount;
1295 >                int expectedModCount = SubList.this.modCount;
1296  
1297                  public boolean hasNext() {
1298                      return cursor != SubList.this.size;
# Line 1194 | Line 1328 | public class ArrayList<E> extends Abstra
1328                      return (E) elementData[offset + (lastRet = i)];
1329                  }
1330  
1331 <                @SuppressWarnings("unchecked")
1332 <                public void forEachRemaining(Consumer<? super E> consumer) {
1199 <                    Objects.requireNonNull(consumer);
1331 >                public void forEachRemaining(Consumer<? super E> action) {
1332 >                    Objects.requireNonNull(action);
1333                      final int size = SubList.this.size;
1334                      int i = cursor;
1335 <                    if (i >= size) {
1336 <                        return;
1337 <                    }
1338 <                    final Object[] elementData = root.elementData;
1339 <                    if (offset + i >= elementData.length) {
1340 <                        throw new ConcurrentModificationException();
1341 <                    }
1342 <                    while (i != size && modCount == expectedModCount) {
1343 <                        consumer.accept((E) elementData[offset + (i++)]);
1335 >                    if (i < size) {
1336 >                        final Object[] es = root.elementData;
1337 >                        if (offset + i >= es.length)
1338 >                            throw new ConcurrentModificationException();
1339 >                        for (; i < size && root.modCount == expectedModCount; i++)
1340 >                            action.accept(elementAt(es, offset + i));
1341 >                        // update once at end to reduce heap write traffic
1342 >                        cursor = i;
1343 >                        lastRet = i - 1;
1344 >                        checkForComodification();
1345                      }
1212                    // update once at end of iteration to reduce heap write traffic
1213                    lastRet = cursor = i;
1214                    checkForComodification();
1346                  }
1347  
1348                  public int nextIndex() {
# Line 1231 | Line 1362 | public class ArrayList<E> extends Abstra
1362                          SubList.this.remove(lastRet);
1363                          cursor = lastRet;
1364                          lastRet = -1;
1365 <                        expectedModCount = root.modCount;
1365 >                        expectedModCount = SubList.this.modCount;
1366                      } catch (IndexOutOfBoundsException ex) {
1367                          throw new ConcurrentModificationException();
1368                      }
# Line 1257 | Line 1388 | public class ArrayList<E> extends Abstra
1388                          SubList.this.add(i, e);
1389                          cursor = i + 1;
1390                          lastRet = -1;
1391 <                        expectedModCount = root.modCount;
1391 >                        expectedModCount = SubList.this.modCount;
1392                      } catch (IndexOutOfBoundsException ex) {
1393                          throw new ConcurrentModificationException();
1394                      }
# Line 1301 | Line 1432 | public class ArrayList<E> extends Abstra
1432          public Spliterator<E> spliterator() {
1433              checkForComodification();
1434  
1435 <            // ArrayListSpliterator is not used because late-binding logic
1436 <            // is different here
1306 <            return new Spliterator<>() {
1435 >            // ArrayListSpliterator not used here due to late-binding
1436 >            return new Spliterator<E>() {
1437                  private int index = offset; // current index, modified on advance/split
1438                  private int fence = -1; // -1 until used; then one past last index
1439                  private int expectedModCount; // initialized when fence set
# Line 1317 | Line 1447 | public class ArrayList<E> extends Abstra
1447                      return hi;
1448                  }
1449  
1450 <                public ArrayListSpliterator<E> trySplit() {
1450 >                public ArrayList<E>.ArrayListSpliterator trySplit() {
1451                      int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
1452 <                    // ArrayListSpliterator could be used here as the source is already bound
1452 >                    // ArrayListSpliterator can be used here as the source is already bound
1453                      return (lo >= mid) ? null : // divide range in half unless too small
1454 <                        new ArrayListSpliterator<>(root, lo, index = mid,
1325 <                                                   expectedModCount);
1454 >                        root.new ArrayListSpliterator(lo, index = mid, expectedModCount);
1455                  }
1456  
1457                  public boolean tryAdvance(Consumer<? super E> action) {
# Line 1364 | Line 1493 | public class ArrayList<E> extends Abstra
1493                  }
1494  
1495                  public long estimateSize() {
1496 <                    return (long) (getFence() - index);
1496 >                    return getFence() - index;
1497                  }
1498  
1499                  public int characteristics() {
# Line 1374 | Line 1503 | public class ArrayList<E> extends Abstra
1503          }
1504      }
1505  
1506 +    /**
1507 +     * @throws NullPointerException {@inheritDoc}
1508 +     */
1509      @Override
1510      public void forEach(Consumer<? super E> action) {
1511          Objects.requireNonNull(action);
1512          final int expectedModCount = modCount;
1513          final Object[] es = elementData;
1514          final int size = this.size;
1515 <        for (int i = 0; modCount == expectedModCount && i < size; i++) {
1515 >        for (int i = 0; modCount == expectedModCount && i < size; i++)
1516              action.accept(elementAt(es, i));
1517 <        }
1386 <        if (modCount != expectedModCount) {
1517 >        if (modCount != expectedModCount)
1518              throw new ConcurrentModificationException();
1388        }
1519      }
1520  
1521      /**
# Line 1403 | Line 1533 | public class ArrayList<E> extends Abstra
1533       */
1534      @Override
1535      public Spliterator<E> spliterator() {
1536 <        return new ArrayListSpliterator<>(this, 0, -1, 0);
1536 >        return new ArrayListSpliterator(0, -1, 0);
1537      }
1538  
1539      /** Index-based split-by-two, lazily initialized Spliterator */
1540 <    static final class ArrayListSpliterator<E> implements Spliterator<E> {
1540 >    final class ArrayListSpliterator implements Spliterator<E> {
1541  
1542          /*
1543           * If ArrayLists were immutable, or structurally immutable (no
# Line 1441 | Line 1571 | public class ArrayList<E> extends Abstra
1571           * these streamlinings.
1572           */
1573  
1444        private final ArrayList<E> list;
1574          private int index; // current index, modified on advance/split
1575          private int fence; // -1 until used; then one past last index
1576          private int expectedModCount; // initialized when fence set
1577  
1578 <        /** Create new spliterator covering the given range */
1579 <        ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
1451 <                             int expectedModCount) {
1452 <            this.list = list; // OK if null unless traversed
1578 >        /** Creates new spliterator covering the given range. */
1579 >        ArrayListSpliterator(int origin, int fence, int expectedModCount) {
1580              this.index = origin;
1581              this.fence = fence;
1582              this.expectedModCount = expectedModCount;
# Line 1457 | Line 1584 | public class ArrayList<E> extends Abstra
1584  
1585          private int getFence() { // initialize fence to size on first use
1586              int hi; // (a specialized variant appears in method forEach)
1460            ArrayList<E> lst;
1587              if ((hi = fence) < 0) {
1588 <                if ((lst = list) == null)
1589 <                    hi = fence = 0;
1464 <                else {
1465 <                    expectedModCount = lst.modCount;
1466 <                    hi = fence = lst.size;
1467 <                }
1588 >                expectedModCount = modCount;
1589 >                hi = fence = size;
1590              }
1591              return hi;
1592          }
1593  
1594 <        public ArrayListSpliterator<E> trySplit() {
1594 >        public ArrayListSpliterator trySplit() {
1595              int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
1596              return (lo >= mid) ? null : // divide range in half unless too small
1597 <                new ArrayListSpliterator<>(list, lo, index = mid,
1476 <                                           expectedModCount);
1597 >                new ArrayListSpliterator(lo, index = mid, expectedModCount);
1598          }
1599  
1600          public boolean tryAdvance(Consumer<? super E> action) {
# Line 1482 | Line 1603 | public class ArrayList<E> extends Abstra
1603              int hi = getFence(), i = index;
1604              if (i < hi) {
1605                  index = i + 1;
1606 <                @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
1606 >                @SuppressWarnings("unchecked") E e = (E)elementData[i];
1607                  action.accept(e);
1608 <                if (list.modCount != expectedModCount)
1608 >                if (modCount != expectedModCount)
1609                      throw new ConcurrentModificationException();
1610                  return true;
1611              }
# Line 1493 | Line 1614 | public class ArrayList<E> extends Abstra
1614  
1615          public void forEachRemaining(Consumer<? super E> action) {
1616              int i, hi, mc; // hoist accesses and checks from loop
1617 <            ArrayList<E> lst; Object[] a;
1617 >            Object[] a;
1618              if (action == null)
1619                  throw new NullPointerException();
1620 <            if ((lst = list) != null && (a = lst.elementData) != null) {
1620 >            if ((a = elementData) != null) {
1621                  if ((hi = fence) < 0) {
1622 <                    mc = lst.modCount;
1623 <                    hi = lst.size;
1622 >                    mc = modCount;
1623 >                    hi = size;
1624                  }
1625                  else
1626                      mc = expectedModCount;
# Line 1508 | Line 1629 | public class ArrayList<E> extends Abstra
1629                          @SuppressWarnings("unchecked") E e = (E) a[i];
1630                          action.accept(e);
1631                      }
1632 <                    if (lst.modCount == mc)
1632 >                    if (modCount == mc)
1633                          return;
1634                  }
1635              }
# Line 1516 | Line 1637 | public class ArrayList<E> extends Abstra
1637          }
1638  
1639          public long estimateSize() {
1640 <            return (long) (getFence() - index);
1640 >            return getFence() - index;
1641          }
1642  
1643          public int characteristics() {
# Line 1536 | Line 1657 | public class ArrayList<E> extends Abstra
1657          return (bits[i >> 6] & (1L << i)) == 0;
1658      }
1659  
1660 +    /**
1661 +     * @throws NullPointerException {@inheritDoc}
1662 +     */
1663      @Override
1664      public boolean removeIf(Predicate<? super E> filter) {
1665          return removeIf(filter, 0, size);
1666      }
1667  
1668 <    boolean removeIf(Predicate<? super E> filter,
1669 <                     final int from, final int end) {
1668 >    /**
1669 >     * Removes all elements satisfying the given predicate, from index
1670 >     * i (inclusive) to index end (exclusive).
1671 >     */
1672 >    boolean removeIf(Predicate<? super E> filter, int i, final int end) {
1673          Objects.requireNonNull(filter);
1674          int expectedModCount = modCount;
1675          final Object[] es = elementData;
1549        final boolean modified;
1550        int i;
1676          // Optimize for initial run of survivors
1677 <        for (i = from; i < end && !filter.test(elementAt(es, i)); i++)
1677 >        for (; i < end && !filter.test(elementAt(es, i)); i++)
1678              ;
1679          // Tolerate predicates that reentrantly access the collection for
1680          // read (but writers still get CME), so traverse once to find
1681          // elements to delete, a second pass to physically expunge.
1682 <        if (modified = (i < end)) {
1558 <            expectedModCount++;
1559 <            modCount++;
1682 >        if (i < end) {
1683              final int beg = i;
1684              final long[] deathRow = nBits(end - beg);
1685              deathRow[0] = 1L;   // set bit 0
# Line 1565 | Line 1688 | public class ArrayList<E> extends Abstra
1688                      setBit(deathRow, i - beg);
1689              if (modCount != expectedModCount)
1690                  throw new ConcurrentModificationException();
1691 +            modCount++;
1692              int w = beg;
1693              for (i = beg; i < end; i++)
1694                  if (isClear(deathRow, i - beg))
1695                      es[w++] = es[i];
1696 <            final int oldSize = size;
1697 <            System.arraycopy(es, end, es, w, oldSize - end);
1698 <            Arrays.fill(es, size -= (end - w), oldSize, null);
1696 >            shiftTailOverGap(es, w, end);
1697 >            // checkInvariants();
1698 >            return true;
1699 >        } else {
1700 >            if (modCount != expectedModCount)
1701 >                throw new ConcurrentModificationException();
1702 >            // checkInvariants();
1703 >            return false;
1704          }
1576        if (modCount != expectedModCount)
1577            throw new ConcurrentModificationException();
1578        return modified;
1705      }
1706  
1707      @Override
1708      public void replaceAll(UnaryOperator<E> operator) {
1709 +        replaceAllRange(operator, 0, size);
1710 +        // TODO(8203662): remove increment of modCount from ...
1711 +        modCount++;
1712 +    }
1713 +
1714 +    private void replaceAllRange(UnaryOperator<E> operator, int i, int end) {
1715          Objects.requireNonNull(operator);
1716          final int expectedModCount = modCount;
1717          final Object[] es = elementData;
1718 <        final int size = this.size;
1587 <        for (int i=0; modCount == expectedModCount && i < size; i++) {
1718 >        for (; modCount == expectedModCount && i < end; i++)
1719              es[i] = operator.apply(elementAt(es, i));
1720 <        }
1590 <        if (modCount != expectedModCount) {
1720 >        if (modCount != expectedModCount)
1721              throw new ConcurrentModificationException();
1722 <        }
1593 <        modCount++;
1722 >        // checkInvariants();
1723      }
1724  
1725      @Override
# Line 1598 | Line 1727 | public class ArrayList<E> extends Abstra
1727      public void sort(Comparator<? super E> c) {
1728          final int expectedModCount = modCount;
1729          Arrays.sort((E[]) elementData, 0, size, c);
1730 <        if (modCount != expectedModCount) {
1730 >        if (modCount != expectedModCount)
1731              throw new ConcurrentModificationException();
1603        }
1732          modCount++;
1733 +        // checkInvariants();
1734 +    }
1735 +
1736 +    void checkInvariants() {
1737 +        // assert size >= 0;
1738 +        // assert size == elementData.length || elementData[size] == null;
1739      }
1740   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines