Pavan Ghantasala
Pavan Ghantasala

Reputation: 249

Difference between Iterator,List iterator and CopyOnWriteArrayList

Consider an ArrayList,where in for Iterator and List iterator operations,when a list is iterated and whenever there is a change in Collection object,then it throws ConcurrentModificationException like below :

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

    public class Wdfds {

        public static void main(String[] args) {

            List<Integer> list=new ArrayList<>();

            list.add(1);
            list.add(2);
            list.add(3);
            list.add(4);

            Iterator it=list.iterator();

            while(it.hasNext()){

            Integer i= (Integer) it.next();

            if(i%2==0)
            list.remove(0);             
            }

            System.out.println(list); } }

This is not the case when Iterator object is updated i.e. like below:

 while(it.hasNext()){

            Integer i= (Integer) it.next();

            if(i%2==0)
            it.remove();            
            }

        System.out.println(list); } }

And when it comes to copyOnWriteArrayList , if iterator object is updated with remove operation for normal iterator like below (or) listIterator is updated(either add/removal), it throws UnsupportedOperationException:

    package JavaImpPrograms;
    import java.util.Iterator;
    import java.util.List;
    import java.util.concurrent.CopyOnWriteArrayList;

    public class Wdfds {

        public static void main(String[] args) {

            List<Integer> list=new CopyOnWriteArrayList<>();

            list.add(1);
            list.add(2);
            list.add(3);
            list.add(4);

            Iterator it=list.iterator();

            while(it.hasNext()){

            Integer i= (Integer) it.next();

            if(i%2==0)
            it.remove();            
            }

            System.out.println(list); } }

package JavaImpPrograms;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.CopyOnWriteArrayList;

public class Wdfds {

    public static void main(String[] args) {

        List<Integer> list=new CopyOnWriteArrayList<>();

        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);

        ListIterator it=list.listIterator();

        while(it.hasNext()){

        Integer i= (Integer) it.next();

        if(i%2==0)
        it.add(9);          
        }

        System.out.println(list); } }

I have a couple of Questions with the above results:

1) For an ArrayList,if an iterator is able to modify the list during iteration using iterator object, why is copyOnWriteArrayList used for?

1)Why copyOnWriteArrayList iterator updates are throwing unsupportedOperationExceptions when it encounters Iterator object changes, but no exception when there is a change for collection object?

3)Looks like above 2 scenarios are opposite to each other.Please let me know when these are used for and in which scenarios?

It is totally Confusing...

Upvotes: 2

Views: 835

Answers (2)

Turing85
Turing85

Reputation: 20185

Your questions are all answered by the documentation of CopyOnWriteArrayList:

A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.

Looking at the documentation of CopyOnWriteArrayList#iterator() reveals that

The returned iterator provides a snapshot of the state of the list when the iterator was constructed. No synchronization is needed while traversing the iterator. The iterator does NOT support the remove method.

The important part is that the Iterator only provides a snapshot of the list.

Iterator#remove() demands the following behaviour:

Removes from the underlying collection the last element returned by this iterator (optional operation).

Since the iterator() of a CopyOnWriteArrayList is only a snapshot of the list, some element seen by the Iterator could already been deleted from the list, thus removing it (again) might cause trouble (e.g. when the same object is in the list multiple times). The only logical consequence is to deny the operation by throwing an UnsupportedOperationException.

Upvotes: 4

Gaurav Srivastav
Gaurav Srivastav

Reputation: 2551

There are two types of iterators Fail Safe and Fail Fast. Iterator is fail fast which means while you traversing the collection and trying to modify the structure of collection by add new element then ConcurrentModificationException is being thrown.

To overcome this we have CopyOnWriteArrayList which is fail safe, we can do add the element while traversing the list.

Its clear that the concurrent modification exception is coming when we call iterator next() function. If you are wondering how Iterator checks for the modification, its implementation is present in AbstractList class where an int variable modCount is defined. modCount provides the number of times list size has been changed. modCount value is used in every next() call to check for any modifications in a function checkForComodification().

The CopyOnWriteArrayList was created to allow for the possibility of safe iterating over elements even when the underlying list gets modified.

Because of the copying mechanism, the remove() operation on the returned Iterator is not permitted – resulting with UnsupportedOperationException.

http://www.baeldung.com/java-copy-on-write-arraylist

Upvotes: 1

Related Questions