CopyOnWriteArrayList special points, compare ArrayList
- ArrayList can use the iterator's remove method to delete elements, CopyOnWriteArrayList can't use the iterator's remove method to delete elements, but can only use the collection's remove method to delete elements
public class Demo15 { public static void main(String[] args) { // Using the iterator of ArrayList to delete elements List<String> list1 = new ArrayList<>(); list1.add("a"); list1.add("b"); list1.add("c"); Iterator<String> iterator1 = list1.iterator(); while (iterator1.hasNext()) { String str = iterator1.next(); if ("b".equals(str)) { iterator1.remove(); } } // Delete elements using the iterator of CopyOnWriteArrayList List<String> list2 = new CopyOnWriteArrayList<>(); list2.add("a"); list2.add("b"); list2.add("c"); Iterator<String> iterator2 = list2.iterator(); while (iterator2.hasNext()) { String str = iterator2.next(); if ("b".equals(str)) { iterator2.remove(); // Unsupported operation exception will be thrown here } } } }
analysis:
CopyOnWriteArrayList source code:
View CopyOnWriteArrayList to get iterator method
public Iterator<E> iterator() { return new CopyOnWriteArrayList.COWIterator(this.getArray(), 0); }
View the internal class COWIterator construction method
COWIterator(Object[] es, int initialCursor) { this.cursor = initialCursor; this.snapshot = es; }
See here, it is actually copying the array of CopyOnWriteArrayList to the iterator. Subsequent operations to delete elements of the iterator are all operations to the array in the iterator. Since it is a copy, then the removal method of the iterator is invalid. Just throw the exception directly
public void remove() { throw new UnsupportedOperationException(); }
The iterator of ArrayList does not copy the array, so it still operates on the elements of the original collection. However, each time an element is deleted, it will check whether the modification times are the same. Because of the real-time comparison between the size of ArrayList collection and the modification times of modCount, once they are inconsistent, the concurrent modification exception will be thrown, which will lead to the inability to delete
- The ArrayList enhanced for loop cannot call remove of a collection to delete elements, while CopyOnWriteArrayList can
public class Demo15 { public static void main(String[] args) { // ArrayList enhanced for loop deletion, error reported List<String> list1 = new ArrayList<>(); list1.add("a"); list1.add("b"); list1.add("c"); for (String str : list1) { list1.remove(str); } // CopyOnWriteArrayList enhanced for circular deletion, normal List<String> list2 = new CopyOnWriteArrayList<>(); list2.add("a"); list2.add("b"); list2.add("c"); for (String str : list2) { list2.remove(str); } } }
analysis:
The key to enhance for conversion in iterations is iterating over iterators. The key is that ArrayList's remove method can't be invoked in iterator traversing elements, while CopyOnWriteArrayList's remove method can be invoked in iterator traversal elements.
In terms of design structure:
ArrayList:
Each time ArrayList gets a new iterator, it initializes the iterator with the modification times of the current ArrayList. The internal maintenance modification times of the iterator are used to determine whether the ArrayList has been modified independently( list.remove Method), or it can be modified by other iterators (get multiple iterators from the same collection under multithreading). If the addition and deletion operations of ArraList are used again, When the next method or remove method of the iterator is called again, the number of changes will be checked. If there is inconsistency, an error will be reported, and the deletion of the iterator will be synchronized to the ArrayList
CopyOnWriteArrayList:
The iterator obtained by CopyOnWriteArrayList every time is a copy of the array in the current collection. Therefore, in enhanced for, only this copy is traversed, and the deletion operation, or the operation collection, can be deleted successfully
Application scenario: read more and write less under multithreading
CopyOnWriteArrayList is mainly used to solve the problem that read and write threads can execute concurrently under multithreading. The results are as follows:
1. The read thread can execute concurrently
2. Read / write threads can execute concurrently
3. The write thread cannot execute concurrently
Problems:
1. It costs a lot of resources to copy every time you add or delete elements
2. The read data is a snapshot, not real-time