Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List retainAll exception

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.

like image 436
Gandalf StormCrow Avatar asked May 10 '12 20:05

Gandalf StormCrow


3 Answers

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]
like image 119
ataylor Avatar answered Oct 10 '22 21:10

ataylor


As the documentation says, the List.retainAll() method

Retains only the elements in this list that are contained in the specified collection (optional operation). In other words, removes from this list all the elements that are not contained in the specified collection. [emphasis mine]

like image 28
Attila Avatar answered Oct 10 '22 21:10

Attila


retainAll does remove items from the list it is invoked on.

like image 21
GriffeyDog Avatar answered Oct 10 '22 22:10

GriffeyDog