1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package java.util.concurrent; 18 19 import java.io.IOException; 20 import java.io.ObjectInputStream; 21 import java.io.ObjectOutputStream; 22 import java.io.Serializable; 23 import java.util.AbstractList; 24 import java.util.Arrays; 25 import java.util.Collection; 26 import java.util.Comparator; 27 import java.util.ConcurrentModificationException; 28 import java.util.Iterator; 29 import java.util.List; 30 import java.util.ListIterator; 31 import java.util.NoSuchElementException; 32 import java.util.RandomAccess; 33 import java.util.function.Consumer; 34 import java.util.function.UnaryOperator; 35 36 import libcore.util.EmptyArray; 37 import libcore.util.Objects; 38 39 /** 40 * A thread-safe random-access list. 41 * 42 * <p>Read operations (including {@link #get}) do not block and may overlap with 43 * update operations. Reads reflect the results of the most recently completed 44 * operations. Aggregate operations like {@link #addAll} and {@link #clear} are 45 * atomic; they never expose an intermediate state. 46 * 47 * <p>Iterators of this list never throw {@link 48 * ConcurrentModificationException}. When an iterator is created, it keeps a 49 * copy of the list's contents. It is always safe to iterate this list, but 50 * iterations may not reflect the latest state of the list. 51 * 52 * <p>Iterators returned by this list and its sub lists cannot modify the 53 * underlying list. In particular, {@link Iterator#remove}, {@link 54 * ListIterator#add} and {@link ListIterator#set} all throw {@link 55 * UnsupportedOperationException}. 56 * 57 * <p>This class offers extended API beyond the {@link List} interface. It 58 * includes additional overloads for indexed search ({@link #indexOf} and {@link 59 * #lastIndexOf}) and methods for conditional adds ({@link #addIfAbsent} and 60 * {@link #addAllAbsent}). 61 */ 62 public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, Serializable { 63 64 private static final long serialVersionUID = 8673264195747942595L; 65 66 /** 67 * Holds the latest snapshot of the list's data. This field is volatile so 68 * that data can be read without synchronization. As a consequence, all 69 * writes to this field must be atomic; it is an error to modify the 70 * contents of an array after it has been assigned to this field. 71 * 72 * Synchronization is required by all update operations. This defends 73 * against one update clobbering the result of another operation. For 74 * example, 100 threads simultaneously calling add() will grow the list's 75 * size by 100 when they have completed. No update operations are lost! 76 * 77 * Maintainers should be careful to read this field only once in 78 * non-blocking read methods. Write methods must be synchronized to avoid 79 * clobbering concurrent writes. 80 */ 81 private transient volatile Object[] elements; 82 83 /** 84 * Creates a new empty instance. 85 */ CopyOnWriteArrayList()86 public CopyOnWriteArrayList() { 87 elements = EmptyArray.OBJECT; 88 } 89 90 /** 91 * Creates a new instance containing the elements of {@code collection}. 92 */ 93 @SuppressWarnings("unchecked") CopyOnWriteArrayList(Collection<? extends E> collection)94 public CopyOnWriteArrayList(Collection<? extends E> collection) { 95 this((E[]) collection.toArray()); 96 } 97 98 /** 99 * Creates a new instance containing the elements of {@code array}. 100 */ CopyOnWriteArrayList(E[] array)101 public CopyOnWriteArrayList(E[] array) { 102 this.elements = Arrays.copyOf(array, array.length, Object[].class); 103 } 104 clone()105 @Override public Object clone() { 106 try { 107 CopyOnWriteArrayList result = (CopyOnWriteArrayList) super.clone(); 108 result.elements = result.elements.clone(); 109 return result; 110 } catch (CloneNotSupportedException e) { 111 throw new AssertionError(e); 112 } 113 } 114 size()115 public int size() { 116 return elements.length; 117 } 118 119 @SuppressWarnings("unchecked") get(int index)120 public E get(int index) { 121 return (E) elements[index]; 122 } 123 contains(Object o)124 public boolean contains(Object o) { 125 return indexOf(o) != -1; 126 } 127 containsAll(Collection<?> collection)128 public boolean containsAll(Collection<?> collection) { 129 Object[] snapshot = elements; 130 return containsAll(collection, snapshot, 0, snapshot.length); 131 } 132 containsAll(Collection<?> collection, Object[] snapshot, int from, int to)133 static boolean containsAll(Collection<?> collection, Object[] snapshot, int from, int to) { 134 for (Object o : collection) { 135 if (indexOf(o, snapshot, from, to) == -1) { 136 return false; 137 } 138 } 139 return true; 140 } 141 142 /** 143 * Searches this list for {@code object} and returns the index of the first 144 * occurrence that is at or after {@code from}. 145 * 146 * @return the index or -1 if the object was not found. 147 */ indexOf(E object, int from)148 public int indexOf(E object, int from) { 149 Object[] snapshot = elements; 150 return indexOf(object, snapshot, from, snapshot.length); 151 } 152 indexOf(Object object)153 public int indexOf(Object object) { 154 Object[] snapshot = elements; 155 return indexOf(object, snapshot, 0, snapshot.length); 156 } 157 158 /** 159 * Searches this list for {@code object} and returns the index of the last 160 * occurrence that is before {@code to}. 161 * 162 * @return the index or -1 if the object was not found. 163 */ lastIndexOf(E object, int to)164 public int lastIndexOf(E object, int to) { 165 Object[] snapshot = elements; 166 return lastIndexOf(object, snapshot, 0, to); 167 } 168 lastIndexOf(Object object)169 public int lastIndexOf(Object object) { 170 Object[] snapshot = elements; 171 return lastIndexOf(object, snapshot, 0, snapshot.length); 172 } 173 isEmpty()174 public boolean isEmpty() { 175 return elements.length == 0; 176 } 177 178 /** 179 * Returns an {@link Iterator} that iterates over the elements of this list 180 * as they were at the time of this method call. Changes to the list made 181 * after this method call will not be reflected by the iterator, nor will 182 * they trigger a {@link ConcurrentModificationException}. 183 * 184 * <p>The returned iterator does not support {@link Iterator#remove()}. 185 */ iterator()186 public Iterator<E> iterator() { 187 Object[] snapshot = elements; 188 return new CowIterator<E>(snapshot, 0, snapshot.length); 189 } 190 191 /** 192 * Returns a {@link ListIterator} that iterates over the elements of this 193 * list as they were at the time of this method call. Changes to the list 194 * made after this method call will not be reflected by the iterator, nor 195 * will they trigger a {@link ConcurrentModificationException}. 196 * 197 * <p>The returned iterator does not support {@link ListIterator#add}, 198 * {@link ListIterator#set} or {@link Iterator#remove()}, 199 */ listIterator(int index)200 public ListIterator<E> listIterator(int index) { 201 Object[] snapshot = elements; 202 if (index < 0 || index > snapshot.length) { 203 throw new IndexOutOfBoundsException("index=" + index + ", length=" + snapshot.length); 204 } 205 CowIterator<E> result = new CowIterator<E>(snapshot, 0, snapshot.length); 206 result.index = index; 207 return result; 208 } 209 210 /** 211 * Equivalent to {@code listIterator(0)}. 212 */ listIterator()213 public ListIterator<E> listIterator() { 214 Object[] snapshot = elements; 215 return new CowIterator<E>(snapshot, 0, snapshot.length); 216 } 217 subList(int from, int to)218 public List<E> subList(int from, int to) { 219 Object[] snapshot = elements; 220 if (from < 0 || from > to || to > snapshot.length) { 221 throw new IndexOutOfBoundsException("from=" + from + ", to=" + to + 222 ", list size=" + snapshot.length); 223 } 224 return new CowSubList(snapshot, from, to); 225 } 226 toArray()227 public Object[] toArray() { 228 return elements.clone(); 229 } 230 231 @SuppressWarnings({"unchecked","SuspiciousSystemArraycopy"}) toArray(T[] contents)232 public <T> T[] toArray(T[] contents) { 233 Object[] snapshot = elements; 234 if (snapshot.length > contents.length) { 235 return (T[]) Arrays.copyOf(snapshot, snapshot.length, contents.getClass()); 236 } 237 System.arraycopy(snapshot, 0, contents, 0, snapshot.length); 238 if (snapshot.length < contents.length) { 239 contents[snapshot.length] = null; 240 } 241 return contents; 242 } 243 equals(Object other)244 @Override public boolean equals(Object other) { 245 if (other instanceof CopyOnWriteArrayList) { 246 return this == other 247 || Arrays.equals(elements, ((CopyOnWriteArrayList<?>) other).elements); 248 } else if (other instanceof List) { 249 Object[] snapshot = elements; 250 Iterator<?> i = ((List<?>) other).iterator(); 251 for (Object o : snapshot) { 252 if (!i.hasNext() || !Objects.equal(o, i.next())) { 253 return false; 254 } 255 } 256 return !i.hasNext(); 257 } else { 258 return false; 259 } 260 } 261 hashCode()262 @Override public int hashCode() { 263 return Arrays.hashCode(elements); 264 } 265 toString()266 @Override public String toString() { 267 return Arrays.toString(elements); 268 } 269 add(E e)270 public synchronized boolean add(E e) { 271 Object[] newElements = new Object[elements.length + 1]; 272 System.arraycopy(elements, 0, newElements, 0, elements.length); 273 newElements[elements.length] = e; 274 elements = newElements; 275 return true; 276 } 277 add(int index, E e)278 public synchronized void add(int index, E e) { 279 Object[] newElements = new Object[elements.length + 1]; 280 System.arraycopy(elements, 0, newElements, 0, index); 281 newElements[index] = e; 282 System.arraycopy(elements, index, newElements, index + 1, elements.length - index); 283 elements = newElements; 284 } 285 addAll(Collection<? extends E> collection)286 public synchronized boolean addAll(Collection<? extends E> collection) { 287 return addAll(elements.length, collection); 288 } 289 addAll(int index, Collection<? extends E> collection)290 public synchronized boolean addAll(int index, Collection<? extends E> collection) { 291 Object[] toAdd = collection.toArray(); 292 Object[] newElements = new Object[elements.length + toAdd.length]; 293 System.arraycopy(elements, 0, newElements, 0, index); 294 System.arraycopy(toAdd, 0, newElements, index, toAdd.length); 295 System.arraycopy(elements, index, 296 newElements, index + toAdd.length, elements.length - index); 297 elements = newElements; 298 return toAdd.length > 0; 299 } 300 301 /** 302 * Adds the elements of {@code collection} that are not already present in 303 * this list. If {@code collection} includes a repeated value, at most one 304 * occurrence of that value will be added to this list. Elements are added 305 * at the end of this list. 306 * 307 * <p>Callers of this method may prefer {@link CopyOnWriteArraySet}, whose 308 * API is more appropriate for set operations. 309 */ addAllAbsent(Collection<? extends E> collection)310 public synchronized int addAllAbsent(Collection<? extends E> collection) { 311 Object[] toAdd = collection.toArray(); 312 Object[] newElements = new Object[elements.length + toAdd.length]; 313 System.arraycopy(elements, 0, newElements, 0, elements.length); 314 int addedCount = 0; 315 for (Object o : toAdd) { 316 if (indexOf(o, newElements, 0, elements.length + addedCount) == -1) { 317 newElements[elements.length + addedCount++] = o; 318 } 319 } 320 if (addedCount < toAdd.length) { 321 newElements = Arrays.copyOfRange( 322 newElements, 0, elements.length + addedCount); // trim to size 323 } 324 elements = newElements; 325 return addedCount; 326 } 327 328 /** 329 * Adds {@code object} to the end of this list if it is not already present. 330 * 331 * <p>Callers of this method may prefer {@link CopyOnWriteArraySet}, whose 332 * API is more appropriate for set operations. 333 */ addIfAbsent(E object)334 public synchronized boolean addIfAbsent(E object) { 335 if (contains(object)) { 336 return false; 337 } 338 add(object); 339 return true; 340 } 341 clear()342 @Override public synchronized void clear() { 343 elements = EmptyArray.OBJECT; 344 } 345 remove(int index)346 public synchronized E remove(int index) { 347 @SuppressWarnings("unchecked") 348 E removed = (E) elements[index]; 349 removeRange(index, index + 1); 350 return removed; 351 } 352 remove(Object o)353 public synchronized boolean remove(Object o) { 354 int index = indexOf(o); 355 if (index == -1) { 356 return false; 357 } 358 remove(index); 359 return true; 360 } 361 removeAll(Collection<?> collection)362 public synchronized boolean removeAll(Collection<?> collection) { 363 return removeOrRetain(collection, false, 0, elements.length) != 0; 364 } 365 retainAll(Collection<?> collection)366 public synchronized boolean retainAll(Collection<?> collection) { 367 return removeOrRetain(collection, true, 0, elements.length) != 0; 368 } 369 370 @Override replaceAll(UnaryOperator<E> operator)371 public synchronized void replaceAll(UnaryOperator<E> operator) { 372 replaceInRange(0, elements.length,operator); 373 } 374 replaceInRange(int from, int to, UnaryOperator<E> operator)375 private void replaceInRange(int from, int to, UnaryOperator<E> operator) { 376 java.util.Objects.requireNonNull(operator); 377 Object[] newElements = new Object[elements.length]; 378 System.arraycopy(elements, 0, newElements, 0, newElements.length); 379 for (int i = from; i < to; i++) { 380 @SuppressWarnings("unchecked") E e = (E) elements[i]; 381 newElements[i] = operator.apply(e); 382 } 383 elements = newElements; 384 } 385 386 @Override sort(Comparator<? super E> c)387 public synchronized void sort(Comparator<? super E> c) { 388 sortInRange(0, elements.length, c); 389 } 390 sortInRange(int from, int to, Comparator<? super E> c)391 private synchronized void sortInRange(int from, int to, Comparator<? super E> c) { 392 java.util.Objects.requireNonNull(c); 393 Object[] newElements = new Object[elements.length]; 394 System.arraycopy(elements, 0, newElements, 0, newElements.length); 395 Arrays.sort((E[])newElements, from, to, c); 396 elements = newElements; 397 } 398 399 @Override forEach(Consumer<? super E> action)400 public void forEach(Consumer<? super E> action) { 401 forInRange(0, elements.length, action); 402 } 403 forInRange(int from, int to, Consumer<? super E> action)404 private void forInRange(int from, int to, Consumer<? super E> action) { 405 java.util.Objects.requireNonNull(action); 406 Object[] newElements = new Object[elements.length]; 407 System.arraycopy(elements, 0, newElements, 0, newElements.length); 408 for (int i = from; i < to; i++) { 409 action.accept((E)newElements[i]); 410 } 411 } 412 413 /** 414 * Removes or retains the elements in {@code collection}. Returns the number 415 * of elements removed. 416 */ removeOrRetain(Collection<?> collection, boolean retain, int from, int to)417 private int removeOrRetain(Collection<?> collection, boolean retain, int from, int to) { 418 for (int i = from; i < to; i++) { 419 if (collection.contains(elements[i]) == retain) { 420 continue; 421 } 422 423 /* 424 * We've encountered an element that must be removed! Create a new 425 * array and copy in the surviving elements one by one. 426 */ 427 Object[] newElements = new Object[elements.length - 1]; 428 System.arraycopy(elements, 0, newElements, 0, i); 429 int newSize = i; 430 for (int j = i + 1; j < to; j++) { 431 if (collection.contains(elements[j]) == retain) { 432 newElements[newSize++] = elements[j]; 433 } 434 } 435 436 /* 437 * Copy the elements after 'to'. This is only useful for sub lists, 438 * where 'to' will be less than elements.length. 439 */ 440 System.arraycopy(elements, to, newElements, newSize, elements.length - to); 441 newSize += (elements.length - to); 442 443 if (newSize < newElements.length) { 444 newElements = Arrays.copyOfRange(newElements, 0, newSize); // trim to size 445 } 446 int removed = elements.length - newElements.length; 447 elements = newElements; 448 return removed; 449 } 450 451 // we made it all the way through the loop without making any changes 452 return 0; 453 } 454 set(int index, E e)455 public synchronized E set(int index, E e) { 456 Object[] newElements = elements.clone(); 457 @SuppressWarnings("unchecked") 458 E result = (E) newElements[index]; 459 newElements[index] = e; 460 elements = newElements; 461 return result; 462 } 463 removeRange(int from, int to)464 private void removeRange(int from, int to) { 465 Object[] newElements = new Object[elements.length - (to - from)]; 466 System.arraycopy(elements, 0, newElements, 0, from); 467 System.arraycopy(elements, to, newElements, from, elements.length - to); 468 elements = newElements; 469 } 470 lastIndexOf(Object o, Object[] data, int from, int to)471 static int lastIndexOf(Object o, Object[] data, int from, int to) { 472 if (o == null) { 473 for (int i = to - 1; i >= from; i--) { 474 if (data[i] == null) { 475 return i; 476 } 477 } 478 } else { 479 for (int i = to - 1; i >= from; i--) { 480 if (o.equals(data[i])) { 481 return i; 482 } 483 } 484 } 485 return -1; 486 } 487 indexOf(Object o, Object[] data, int from, int to)488 static int indexOf(Object o, Object[] data, int from, int to) { 489 if (o == null) { 490 for (int i = from; i < to; i++) { 491 if (data[i] == null) { 492 return i; 493 } 494 } 495 } else { 496 for (int i = from; i < to; i++) { 497 if (o.equals(data[i])) { 498 return i; 499 } 500 } 501 } 502 return -1; 503 } 504 getArray()505 final Object[] getArray() { 506 // CopyOnWriteArraySet needs this. 507 return elements; 508 } 509 510 /** 511 * The sub list is thread safe and supports non-blocking reads. Doing so is 512 * more difficult than in the full list, because each read needs to examine 513 * four fields worth of state: 514 * - the elements array of the full list 515 * - two integers for the bounds of this sub list 516 * - the expected elements array (to detect concurrent modification) 517 * 518 * This is accomplished by aggregating the sub list's three fields into a 519 * single snapshot object representing the current slice. This permits reads 520 * to be internally consistent without synchronization. This takes advantage 521 * of Java's concurrency semantics for final fields. 522 */ 523 class CowSubList extends AbstractList<E> { 524 525 /* 526 * An immutable snapshot of a sub list's state. By gathering all three 527 * of the sub list's fields in an immutable object, 528 */ 529 private volatile Slice slice; 530 CowSubList(Object[] expectedElements, int from, int to)531 public CowSubList(Object[] expectedElements, int from, int to) { 532 this.slice = new Slice(expectedElements, from, to); 533 } 534 size()535 @Override public int size() { 536 Slice slice = this.slice; 537 return slice.to - slice.from; 538 } 539 isEmpty()540 @Override public boolean isEmpty() { 541 Slice slice = this.slice; 542 return slice.from == slice.to; 543 } 544 545 @SuppressWarnings("unchecked") get(int index)546 @Override public E get(int index) { 547 Slice slice = this.slice; 548 Object[] snapshot = elements; 549 slice.checkElementIndex(index); 550 slice.checkConcurrentModification(snapshot); 551 return (E) snapshot[index + slice.from]; 552 } 553 iterator()554 @Override public Iterator<E> iterator() { 555 return listIterator(0); 556 } 557 listIterator()558 @Override public ListIterator<E> listIterator() { 559 return listIterator(0); 560 } 561 listIterator(int index)562 @Override public ListIterator<E> listIterator(int index) { 563 Slice slice = this.slice; 564 Object[] snapshot = elements; 565 slice.checkPositionIndex(index); 566 slice.checkConcurrentModification(snapshot); 567 CowIterator<E> result = new CowIterator<E>(snapshot, slice.from, slice.to); 568 result.index = slice.from + index; 569 return result; 570 } 571 indexOf(Object object)572 @Override public int indexOf(Object object) { 573 Slice slice = this.slice; 574 Object[] snapshot = elements; 575 slice.checkConcurrentModification(snapshot); 576 int result = CopyOnWriteArrayList.indexOf(object, snapshot, slice.from, slice.to); 577 return (result != -1) ? (result - slice.from) : -1; 578 } 579 lastIndexOf(Object object)580 @Override public int lastIndexOf(Object object) { 581 Slice slice = this.slice; 582 Object[] snapshot = elements; 583 slice.checkConcurrentModification(snapshot); 584 int result = CopyOnWriteArrayList.lastIndexOf(object, snapshot, slice.from, slice.to); 585 return (result != -1) ? (result - slice.from) : -1; 586 } 587 contains(Object object)588 @Override public boolean contains(Object object) { 589 return indexOf(object) != -1; 590 } 591 containsAll(Collection<?> collection)592 @Override public boolean containsAll(Collection<?> collection) { 593 Slice slice = this.slice; 594 Object[] snapshot = elements; 595 slice.checkConcurrentModification(snapshot); 596 return CopyOnWriteArrayList.containsAll(collection, snapshot, slice.from, slice.to); 597 } 598 subList(int from, int to)599 @Override public List<E> subList(int from, int to) { 600 Slice slice = this.slice; 601 if (from < 0 || from > to || to > size()) { 602 throw new IndexOutOfBoundsException("from=" + from + ", to=" + to + 603 ", list size=" + size()); 604 } 605 return new CowSubList(slice.expectedElements, slice.from + from, slice.from + to); 606 } 607 remove(int index)608 @Override public E remove(int index) { 609 synchronized (CopyOnWriteArrayList.this) { 610 slice.checkElementIndex(index); 611 slice.checkConcurrentModification(elements); 612 E removed = CopyOnWriteArrayList.this.remove(slice.from + index); 613 slice = new Slice(elements, slice.from, slice.to - 1); 614 return removed; 615 } 616 } 617 clear()618 @Override public void clear() { 619 synchronized (CopyOnWriteArrayList.this) { 620 slice.checkConcurrentModification(elements); 621 CopyOnWriteArrayList.this.removeRange(slice.from, slice.to); 622 slice = new Slice(elements, slice.from, slice.from); 623 } 624 } 625 add(int index, E object)626 @Override public void add(int index, E object) { 627 synchronized (CopyOnWriteArrayList.this) { 628 slice.checkPositionIndex(index); 629 slice.checkConcurrentModification(elements); 630 CopyOnWriteArrayList.this.add(index + slice.from, object); 631 slice = new Slice(elements, slice.from, slice.to + 1); 632 } 633 } 634 add(E object)635 @Override public boolean add(E object) { 636 synchronized (CopyOnWriteArrayList.this) { 637 add(slice.to - slice.from, object); 638 return true; 639 } 640 } 641 addAll(int index, Collection<? extends E> collection)642 @Override public boolean addAll(int index, Collection<? extends E> collection) { 643 synchronized (CopyOnWriteArrayList.this) { 644 slice.checkPositionIndex(index); 645 slice.checkConcurrentModification(elements); 646 int oldSize = elements.length; 647 boolean result = CopyOnWriteArrayList.this.addAll(index + slice.from, collection); 648 slice = new Slice(elements, slice.from, slice.to + (elements.length - oldSize)); 649 return result; 650 } 651 } 652 addAll(Collection<? extends E> collection)653 @Override public boolean addAll(Collection<? extends E> collection) { 654 synchronized (CopyOnWriteArrayList.this) { 655 return addAll(size(), collection); 656 } 657 } 658 set(int index, E object)659 @Override public E set(int index, E object) { 660 synchronized (CopyOnWriteArrayList.this) { 661 slice.checkElementIndex(index); 662 slice.checkConcurrentModification(elements); 663 E result = CopyOnWriteArrayList.this.set(index + slice.from, object); 664 slice = new Slice(elements, slice.from, slice.to); 665 return result; 666 } 667 } 668 remove(Object object)669 @Override public boolean remove(Object object) { 670 synchronized (CopyOnWriteArrayList.this) { 671 int index = indexOf(object); 672 if (index == -1) { 673 return false; 674 } 675 remove(index); 676 return true; 677 } 678 } 679 removeAll(Collection<?> collection)680 @Override public boolean removeAll(Collection<?> collection) { 681 synchronized (CopyOnWriteArrayList.this) { 682 slice.checkConcurrentModification(elements); 683 int removed = removeOrRetain(collection, false, slice.from, slice.to); 684 slice = new Slice(elements, slice.from, slice.to - removed); 685 return removed != 0; 686 } 687 } 688 retainAll(Collection<?> collection)689 @Override public boolean retainAll(Collection<?> collection) { 690 synchronized (CopyOnWriteArrayList.this) { 691 slice.checkConcurrentModification(elements); 692 int removed = removeOrRetain(collection, true, slice.from, slice.to); 693 slice = new Slice(elements, slice.from, slice.to - removed); 694 return removed != 0; 695 } 696 } 697 698 @Override forEach(Consumer<? super E> action)699 public void forEach(Consumer<? super E> action) { 700 CopyOnWriteArrayList.this.forInRange(slice.from, slice.to, action); 701 } 702 703 @Override replaceAll(UnaryOperator<E> operator)704 public void replaceAll(UnaryOperator<E> operator) { 705 synchronized (CopyOnWriteArrayList.this) { 706 slice.checkConcurrentModification(elements); 707 CopyOnWriteArrayList.this.replaceInRange(slice.from, slice.to, operator); 708 slice = new Slice(elements, slice.from, slice.to); 709 } 710 } 711 712 @Override sort(Comparator<? super E> c)713 public synchronized void sort(Comparator<? super E> c) { 714 synchronized (CopyOnWriteArrayList.this) { 715 slice.checkConcurrentModification(elements); 716 CopyOnWriteArrayList.this.sortInRange(slice.from, slice.to, c); 717 slice = new Slice(elements, slice.from, slice.to); 718 } 719 } 720 } 721 722 static class Slice { 723 private final Object[] expectedElements; 724 private final int from; 725 private final int to; 726 Slice(Object[] expectedElements, int from, int to)727 Slice(Object[] expectedElements, int from, int to) { 728 this.expectedElements = expectedElements; 729 this.from = from; 730 this.to = to; 731 } 732 733 /** 734 * Throws if {@code index} doesn't identify an element in the array. 735 */ checkElementIndex(int index)736 void checkElementIndex(int index) { 737 if (index < 0 || index >= to - from) { 738 throw new IndexOutOfBoundsException("index=" + index + ", size=" + (to - from)); 739 } 740 } 741 742 /** 743 * Throws if {@code index} doesn't identify an insertion point in the 744 * array. Unlike element index, it's okay to add or iterate at size(). 745 */ checkPositionIndex(int index)746 void checkPositionIndex(int index) { 747 if (index < 0 || index > to - from) { 748 throw new IndexOutOfBoundsException("index=" + index + ", size=" + (to - from)); 749 } 750 } 751 checkConcurrentModification(Object[] snapshot)752 void checkConcurrentModification(Object[] snapshot) { 753 if (expectedElements != snapshot) { 754 throw new ConcurrentModificationException(); 755 } 756 } 757 } 758 759 /** 760 * Iterates an immutable snapshot of the list. 761 */ 762 static class CowIterator<E> implements ListIterator<E> { 763 private final Object[] snapshot; 764 private final int from; 765 private final int to; 766 private int index = 0; 767 CowIterator(Object[] snapshot, int from, int to)768 CowIterator(Object[] snapshot, int from, int to) { 769 this.snapshot = snapshot; 770 this.from = from; 771 this.to = to; 772 this.index = from; 773 } 774 add(E object)775 public void add(E object) { 776 throw new UnsupportedOperationException(); 777 } 778 hasNext()779 public boolean hasNext() { 780 return index < to; 781 } 782 hasPrevious()783 public boolean hasPrevious() { 784 return index > from; 785 } 786 787 @SuppressWarnings("unchecked") next()788 public E next() { 789 if (index < to) { 790 return (E) snapshot[index++]; 791 } else { 792 throw new NoSuchElementException(); 793 } 794 } 795 nextIndex()796 public int nextIndex() { 797 return index; 798 } 799 800 @SuppressWarnings("unchecked") previous()801 public E previous() { 802 if (index > from) { 803 return (E) snapshot[--index]; 804 } else { 805 throw new NoSuchElementException(); 806 } 807 } 808 previousIndex()809 public int previousIndex() { 810 return index - 1; 811 } 812 remove()813 public void remove() { 814 throw new UnsupportedOperationException(); 815 } 816 set(E object)817 public void set(E object) { 818 throw new UnsupportedOperationException(); 819 } 820 821 @Override forEachRemaining(Consumer<? super E> action)822 public void forEachRemaining(Consumer<? super E> action) { 823 java.util.Objects.requireNonNull(action); 824 Object[] elements = snapshot; 825 for (int i = index; i < to; i++) { 826 @SuppressWarnings("unchecked") E e = (E) elements[i]; 827 action.accept(e); 828 } 829 index = to; 830 } 831 } 832 writeObject(ObjectOutputStream out)833 private void writeObject(ObjectOutputStream out) throws IOException { 834 Object[] snapshot = elements; 835 out.defaultWriteObject(); 836 out.writeInt(snapshot.length); 837 for (Object o : snapshot) { 838 out.writeObject(o); 839 } 840 } 841 readObject(ObjectInputStream in)842 private synchronized void readObject(ObjectInputStream in) 843 throws IOException, ClassNotFoundException { 844 in.defaultReadObject(); 845 Object[] snapshot = new Object[in.readInt()]; 846 for (int i = 0; i < snapshot.length; i++) { 847 snapshot[i] = in.readObject(); 848 } 849 elements = snapshot; 850 } 851 } 852