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.44 by jsr166, Wed Nov 16 00:17:25 2016 UTC vs.
Revision 1.71 by jsr166, Fri Jul 24 20:57:26 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 175 | Line 178 | public class ArrayList<E> extends Abstra
178       * @throws NullPointerException if the specified collection is null
179       */
180      public ArrayList(Collection<? extends E> c) {
181 <        elementData = c.toArray();
182 <        if ((size = elementData.length) != 0) {
183 <            // defend against c.toArray (incorrectly) not returning Object[]
184 <            // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
185 <            if (elementData.getClass() != Object[].class)
186 <                elementData = Arrays.copyOf(elementData, size, Object[].class);
181 >        Object[] a = c.toArray();
182 >        if ((size = a.length) != 0) {
183 >            if (c.getClass() == ArrayList.class) {
184 >                elementData = a;
185 >            } else {
186 >                elementData = Arrays.copyOf(a, size, Object[].class);
187 >            }
188          } else {
189              // replace with empty array.
190 <            this.elementData = EMPTY_ELEMENTDATA;
190 >            elementData = EMPTY_ELEMENTDATA;
191          }
192      }
193  
# Line 218 | Line 222 | public class ArrayList<E> extends Abstra
222      }
223  
224      /**
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    /**
225       * Increases the capacity to ensure that it can hold at least the
226       * number of elements specified by the minimum capacity argument.
227       *
# Line 233 | Line 229 | public class ArrayList<E> extends Abstra
229       * @throws OutOfMemoryError if minCapacity is less than zero
230       */
231      private Object[] grow(int minCapacity) {
232 <        return elementData = Arrays.copyOf(elementData,
233 <                                           newCapacity(minCapacity));
232 >        int oldCapacity = elementData.length;
233 >        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
234 >            int newCapacity = ArraysSupport.newLength(oldCapacity,
235 >                    minCapacity - oldCapacity, /* minimum growth */
236 >                    oldCapacity >> 1           /* preferred growth */);
237 >            return elementData = Arrays.copyOf(elementData, newCapacity);
238 >        } else {
239 >            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
240 >        }
241      }
242  
243      private Object[] grow() {
# Line 242 | Line 245 | public class ArrayList<E> extends Abstra
245      }
246  
247      /**
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    /**
248       * Returns the number of elements in this list.
249       *
250       * @return the number of elements in this list
# Line 313 | Line 283 | public class ArrayList<E> extends Abstra
283       * or -1 if there is no such index.
284       */
285      public int indexOf(Object o) {
286 +        return indexOfRange(o, 0, size);
287 +    }
288 +
289 +    int indexOfRange(Object o, int start, int end) {
290 +        Object[] es = elementData;
291          if (o == null) {
292 <            for (int i = 0; i < size; i++)
293 <                if (elementData[i]==null)
292 >            for (int i = start; i < end; i++) {
293 >                if (es[i] == null) {
294                      return i;
295 +                }
296 +            }
297          } else {
298 <            for (int i = 0; i < size; i++)
299 <                if (o.equals(elementData[i]))
298 >            for (int i = start; i < end; i++) {
299 >                if (o.equals(es[i])) {
300                      return i;
301 +                }
302 +            }
303          }
304          return -1;
305      }
# Line 333 | Line 312 | public class ArrayList<E> extends Abstra
312       * or -1 if there is no such index.
313       */
314      public int lastIndexOf(Object o) {
315 +        return lastIndexOfRange(o, 0, size);
316 +    }
317 +
318 +    int lastIndexOfRange(Object o, int start, int end) {
319 +        Object[] es = elementData;
320          if (o == null) {
321 <            for (int i = size-1; i >= 0; i--)
322 <                if (elementData[i]==null)
321 >            for (int i = end - 1; i >= start; i--) {
322 >                if (es[i] == null) {
323                      return i;
324 +                }
325 +            }
326          } else {
327 <            for (int i = size-1; i >= 0; i--)
328 <                if (o.equals(elementData[i]))
327 >            for (int i = end - 1; i >= start; i--) {
328 >                if (o.equals(es[i])) {
329                      return i;
330 +                }
331 +            }
332          }
333          return -1;
334      }
# Line 515 | Line 503 | public class ArrayList<E> extends Abstra
503       */
504      public E remove(int index) {
505          Objects.checkIndex(index, size);
506 +        final Object[] es = elementData;
507  
508 <        modCount++;
509 <        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
508 >        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
509 >        fastRemove(es, index);
510  
511          // checkInvariants();
512          return oldValue;
513      }
514  
515      /**
516 +     * {@inheritDoc}
517 +     */
518 +    public boolean equals(Object o) {
519 +        if (o == this) {
520 +            return true;
521 +        }
522 +
523 +        if (!(o instanceof List)) {
524 +            return false;
525 +        }
526 +
527 +        final int expectedModCount = modCount;
528 +        // ArrayList can be subclassed and given arbitrary behavior, but we can
529 +        // still deal with the common case where o is ArrayList precisely
530 +        boolean equal = (o.getClass() == ArrayList.class)
531 +            ? equalsArrayList((ArrayList<?>) o)
532 +            : equalsRange((List<?>) o, 0, size);
533 +
534 +        checkForComodification(expectedModCount);
535 +        return equal;
536 +    }
537 +
538 +    boolean equalsRange(List<?> other, int from, int to) {
539 +        final Object[] es = elementData;
540 +        if (to > es.length) {
541 +            throw new ConcurrentModificationException();
542 +        }
543 +        var oit = other.iterator();
544 +        for (; from < to; from++) {
545 +            if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) {
546 +                return false;
547 +            }
548 +        }
549 +        return !oit.hasNext();
550 +    }
551 +
552 +    private boolean equalsArrayList(ArrayList<?> other) {
553 +        final int otherModCount = other.modCount;
554 +        final int s = size;
555 +        boolean equal;
556 +        if (equal = (s == other.size)) {
557 +            final Object[] otherEs = other.elementData;
558 +            final Object[] es = elementData;
559 +            if (s > es.length || s > otherEs.length) {
560 +                throw new ConcurrentModificationException();
561 +            }
562 +            for (int i = 0; i < s; i++) {
563 +                if (!Objects.equals(es[i], otherEs[i])) {
564 +                    equal = false;
565 +                    break;
566 +                }
567 +            }
568 +        }
569 +        other.checkForComodification(otherModCount);
570 +        return equal;
571 +    }
572 +
573 +    private void checkForComodification(final int expectedModCount) {
574 +        if (modCount != expectedModCount) {
575 +            throw new ConcurrentModificationException();
576 +        }
577 +    }
578 +
579 +    /**
580 +     * {@inheritDoc}
581 +     */
582 +    public int hashCode() {
583 +        int expectedModCount = modCount;
584 +        int hash = hashCodeRange(0, size);
585 +        checkForComodification(expectedModCount);
586 +        return hash;
587 +    }
588 +
589 +    int hashCodeRange(int from, int to) {
590 +        final Object[] es = elementData;
591 +        if (to > es.length) {
592 +            throw new ConcurrentModificationException();
593 +        }
594 +        int hashCode = 1;
595 +        for (int i = from; i < to; i++) {
596 +            Object e = es[i];
597 +            hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
598 +        }
599 +        return hashCode;
600 +    }
601 +
602 +    /**
603       * Removes the first occurrence of the specified element from this list,
604       * if it is present.  If the list does not contain the element, it is
605       * unchanged.  More formally, removes the element with the lowest index
# Line 543 | Line 613 | public class ArrayList<E> extends Abstra
613       * @return {@code true} if this list contained the specified element
614       */
615      public boolean remove(Object o) {
616 <        if (o == null) {
617 <            for (int index = 0; index < size; index++)
618 <                if (elementData[index] == null) {
619 <                    fastRemove(index);
620 <                    return true;
621 <                }
622 <        } else {
623 <            for (int index = 0; index < size; index++)
624 <                if (o.equals(elementData[index])) {
625 <                    fastRemove(index);
626 <                    return true;
627 <                }
616 >        final Object[] es = elementData;
617 >        final int size = this.size;
618 >        int i = 0;
619 >        found: {
620 >            if (o == null) {
621 >                for (; i < size; i++)
622 >                    if (es[i] == null)
623 >                        break found;
624 >            } else {
625 >                for (; i < size; i++)
626 >                    if (o.equals(es[i]))
627 >                        break found;
628 >            }
629 >            return false;
630          }
631 <        return false;
631 >        fastRemove(es, i);
632 >        return true;
633      }
634  
635      /**
636       * Private remove method that skips bounds checking and does not
637       * return the value removed.
638       */
639 <    private void fastRemove(int index) {
639 >    private void fastRemove(Object[] es, int i) {
640          modCount++;
641 <        int numMoved = size - index - 1;
642 <        if (numMoved > 0)
643 <            System.arraycopy(elementData, index+1, elementData, index,
644 <                             numMoved);
572 <        elementData[--size] = null; // clear to let GC do its work
641 >        final int newSize;
642 >        if ((newSize = size - 1) > i)
643 >            System.arraycopy(es, i + 1, es, i, newSize - i);
644 >        es[size = newSize] = null;
645      }
646  
647      /**
# Line 578 | Line 650 | public class ArrayList<E> extends Abstra
650       */
651      public void clear() {
652          modCount++;
653 <        Arrays.fill(elementData, 0, size, null);
654 <        size = 0;
653 >        final Object[] es = elementData;
654 >        for (int to = size, i = size = 0; i < to; i++)
655 >            es[i] = null;
656      }
657  
658      /**
# Line 669 | Line 742 | public class ArrayList<E> extends Abstra
742                      outOfBoundsMsg(fromIndex, toIndex));
743          }
744          modCount++;
745 <        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);
745 >        shiftTailOverGap(elementData, fromIndex, toIndex);
746          // checkInvariants();
747      }
748  
749 +    /** Erases the gap from lo to hi, by sliding down following elements. */
750 +    private void shiftTailOverGap(Object[] es, int lo, int hi) {
751 +        System.arraycopy(es, hi, es, lo, size - hi);
752 +        for (int to = size, i = (size -= hi - lo); i < to; i++)
753 +            es[i] = null;
754 +    }
755 +
756      /**
757       * A version of rangeCheck used by add and addAll.
758       */
# Line 743 | Line 820 | public class ArrayList<E> extends Abstra
820                          final int from, final int end) {
821          Objects.requireNonNull(c);
822          final Object[] es = elementData;
746        final boolean modified;
823          int r;
824          // Optimize for initial run of survivors
825 <        for (r = from; r < end && c.contains(es[r]) == complement; r++)
826 <            ;
827 <        if (modified = (r < end)) {
828 <            int w = r++;
829 <            try {
830 <                for (Object e; r < end; r++)
831 <                    if (c.contains(e = es[r]) == complement)
832 <                        es[w++] = e;
833 <            } catch (Throwable ex) {
834 <                // Preserve behavioral compatibility with AbstractCollection,
835 <                // even if c.contains() throws.
836 <                System.arraycopy(es, r, es, w, end - r);
837 <                w += end - r;
838 <                throw ex;
839 <            } finally {
840 <                final int oldSize = size, deleted = end - w;
841 <                modCount += deleted;
842 <                System.arraycopy(es, end, es, w, oldSize - end);
843 <                Arrays.fill(es, size -= deleted, oldSize, null);
844 <            }
825 >        for (r = from;; r++) {
826 >            if (r == end)
827 >                return false;
828 >            if (c.contains(es[r]) != complement)
829 >                break;
830 >        }
831 >        int w = r++;
832 >        try {
833 >            for (Object e; r < end; r++)
834 >                if (c.contains(e = es[r]) == complement)
835 >                    es[w++] = e;
836 >        } catch (Throwable ex) {
837 >            // Preserve behavioral compatibility with AbstractCollection,
838 >            // even if c.contains() throws.
839 >            System.arraycopy(es, r, es, w, end - r);
840 >            w += end - r;
841 >            throw ex;
842 >        } finally {
843 >            modCount += end - w;
844 >            shiftTailOverGap(es, w, end);
845          }
846          // checkInvariants();
847 <        return modified;
847 >        return true;
848      }
849  
850      /**
851 <     * Save the state of the {@code ArrayList} instance to a stream (that
852 <     * is, serialize it).
851 >     * Saves the state of the {@code ArrayList} instance to a stream
852 >     * (that is, serializes it).
853       *
854 +     * @param s the stream
855 +     * @throws java.io.IOException if an I/O error occurs
856       * @serialData The length of the array backing the {@code ArrayList}
857       *             instance is emitted (int), followed by all of its elements
858       *             (each an {@code Object}) in the proper order.
859       */
860 +    // OPENJDK @java.io.Serial
861      private void writeObject(java.io.ObjectOutputStream s)
862 <        throws java.io.IOException{
862 >        throws java.io.IOException {
863          // Write out element count, and any hidden stuff
864          int expectedModCount = modCount;
865          s.defaultWriteObject();
866  
867 <        // Write out size as capacity for behavioural compatibility with clone()
867 >        // Write out size as capacity for behavioral compatibility with clone()
868          s.writeInt(size);
869  
870          // Write out all elements in the proper order.
# Line 799 | Line 878 | public class ArrayList<E> extends Abstra
878      }
879  
880      /**
881 <     * Reconstitute the {@code ArrayList} instance from a stream (that is,
882 <     * deserialize it).
881 >     * Reconstitutes the {@code ArrayList} instance from a stream (that is,
882 >     * deserializes it).
883 >     * @param s the stream
884 >     * @throws ClassNotFoundException if the class of a serialized object
885 >     *         could not be found
886 >     * @throws java.io.IOException if an I/O error occurs
887       */
888 +    // OPENJDK @java.io.Serial
889      private void readObject(java.io.ObjectInputStream s)
890          throws java.io.IOException, ClassNotFoundException {
891  
# Line 813 | Line 897 | public class ArrayList<E> extends Abstra
897  
898          if (size > 0) {
899              // like clone(), allocate array based upon size not capacity
900 +            jsr166.Platform.checkArray(s, Object[].class, size);
901              Object[] elements = new Object[size];
902  
903              // Read in all elements in the proper order.
# Line 1055 | Line 1140 | public class ArrayList<E> extends Abstra
1140              this.parent = parent;
1141              this.offset = parent.offset + fromIndex;
1142              this.size = toIndex - fromIndex;
1143 <            this.modCount = root.modCount;
1143 >            this.modCount = parent.modCount;
1144          }
1145  
1146          public E set(int index, E element) {
# Line 1113 | Line 1198 | public class ArrayList<E> extends Abstra
1198              return true;
1199          }
1200  
1201 +        public void replaceAll(UnaryOperator<E> operator) {
1202 +            root.replaceAllRange(operator, offset, offset + size);
1203 +        }
1204 +
1205          public boolean removeAll(Collection<?> c) {
1206              return batchRemove(c, false);
1207          }
# Line 1140 | Line 1229 | public class ArrayList<E> extends Abstra
1229              return modified;
1230          }
1231  
1232 +        public Object[] toArray() {
1233 +            checkForComodification();
1234 +            return Arrays.copyOfRange(root.elementData, offset, offset + size);
1235 +        }
1236 +
1237 +        @SuppressWarnings("unchecked")
1238 +        public <T> T[] toArray(T[] a) {
1239 +            checkForComodification();
1240 +            if (a.length < size)
1241 +                return (T[]) Arrays.copyOfRange(
1242 +                        root.elementData, offset, offset + size, a.getClass());
1243 +            System.arraycopy(root.elementData, offset, a, 0, size);
1244 +            if (a.length > size)
1245 +                a[size] = null;
1246 +            return a;
1247 +        }
1248 +
1249 +        public boolean equals(Object o) {
1250 +            if (o == this) {
1251 +                return true;
1252 +            }
1253 +
1254 +            if (!(o instanceof List)) {
1255 +                return false;
1256 +            }
1257 +
1258 +            boolean equal = root.equalsRange((List<?>)o, offset, offset + size);
1259 +            checkForComodification();
1260 +            return equal;
1261 +        }
1262 +
1263 +        public int hashCode() {
1264 +            int hash = root.hashCodeRange(offset, offset + size);
1265 +            checkForComodification();
1266 +            return hash;
1267 +        }
1268 +
1269 +        public int indexOf(Object o) {
1270 +            int index = root.indexOfRange(o, offset, offset + size);
1271 +            checkForComodification();
1272 +            return index >= 0 ? index - offset : -1;
1273 +        }
1274 +
1275 +        public int lastIndexOf(Object o) {
1276 +            int index = root.lastIndexOfRange(o, offset, offset + size);
1277 +            checkForComodification();
1278 +            return index >= 0 ? index - offset : -1;
1279 +        }
1280 +
1281 +        public boolean contains(Object o) {
1282 +            return indexOf(o) >= 0;
1283 +        }
1284 +
1285          public Iterator<E> iterator() {
1286              return listIterator();
1287          }
# Line 1151 | Line 1293 | public class ArrayList<E> extends Abstra
1293              return new ListIterator<E>() {
1294                  int cursor = index;
1295                  int lastRet = -1;
1296 <                int expectedModCount = root.modCount;
1296 >                int expectedModCount = SubList.this.modCount;
1297  
1298                  public boolean hasNext() {
1299                      return cursor != SubList.this.size;
# Line 1195 | Line 1337 | public class ArrayList<E> extends Abstra
1337                          final Object[] es = root.elementData;
1338                          if (offset + i >= es.length)
1339                              throw new ConcurrentModificationException();
1340 <                        for (; i < size && modCount == expectedModCount; i++)
1340 >                        for (; i < size && root.modCount == expectedModCount; i++)
1341                              action.accept(elementAt(es, offset + i));
1342                          // update once at end to reduce heap write traffic
1343                          cursor = i;
# Line 1221 | Line 1363 | public class ArrayList<E> extends Abstra
1363                          SubList.this.remove(lastRet);
1364                          cursor = lastRet;
1365                          lastRet = -1;
1366 <                        expectedModCount = root.modCount;
1366 >                        expectedModCount = SubList.this.modCount;
1367                      } catch (IndexOutOfBoundsException ex) {
1368                          throw new ConcurrentModificationException();
1369                      }
# Line 1247 | Line 1389 | public class ArrayList<E> extends Abstra
1389                          SubList.this.add(i, e);
1390                          cursor = i + 1;
1391                          lastRet = -1;
1392 <                        expectedModCount = root.modCount;
1392 >                        expectedModCount = SubList.this.modCount;
1393                      } catch (IndexOutOfBoundsException ex) {
1394                          throw new ConcurrentModificationException();
1395                      }
# Line 1291 | Line 1433 | public class ArrayList<E> extends Abstra
1433          public Spliterator<E> spliterator() {
1434              checkForComodification();
1435  
1436 <            // ArrayListSpliterator is not used because late-binding logic
1437 <            // is different here
1296 <            return new Spliterator<>() {
1436 >            // ArrayListSpliterator not used here due to late-binding
1437 >            return new Spliterator<E>() {
1438                  private int index = offset; // current index, modified on advance/split
1439                  private int fence = -1; // -1 until used; then one past last index
1440                  private int expectedModCount; // initialized when fence set
# Line 1307 | Line 1448 | public class ArrayList<E> extends Abstra
1448                      return hi;
1449                  }
1450  
1451 <                public ArrayListSpliterator<E> trySplit() {
1451 >                public ArrayList<E>.ArrayListSpliterator trySplit() {
1452                      int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
1453 <                    // ArrayListSpliterator could be used here as the source is already bound
1453 >                    // ArrayListSpliterator can be used here as the source is already bound
1454                      return (lo >= mid) ? null : // divide range in half unless too small
1455 <                        new ArrayListSpliterator<>(root, lo, index = mid,
1315 <                                                   expectedModCount);
1455 >                        root.new ArrayListSpliterator(lo, index = mid, expectedModCount);
1456                  }
1457  
1458                  public boolean tryAdvance(Consumer<? super E> action) {
# Line 1354 | Line 1494 | public class ArrayList<E> extends Abstra
1494                  }
1495  
1496                  public long estimateSize() {
1497 <                    return (long) (getFence() - index);
1497 >                    return getFence() - index;
1498                  }
1499  
1500                  public int characteristics() {
# Line 1364 | Line 1504 | public class ArrayList<E> extends Abstra
1504          }
1505      }
1506  
1507 +    /**
1508 +     * @throws NullPointerException {@inheritDoc}
1509 +     */
1510      @Override
1511      public void forEach(Consumer<? super E> action) {
1512          Objects.requireNonNull(action);
# Line 1391 | Line 1534 | public class ArrayList<E> extends Abstra
1534       */
1535      @Override
1536      public Spliterator<E> spliterator() {
1537 <        return new ArrayListSpliterator<>(this, 0, -1, 0);
1537 >        return new ArrayListSpliterator(0, -1, 0);
1538      }
1539  
1540      /** Index-based split-by-two, lazily initialized Spliterator */
1541 <    static final class ArrayListSpliterator<E> implements Spliterator<E> {
1541 >    final class ArrayListSpliterator implements Spliterator<E> {
1542  
1543          /*
1544           * If ArrayLists were immutable, or structurally immutable (no
# Line 1429 | Line 1572 | public class ArrayList<E> extends Abstra
1572           * these streamlinings.
1573           */
1574  
1432        private final ArrayList<E> list;
1575          private int index; // current index, modified on advance/split
1576          private int fence; // -1 until used; then one past last index
1577          private int expectedModCount; // initialized when fence set
1578  
1579 <        /** Create new spliterator covering the given range */
1580 <        ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
1439 <                             int expectedModCount) {
1440 <            this.list = list; // OK if null unless traversed
1579 >        /** Creates new spliterator covering the given range. */
1580 >        ArrayListSpliterator(int origin, int fence, int expectedModCount) {
1581              this.index = origin;
1582              this.fence = fence;
1583              this.expectedModCount = expectedModCount;
# Line 1445 | Line 1585 | public class ArrayList<E> extends Abstra
1585  
1586          private int getFence() { // initialize fence to size on first use
1587              int hi; // (a specialized variant appears in method forEach)
1448            ArrayList<E> lst;
1588              if ((hi = fence) < 0) {
1589 <                if ((lst = list) == null)
1590 <                    hi = fence = 0;
1452 <                else {
1453 <                    expectedModCount = lst.modCount;
1454 <                    hi = fence = lst.size;
1455 <                }
1589 >                expectedModCount = modCount;
1590 >                hi = fence = size;
1591              }
1592              return hi;
1593          }
1594  
1595 <        public ArrayListSpliterator<E> trySplit() {
1595 >        public ArrayListSpliterator trySplit() {
1596              int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
1597              return (lo >= mid) ? null : // divide range in half unless too small
1598 <                new ArrayListSpliterator<>(list, lo, index = mid,
1464 <                                           expectedModCount);
1598 >                new ArrayListSpliterator(lo, index = mid, expectedModCount);
1599          }
1600  
1601          public boolean tryAdvance(Consumer<? super E> action) {
# Line 1470 | Line 1604 | public class ArrayList<E> extends Abstra
1604              int hi = getFence(), i = index;
1605              if (i < hi) {
1606                  index = i + 1;
1607 <                @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
1607 >                @SuppressWarnings("unchecked") E e = (E)elementData[i];
1608                  action.accept(e);
1609 <                if (list.modCount != expectedModCount)
1609 >                if (modCount != expectedModCount)
1610                      throw new ConcurrentModificationException();
1611                  return true;
1612              }
# Line 1481 | Line 1615 | public class ArrayList<E> extends Abstra
1615  
1616          public void forEachRemaining(Consumer<? super E> action) {
1617              int i, hi, mc; // hoist accesses and checks from loop
1618 <            ArrayList<E> lst; Object[] a;
1618 >            Object[] a;
1619              if (action == null)
1620                  throw new NullPointerException();
1621 <            if ((lst = list) != null && (a = lst.elementData) != null) {
1621 >            if ((a = elementData) != null) {
1622                  if ((hi = fence) < 0) {
1623 <                    mc = lst.modCount;
1624 <                    hi = lst.size;
1623 >                    mc = modCount;
1624 >                    hi = size;
1625                  }
1626                  else
1627                      mc = expectedModCount;
# Line 1496 | Line 1630 | public class ArrayList<E> extends Abstra
1630                          @SuppressWarnings("unchecked") E e = (E) a[i];
1631                          action.accept(e);
1632                      }
1633 <                    if (lst.modCount == mc)
1633 >                    if (modCount == mc)
1634                          return;
1635                  }
1636              }
# Line 1504 | Line 1638 | public class ArrayList<E> extends Abstra
1638          }
1639  
1640          public long estimateSize() {
1641 <            return (long) (getFence() - index);
1641 >            return getFence() - index;
1642          }
1643  
1644          public int characteristics() {
# Line 1524 | Line 1658 | public class ArrayList<E> extends Abstra
1658          return (bits[i >> 6] & (1L << i)) == 0;
1659      }
1660  
1661 +    /**
1662 +     * @throws NullPointerException {@inheritDoc}
1663 +     */
1664      @Override
1665      public boolean removeIf(Predicate<? super E> filter) {
1666          return removeIf(filter, 0, size);
# Line 1552 | Line 1689 | public class ArrayList<E> extends Abstra
1689                      setBit(deathRow, i - beg);
1690              if (modCount != expectedModCount)
1691                  throw new ConcurrentModificationException();
1555            expectedModCount++;
1692              modCount++;
1693              int w = beg;
1694              for (i = beg; i < end; i++)
1695                  if (isClear(deathRow, i - beg))
1696                      es[w++] = es[i];
1697 <            final int oldSize = size;
1562 <            System.arraycopy(es, end, es, w, oldSize - end);
1563 <            Arrays.fill(es, size -= (end - w), oldSize, null);
1697 >            shiftTailOverGap(es, w, end);
1698              // checkInvariants();
1699              return true;
1700          } else {
# Line 1573 | Line 1707 | public class ArrayList<E> extends Abstra
1707  
1708      @Override
1709      public void replaceAll(UnaryOperator<E> operator) {
1710 +        replaceAllRange(operator, 0, size);
1711 +        // TODO(8203662): remove increment of modCount from ...
1712 +        modCount++;
1713 +    }
1714 +
1715 +    private void replaceAllRange(UnaryOperator<E> operator, int i, int end) {
1716          Objects.requireNonNull(operator);
1717          final int expectedModCount = modCount;
1718          final Object[] es = elementData;
1719 <        final int size = this.size;
1580 <        for (int i = 0; modCount == expectedModCount && i < size; i++)
1719 >        for (; modCount == expectedModCount && i < end; i++)
1720              es[i] = operator.apply(elementAt(es, i));
1721          if (modCount != expectedModCount)
1722              throw new ConcurrentModificationException();
1584        modCount++;
1723          // checkInvariants();
1724      }
1725  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines