List retainAll exception

Gandalf StormCrow picture Gandalf StormCrow · May 10, 2012 · Viewed 8.4k times · Source

I wanted to test how to get intersection between two lists, here is my code :

            List<Integer> list = Arrays.asList(16, 17, 18, 19, 20);
        List<Integer> list2 = list.subList(2, 5);

        System.out.println(list.subList(2, 5));
        System.out.println(list.containsAll(list.subList(2, 5)));
        System.out.println(list.retainAll(list2));

This produces :

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.remove(Unknown Source)
    at java.util.AbstractList$Itr.remove(Unknown Source)
    at java.util.AbstractCollection.retainAll(Unknown Source)
    at gov.noaa.nhc.App.main(App.java:48)

But I'm not doing any removes. Why is this producing exception?

Update I :

Using :

List<Integer> list = new ArrayList<Integer>(Arrays.asList(16, 17, 18, 19, 20));
List<Integer> list2 = list.subList(2, 5);

Produces :

java.util.ConcurrentModificationException

Since list2 is backed by list1, removing items from list1 will cause this exception. Finally working version :

List<Integer> list = new ArrayList<Integer>(Arrays.asList(16, 17, 18, 19, 20));
List<Integer> list2 = Arrays.asList(18, 19, 20);

or

List<Integer> list = new ArrayList<Integer>(Arrays.asList(16, 17, 18, 19, 20));
List<Integer> list2 = new ArrayList<Integer>(Arrays.asList(18, 19, 20));

or

 List<Integer> list = new ArrayList<Integer>(Arrays.asList(16, 17, 18, 19, 20));
 List<Integer> list2 = new ArrayList<Integer>(list.subList(2, 5));

Thanks for your answers everyone.

Answer

ataylor picture ataylor · May 10, 2012

When you use Arrays.asList, you get a list backed by the actual array passed in with restricted functionality. If you want a fully modifiable list you have to create a new list. For example:

List<Integer> list = new ArrayList<Integer>(Arrays.asList(16, 17, 18, 19, 20));
List<Integer> list2 = new ArrayList<Integer>(list.subList(2, 5));
list.retainAll(list2);
System.out.println(list);
// result: [18, 19, 20]