< prev index next >

src/java.base/share/classes/java/util/ArrayList.java

Print this page
rev 11832 : [mq]: 8079136-NestedSubList


 655      */
 656     private void rangeCheck(int index) {
 657         if (index >= size)
 658             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 659     }
 660 
 661     /**
 662      * A version of rangeCheck used by add and addAll.
 663      */
 664     private void rangeCheckForAdd(int index) {
 665         if (index > size || index < 0)
 666             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 667     }
 668 
 669     /**
 670      * Constructs an IndexOutOfBoundsException detail message.
 671      * Of the many possible refactorings of the error handling code,
 672      * this "outlining" performs best with both server and client VMs.
 673      */
 674     private String outOfBoundsMsg(int index) {
 675         return "Index: "+index+", Size: "+size;
 676     }
 677 
 678     /**
 679      * A version used in checking (fromIndex > toIndex) condition
 680      */
 681     private static String outOfBoundsMsg(int fromIndex, int toIndex) {
 682         return "From Index: " + fromIndex + " > To Index: " + toIndex;
 683     }
 684 
 685     /**
 686      * Removes from this list all of its elements that are contained in the
 687      * specified collection.
 688      *
 689      * @param c collection containing elements to be removed from this list
 690      * @return {@code true} if this list changed as a result of the call
 691      * @throws ClassCastException if the class of an element of this list
 692      *         is incompatible with the specified collection
 693      * (<a href="Collection.html#optional-restrictions">optional</a>)
 694      * @throws NullPointerException if this list contains a null element and the
 695      *         specified collection does not permit null elements


 989      * instead of a whole list.  For example, the following idiom
 990      * removes a range of elements from a list:
 991      * <pre>
 992      *      list.subList(from, to).clear();
 993      * </pre>
 994      * Similar idioms may be constructed for {@link #indexOf(Object)} and
 995      * {@link #lastIndexOf(Object)}, and all of the algorithms in the
 996      * {@link Collections} class can be applied to a subList.
 997      *
 998      * <p>The semantics of the list returned by this method become undefined if
 999      * the backing list (i.e., this list) is <i>structurally modified</i> in
1000      * any way other than via the returned list.  (Structural modifications are
1001      * those that change the size of this list, or otherwise perturb it in such
1002      * a fashion that iterations in progress may yield incorrect results.)
1003      *
1004      * @throws IndexOutOfBoundsException {@inheritDoc}
1005      * @throws IllegalArgumentException {@inheritDoc}
1006      */
1007     public List<E> subList(int fromIndex, int toIndex) {
1008         subListRangeCheck(fromIndex, toIndex, size);
1009         return new SubList(this, 0, fromIndex, toIndex);
1010     }
1011 
1012     static void subListRangeCheck(int fromIndex, int toIndex, int size) {
1013         if (fromIndex < 0)
1014             throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
1015         if (toIndex > size)
1016             throw new IndexOutOfBoundsException("toIndex = " + toIndex);
1017         if (fromIndex > toIndex)
1018             throw new IllegalArgumentException("fromIndex(" + fromIndex +
1019                                                ") > toIndex(" + toIndex + ")");
1020     }
1021 
1022     private class SubList extends AbstractList<E> implements RandomAccess {
1023         private final AbstractList<E> parent;
1024         private final int parentOffset;
1025         private final int offset;
1026         int size;
1027 
1028         SubList(AbstractList<E> parent,
1029                 int offset, int fromIndex, int toIndex) {
1030             this.parent = parent;
1031             this.parentOffset = fromIndex;
1032             this.offset = offset + fromIndex;
1033             this.size = toIndex - fromIndex;
1034             this.modCount = ArrayList.this.modCount;
1035         }
1036 
1037         public E set(int index, E e) {
1038             rangeCheck(index);
1039             checkForComodification();
1040             E oldValue = ArrayList.this.elementData(offset + index);
1041             ArrayList.this.elementData[offset + index] = e;
1042             return oldValue;
1043         }
1044 
1045         public E get(int index) {
1046             rangeCheck(index);
1047             checkForComodification();
1048             return ArrayList.this.elementData(offset + index);
1049         }
1050 
1051         public int size() {
1052             checkForComodification();
1053             return this.size;
1054         }
1055 
1056         public void add(int index, E e) {
1057             rangeCheckForAdd(index);
1058             checkForComodification();
1059             parent.add(parentOffset + index, e);
1060             this.modCount = parent.modCount;
1061             this.size++;
1062         }
1063 
1064         public E remove(int index) {
1065             rangeCheck(index);
1066             checkForComodification();
1067             E result = parent.remove(parentOffset + index);
1068             this.modCount = parent.modCount;
1069             this.size--;
1070             return result;
1071         }
1072 
1073         protected void removeRange(int fromIndex, int toIndex) {
1074             checkForComodification();
1075             parent.removeRange(parentOffset + fromIndex,
1076                                parentOffset + toIndex);
1077             this.modCount = parent.modCount;
1078             this.size -= toIndex - fromIndex;
1079         }
1080 
1081         public boolean addAll(Collection<? extends E> c) {
1082             return addAll(this.size, c);
1083         }
1084 
1085         public boolean addAll(int index, Collection<? extends E> c) {
1086             rangeCheckForAdd(index);
1087             int cSize = c.size();
1088             if (cSize==0)
1089                 return false;
1090 
1091             checkForComodification();
1092             parent.addAll(parentOffset + index, c);
1093             this.modCount = parent.modCount;
1094             this.size += cSize;
1095             return true;
1096         }
1097 
1098         public Iterator<E> iterator() {
1099             return listIterator();
1100         }
1101 
1102         public ListIterator<E> listIterator(final int index) {
1103             checkForComodification();
1104             rangeCheckForAdd(index);
1105             final int offset = this.offset;
1106 
1107             return new ListIterator<E>() {
1108                 int cursor = index;
1109                 int lastRet = -1;
1110                 int expectedModCount = ArrayList.this.modCount;
1111 
1112                 public boolean hasNext() {
1113                     return cursor != SubList.this.size;
1114                 }
1115 
1116                 @SuppressWarnings("unchecked")
1117                 public E next() {
1118                     checkForComodification();
1119                     int i = cursor;
1120                     if (i >= SubList.this.size)
1121                         throw new NoSuchElementException();
1122                     Object[] elementData = ArrayList.this.elementData;
1123                     if (offset + i >= elementData.length)
1124                         throw new ConcurrentModificationException();
1125                     cursor = i + 1;
1126                     return (E) elementData[offset + (lastRet = i)];
1127                 }
1128 
1129                 public boolean hasPrevious() {
1130                     return cursor != 0;
1131                 }
1132 
1133                 @SuppressWarnings("unchecked")
1134                 public E previous() {
1135                     checkForComodification();
1136                     int i = cursor - 1;
1137                     if (i < 0)
1138                         throw new NoSuchElementException();
1139                     Object[] elementData = ArrayList.this.elementData;
1140                     if (offset + i >= elementData.length)
1141                         throw new ConcurrentModificationException();
1142                     cursor = i;
1143                     return (E) elementData[offset + (lastRet = i)];
1144                 }
1145 
1146                 @SuppressWarnings("unchecked")
1147                 public void forEachRemaining(Consumer<? super E> consumer) {
1148                     Objects.requireNonNull(consumer);
1149                     final int size = SubList.this.size;
1150                     int i = cursor;
1151                     if (i >= size) {
1152                         return;
1153                     }
1154                     final Object[] elementData = ArrayList.this.elementData;
1155                     if (offset + i >= elementData.length) {
1156                         throw new ConcurrentModificationException();
1157                     }
1158                     while (i != size && modCount == expectedModCount) {
1159                         consumer.accept((E) elementData[offset + (i++)]);
1160                     }
1161                     // update once at end of iteration to reduce heap write traffic
1162                     lastRet = cursor = i;
1163                     checkForComodification();
1164                 }
1165 
1166                 public int nextIndex() {
1167                     return cursor;
1168                 }
1169 
1170                 public int previousIndex() {
1171                     return cursor - 1;
1172                 }
1173 
1174                 public void remove() {
1175                     if (lastRet < 0)
1176                         throw new IllegalStateException();
1177                     checkForComodification();
1178 
1179                     try {
1180                         SubList.this.remove(lastRet);
1181                         cursor = lastRet;
1182                         lastRet = -1;
1183                         expectedModCount = ArrayList.this.modCount;
1184                     } catch (IndexOutOfBoundsException ex) {
1185                         throw new ConcurrentModificationException();
1186                     }
1187                 }
1188 
1189                 public void set(E e) {
1190                     if (lastRet < 0)
1191                         throw new IllegalStateException();
1192                     checkForComodification();
1193 
1194                     try {
1195                         ArrayList.this.set(offset + lastRet, e);
1196                     } catch (IndexOutOfBoundsException ex) {
1197                         throw new ConcurrentModificationException();
1198                     }
1199                 }
1200 
1201                 public void add(E e) {
1202                     checkForComodification();
1203 
1204                     try {
1205                         int i = cursor;
1206                         SubList.this.add(i, e);
1207                         cursor = i + 1;
1208                         lastRet = -1;
1209                         expectedModCount = ArrayList.this.modCount;
1210                     } catch (IndexOutOfBoundsException ex) {
1211                         throw new ConcurrentModificationException();
1212                     }
1213                 }
1214 
1215                 final void checkForComodification() {
1216                     if (expectedModCount != ArrayList.this.modCount)
1217                         throw new ConcurrentModificationException();
1218                 }
1219             };
1220         }
1221 
1222         public List<E> subList(int fromIndex, int toIndex) {
1223             subListRangeCheck(fromIndex, toIndex, size);
1224             return new SubList(this, offset, fromIndex, toIndex);
1225         }
1226 
1227         private void rangeCheck(int index) {
1228             if (index < 0 || index >= this.size)
1229                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
1230         }
1231 
1232         private void rangeCheckForAdd(int index) {
1233             if (index < 0 || index > this.size)
1234                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
1235         }
1236 
1237         private String outOfBoundsMsg(int index) {
1238             return "Index: "+index+", Size: "+this.size;
1239         }
1240 
1241         private void checkForComodification() {
1242             if (ArrayList.this.modCount != this.modCount)
1243                 throw new ConcurrentModificationException();
1244         }
1245 
1246         public Spliterator<E> spliterator() {
1247             checkForComodification();
1248             return new ArrayListSpliterator<>(ArrayList.this, offset,
1249                                               offset + this.size, this.modCount);
1250         }
1251     }
1252 
1253     @Override
1254     public void forEach(Consumer<? super E> action) {
1255         Objects.requireNonNull(action);
1256         final int expectedModCount = modCount;
1257         @SuppressWarnings("unchecked")
1258         final E[] elementData = (E[]) this.elementData;
1259         final int size = this.size;
1260         for (int i=0; modCount == expectedModCount && i < size; i++) {
1261             action.accept(elementData[i]);
1262         }
1263         if (modCount != expectedModCount) {
1264             throw new ConcurrentModificationException();
1265         }
1266     }
1267 
1268     /**
1269      * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
1270      * and <em>fail-fast</em> {@link Spliterator} over the elements in this


1453         for (int i=0; modCount == expectedModCount && i < size; i++) {
1454             elementData[i] = operator.apply((E) elementData[i]);
1455         }
1456         if (modCount != expectedModCount) {
1457             throw new ConcurrentModificationException();
1458         }
1459         modCount++;
1460     }
1461 
1462     @Override
1463     @SuppressWarnings("unchecked")
1464     public void sort(Comparator<? super E> c) {
1465         final int expectedModCount = modCount;
1466         Arrays.sort((E[]) elementData, 0, size, c);
1467         if (modCount != expectedModCount) {
1468             throw new ConcurrentModificationException();
1469         }
1470         modCount++;
1471     }
1472 }

























































































































































































































































 655      */
 656     private void rangeCheck(int index) {
 657         if (index >= size)
 658             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 659     }
 660 
 661     /**
 662      * A version of rangeCheck used by add and addAll.
 663      */
 664     private void rangeCheckForAdd(int index) {
 665         if (index > size || index < 0)
 666             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 667     }
 668 
 669     /**
 670      * Constructs an IndexOutOfBoundsException detail message.
 671      * Of the many possible refactorings of the error handling code,
 672      * this "outlining" performs best with both server and client VMs.
 673      */
 674     private String outOfBoundsMsg(int index) {
 675         return "Index: " + index + ", Size: " + size;
 676     }
 677 
 678     /**
 679      * A version used in checking (fromIndex > toIndex) condition
 680      */
 681     private static String outOfBoundsMsg(int fromIndex, int toIndex) {
 682         return "From Index: " + fromIndex + " > To Index: " + toIndex;
 683     }
 684 
 685     /**
 686      * Removes from this list all of its elements that are contained in the
 687      * specified collection.
 688      *
 689      * @param c collection containing elements to be removed from this list
 690      * @return {@code true} if this list changed as a result of the call
 691      * @throws ClassCastException if the class of an element of this list
 692      *         is incompatible with the specified collection
 693      * (<a href="Collection.html#optional-restrictions">optional</a>)
 694      * @throws NullPointerException if this list contains a null element and the
 695      *         specified collection does not permit null elements


 989      * instead of a whole list.  For example, the following idiom
 990      * removes a range of elements from a list:
 991      * <pre>
 992      *      list.subList(from, to).clear();
 993      * </pre>
 994      * Similar idioms may be constructed for {@link #indexOf(Object)} and
 995      * {@link #lastIndexOf(Object)}, and all of the algorithms in the
 996      * {@link Collections} class can be applied to a subList.
 997      *
 998      * <p>The semantics of the list returned by this method become undefined if
 999      * the backing list (i.e., this list) is <i>structurally modified</i> in
1000      * any way other than via the returned list.  (Structural modifications are
1001      * those that change the size of this list, or otherwise perturb it in such
1002      * a fashion that iterations in progress may yield incorrect results.)
1003      *
1004      * @throws IndexOutOfBoundsException {@inheritDoc}
1005      * @throws IllegalArgumentException {@inheritDoc}
1006      */
1007     public List<E> subList(int fromIndex, int toIndex) {
1008         subListRangeCheck(fromIndex, toIndex, size);
1009         return new ArraySubList<>(this, fromIndex, toIndex);

















































































































































































































































1010     }
1011 
1012     @Override
1013     public void forEach(Consumer<? super E> action) {
1014         Objects.requireNonNull(action);
1015         final int expectedModCount = modCount;
1016         @SuppressWarnings("unchecked")
1017         final E[] elementData = (E[]) this.elementData;
1018         final int size = this.size;
1019         for (int i=0; modCount == expectedModCount && i < size; i++) {
1020             action.accept(elementData[i]);
1021         }
1022         if (modCount != expectedModCount) {
1023             throw new ConcurrentModificationException();
1024         }
1025     }
1026 
1027     /**
1028      * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
1029      * and <em>fail-fast</em> {@link Spliterator} over the elements in this


1212         for (int i=0; modCount == expectedModCount && i < size; i++) {
1213             elementData[i] = operator.apply((E) elementData[i]);
1214         }
1215         if (modCount != expectedModCount) {
1216             throw new ConcurrentModificationException();
1217         }
1218         modCount++;
1219     }
1220 
1221     @Override
1222     @SuppressWarnings("unchecked")
1223     public void sort(Comparator<? super E> c) {
1224         final int expectedModCount = modCount;
1225         Arrays.sort((E[]) elementData, 0, size, c);
1226         if (modCount != expectedModCount) {
1227             throw new ConcurrentModificationException();
1228         }
1229         modCount++;
1230     }
1231 }
1232 
1233 class ArraySubList<E> extends AbstractList<E> implements RandomAccess {
1234     final ArrayList<E> root;
1235     final ArraySubList<E> parent;
1236     final int offset;
1237     int size;
1238 
1239     /**
1240      * Constructs a sublist of an arbitrary ArrayList.
1241      */
1242     public ArraySubList(ArrayList<E> root, int fromIndex, int toIndex) {
1243         this.root = root;
1244         this.parent = null;
1245         this.offset = fromIndex;
1246         this.size = toIndex - fromIndex;
1247         this.modCount = root.modCount;
1248     }
1249 
1250     /**
1251      * Constructs a sublist of another ArraySubList.
1252      */
1253     private ArraySubList(ArraySubList<E> parent, int fromIndex, int toIndex) {
1254         this.root = parent.root;
1255         this.parent = parent;
1256         this.offset = parent.offset + fromIndex;
1257         this.size = toIndex - fromIndex;
1258         this.modCount = root.modCount;
1259     }
1260 
1261     public E set(int index, E element) {
1262         rangeCheck(index);
1263         checkForComodification();
1264         E oldValue = root.elementData(offset + index);
1265         root.elementData[offset + index] = element;
1266         return oldValue;
1267     }
1268 
1269     public E get(int index) {
1270         rangeCheck(index);
1271         checkForComodification();
1272         return root.elementData(offset + index);
1273     }
1274 
1275     public int size() {
1276         checkForComodification();
1277         return size;
1278     }
1279 
1280     public void add(int index, E element) {
1281         rangeCheckForAdd(index);
1282         checkForComodification();
1283         root.add(offset + index, element);
1284         updateSizeAndModCount(1);
1285     }
1286 
1287     public E remove(int index) {
1288         rangeCheck(index);
1289         checkForComodification();
1290         E result = root.remove(offset + index);
1291         updateSizeAndModCount(-1);
1292         return result;
1293     }
1294 
1295     protected void removeRange(int fromIndex, int toIndex) {
1296         checkForComodification();
1297         root.removeRange(offset + fromIndex, offset + toIndex);
1298         updateSizeAndModCount(fromIndex - toIndex);
1299     }
1300 
1301     public boolean addAll(Collection<? extends E> c) {
1302         return addAll(this.size, c);
1303     }
1304 
1305     public boolean addAll(int index, Collection<? extends E> c) {
1306         rangeCheckForAdd(index);
1307         int cSize = c.size();
1308         if (cSize == 0)
1309             return false;
1310         checkForComodification();
1311         root.addAll(offset + index, c);
1312         updateSizeAndModCount(cSize);
1313         return true;
1314     }
1315 
1316     public Iterator<E> iterator() {
1317         return listIterator();
1318     }
1319 
1320     public ListIterator<E> listIterator(int index) {
1321         checkForComodification();
1322         rangeCheckForAdd(index);
1323 
1324         return new ListIterator<E>() {
1325             int cursor = index;
1326             int lastRet = -1;
1327             int expectedModCount = root.modCount;
1328 
1329             public boolean hasNext() {
1330                 return cursor != ArraySubList.this.size;
1331             }
1332 
1333             @SuppressWarnings("unchecked")
1334             public E next() {
1335                 checkForComodification();
1336                 int i = cursor;
1337                 if (i >= ArraySubList.this.size)
1338                     throw new NoSuchElementException();
1339                 Object[] elementData = root.elementData;
1340                 if (offset + i >= elementData.length)
1341                     throw new ConcurrentModificationException();
1342                 cursor = i + 1;
1343                 return (E) elementData[offset + (lastRet = i)];
1344             }
1345 
1346             public boolean hasPrevious() {
1347                 return cursor != 0;
1348             }
1349 
1350             @SuppressWarnings("unchecked")
1351             public E previous() {
1352                 checkForComodification();
1353                 int i = cursor - 1;
1354                 if (i < 0)
1355                     throw new NoSuchElementException();
1356                 Object[] elementData = root.elementData;
1357                 if (offset + i >= elementData.length)
1358                     throw new ConcurrentModificationException();
1359                 cursor = i;
1360                 return (E) elementData[offset + (lastRet = i)];
1361             }
1362 
1363             @SuppressWarnings("unchecked")
1364             public void forEachRemaining(Consumer<? super E> consumer) {
1365                 Objects.requireNonNull(consumer);
1366                 final int size = ArraySubList.this.size;
1367                 int i = cursor;
1368                 if (i >= size) {
1369                     return;
1370                 }
1371                 final Object[] elementData = root.elementData;
1372                 if (offset + i >= elementData.length) {
1373                     throw new ConcurrentModificationException();
1374                 }
1375                 while (i != size && modCount == expectedModCount) {
1376                     consumer.accept((E) elementData[offset + (i++)]);
1377                 }
1378                 // update once at end of iteration to reduce heap write traffic
1379                 lastRet = cursor = i;
1380                 checkForComodification();
1381             }
1382 
1383             public int nextIndex() {
1384                 return cursor;
1385             }
1386 
1387             public int previousIndex() {
1388                 return cursor - 1;
1389             }
1390 
1391             public void remove() {
1392                 if (lastRet < 0)
1393                     throw new IllegalStateException();
1394                 checkForComodification();
1395 
1396                 try {
1397                     ArraySubList.this.remove(lastRet);
1398                     cursor = lastRet;
1399                     lastRet = -1;
1400                     expectedModCount = root.modCount;
1401                 } catch (IndexOutOfBoundsException ex) {
1402                     throw new ConcurrentModificationException();
1403                 }
1404             }
1405 
1406             public void set(E e) {
1407                 if (lastRet < 0)
1408                     throw new IllegalStateException();
1409                 checkForComodification();
1410 
1411                 try {
1412                     root.set(offset + lastRet, e);
1413                 } catch (IndexOutOfBoundsException ex) {
1414                     throw new ConcurrentModificationException();
1415                 }
1416             }
1417 
1418             public void add(E e) {
1419                 checkForComodification();
1420 
1421                 try {
1422                     int i = cursor;
1423                     ArraySubList.this.add(i, e);
1424                     cursor = i + 1;
1425                     lastRet = -1;
1426                     expectedModCount = root.modCount;
1427                 } catch (IndexOutOfBoundsException ex) {
1428                     throw new ConcurrentModificationException();
1429                 }
1430             }
1431 
1432             final void checkForComodification() {
1433                 if (root.modCount != expectedModCount)
1434                     throw new ConcurrentModificationException();
1435             }
1436         };
1437     }
1438 
1439     public List<E> subList(int fromIndex, int toIndex) {
1440         subListRangeCheck(fromIndex, toIndex, size);
1441         return new ArraySubList<>(this, fromIndex, toIndex);
1442     }
1443 
1444     private void rangeCheck(int index) {
1445         if (index < 0 || index >= size)
1446             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
1447     }
1448 
1449     private void rangeCheckForAdd(int index) {
1450         if (index < 0 || index > size)
1451             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
1452     }
1453 
1454     private String outOfBoundsMsg(int index) {
1455         return "Index: " + index + ", Size: " + size;
1456     }
1457 
1458     private void checkForComodification() {
1459         if (root.modCount != modCount)
1460             throw new ConcurrentModificationException();
1461     }
1462 
1463     private void updateSizeAndModCount(int sizeChange) {
1464         ArraySubList<E> slist = this;
1465         do {
1466             slist.size += sizeChange;
1467             slist.modCount = root.modCount;
1468             slist = slist.parent;
1469         } while (slist != null);
1470     }
1471 
1472     public Spliterator<E> spliterator() {
1473         checkForComodification();
1474         return new ArrayList.ArrayListSpliterator<>(root, offset,
1475                 offset + size, modCount);
1476     }
1477 }
1478 
< prev index next >