CopyOnWriteArrayList

Let’s look into below example code. The only difference between these blocks is type of iteration. Example 1 uses Iterator and Example 2 uses for each loop.

package com.bruiser.java;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class CopyOnWriteArrayListDemo {

	public static void main(String[] args) {
		
		List<String> fruits = new ArrayList<>();
		fruits.add("Banana");		
		fruits.add("Apple");
		fruits.add("Orange");
		
		Iterator<String> iterator= fruits.iterator();
		while(iterator.hasNext()) {
			String fruit = iterator.next();
			if(fruit.equalsIgnoreCase("Orange")) {
				fruits.remove("Orange");
			}
		}
			
	}

}
package com.bruiser.java;

import java.util.ArrayList;
import java.util.List;

public class CopyOnWriteArrayListDemo {

	public static void main(String[] args) {
		
		List<String> fruits = new ArrayList<>();
		fruits.add("Banana");		
		fruits.add("Apple");
		fruits.add("Orange");
		
		for(String fruit : fruits) {
			if(fruit.equalsIgnoreCase("Orange")) {
				fruits.remove("Orange");
			}
		}
			
	}

}

Running either of above example will result in below exception.

Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
	at com.bruiser.java.CopyOnWriteArrayListDemo.main(CopyOnWriteArrayListDemo.java:15)

So, what this exemption conveys us ? We are not allowed to modify the list during iteration. We resolve this exception by tweaking the code as below,

package com.bruiser.java;

import java.util.ArrayList;
import java.util.List;

public class CopyOnWriteArrayListDemo {

	public static void main(String[] args) {
		
		List<String> fruits = new ArrayList<>();
		fruits.add("Banana");		
		fruits.add("Apple");
		fruits.add("Orange");
		
		List<String> copyOfFruits = new ArrayList<>();
		copyOfFruits.addAll(fruits);
		for(String fruit : fruits) {
			if(fruit.equalsIgnoreCase("Orange")) {
				copyOfFruits.remove(fruit);
			}
		}
		
		for(String fruit : copyOfFruits) {
			System.out.println(fruit);
		}
			
	}

}
Banana
Apple

Here is action of CopyOnWriteArrayList comes into the picture. It performs the same function as above tweaked code. As per java docs, CopyOnWriteArryList is “A thread-safe variant of ArrayList in which all mutative operations (addset, and so on) are implemented by making a fresh copy of the underlying array.

Here is the example of using CopyOnWriteArrayList,

package com.bruiser.java;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListDemo {

	public static void main(String[] args) {
		
		List<String> fruits = new CopyOnWriteArrayList<>();
		fruits.add("Banana");		
		fruits.add("Apple");
		fruits.add("Orange");
		
		for(String fruit : fruits) {
			if(fruit.equalsIgnoreCase("Orange")) {
				fruits.remove(fruit);
			}
		}
		
		for(String fruit : fruits) {
			System.out.println(fruit);
		}
			
	}

}
Banana
Apple