30

I am trying to remove elements from a List and getting java.lang.UnsupportedOperationException.

    public <T extends Object> void findDuplicates(
        String title, Multimap<T, ChunkId> map) {
        for (T key : map.keySet()) {
            Collection<ChunkId> ids = map.get(key);
            List<ChunkId> idList = (Arrays.asList(ids.toArray(new ChunkId[0])));
            removeUsedIds(idList);
            Collections.sort(idList);
//...
        }
    }

    private void removeUsedIds(List<ChunkId> idList) {
        // decrement counter to avoid indexing changed parts of list
        for (int i = idList.size() - 1; i >= 0; i--) {
            if (usedIdSet.contains(idList.get(i))) {
                idList.remove(i);   // **** Exception thrown here
            }
        }
    }

and I get

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.remove(Unknown Source)
    at org.xmlcml.svg2xml.analyzer.PDFIndex.removeUsedIds(PDFIndex.java:104)
    at org.xmlcml.svg2xml.analyzer.PDFIndex.findDuplicates(PDFIndex.java:87)
    at org.xmlcml.svg2xml.analyzer.PDFIndex.findDuplicatesInIndexes(PDFIndex.java:129)
    at org.xmlcml.svg2xml.analyzer.PDFAnalyzer.analyzePDF(PDFAnalyzer.java:188)
    at org.xmlcml.svg2xml.analyzer.PDFAnalyzer.analyzePDFFile(PDFAnalyzer.java:115)
    at org.xmlcml.svg2xml.analyzer.PDFAnalyzer.main(PDFAnalyzer.java:398)

NOTE: This is flagged as a duplicate of remove() on List created by Arrays.asList() throws UnsupportedOperationException but it's significantly different. That poster knew what the problem was and wanted an explanation; I did not know what the problem was and couldn't find it on SO by posting the current question. Java 6 docs (http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html) gives no hint of the problem (its signature throws IndexOutOfBoundsException). The previous question also used removeAll() while this question referred to remove(int) so lexical searching is less precise.

I therefore asked on SO and got rapid and useful answers. Because I phrased the title exactly (unlike the previous question) it should be easy for others to find this answer. In less than a day it already has nearly as many votes as the previous question in a year (and 100+ views), suggesting that it will be significantly more useful. Since this question is now linked to the previous one I think it adds to the general usefulness without polluting SO. (The current answers are short and don't unnecessarily repeat information.)

I have edited the question to remove extraneous code. If this question had been available when I encountered the problem it would have saved me an hour!

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
peter.murray.rust
  • 37,407
  • 44
  • 153
  • 217
  • which line does it happen? – Ariel Pinchover Apr 17 '13 at 20:56
  • You need to add one more piece of information: what kind of list did you previously instantiate? – atk Apr 17 '13 at 20:57
  • Marked as a dupe because the `idList` you're passing into the `removeUsedIds()` method is created using the `Arrays.asList()` method, which returns a List wrapper around the array, which does not support modification. – Craig Otis Apr 17 '13 at 20:57
  • The problem arose for me because the creation of the list was considerably removed from its modification. I tried to search SO for previous answers and didn't find them. [The previous question mentioned `UnsupportedException` – peter.murray.rust Apr 17 '13 at 21:16

3 Answers3

62

You're using it on a List implementation returned by Arrays.asList(), which returns a fixed-length collection, therefore a remove is unsupported.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
51

Arrays#asList creates an unmodifiable list:

Returns a fixed-size list backed by the specified array.

Try to do:

List<ChunkId> idList = new ArrayList(Arrays.asList(ids.toArray(new ChunkId[0])));

Instead of:

List<ChunkId> idList = (Arrays.asList(ids.toArray(new ChunkId[0])));
Maroun
  • 94,125
  • 30
  • 188
  • 241
  • https://stackoverflow.com/questions/2965747/why-do-i-get-an-unsupportedoperationexception-when-trying-to-remove-an-element-f – Spartan Jul 03 '17 at 11:03
  • yes seems it should be `new LinkedList<>` not `new ArrayList` (from @thanga link) – user25 Mar 11 '18 at 17:41
18

This is because Arrays.asList() creates wrapper list over array. Exactly as array's length cannot be changed the length of this list cannot be changed too.

If you want to create "real" list filled with elements of your array do the following:

new ArrayList<ChunkId>(Arrays.asList(array))

AlexR
  • 114,158
  • 16
  • 130
  • 208