为什么List.remove(int)抛出java.lang.UnsupportedOperationException?

pet*_*ust 28 java

我试图从a中删除元素List并获取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
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我明白了

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)
Run Code Online (Sandbox Code Playgroud)

注意:这被标记为由Arrays.asList()创建的List上remove()的副本抛出UnsupportedOperationException,但它有很大不同.那张海报知道问题是什么,想得到解释; 我不知道问题是什么,也无法通过发布当前问题找到它.Java 6 docs(http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html)没有给出任何问题的提示(它的签名抛出IndexOutOfBoundsException).在提出removeAll()这个问题时也使用了上一个问题,remove(int)因此词法搜索不太精确.

因此,我问了SO,得到了快速有用的答案.因为我准确地说了这个标题(与上一个问题不同),其他人应该很容易找到这个答案.在不到一天的时间里,它已经拥有与一年中前一个问题(和100多个观点)相同数量的投票,这表明它将更有用.由于这个问题现在与前一个问题相关联,我认为它增加了一般用途而不污染SO.(目前的答案很短,不会不必要地重复信息.)

我编辑了这个问题以删除多余的代码.如果我遇到问题时可以提出这个问题,那么我可以节省一个小时!

The*_*kis 59

您在List返回的实现上使用它Arrays.asList(),它返回一个固定长度的集合,因此remove不支持.


Mar*_*oun 46

Arrays#asList创建一个不可修改的列表:

返回由指定数组支持的固定大小的列表.

试着做:

List<ChunkId> idList = new ArrayList(Arrays.asList(ids.toArray(new ChunkId[0])));
Run Code Online (Sandbox Code Playgroud)

代替:

List<ChunkId> idList = (Arrays.asList(ids.toArray(new ChunkId[0])));
Run Code Online (Sandbox Code Playgroud)


Ale*_*exR 16

这是因为Arrays.asList()在数组上创建包装列表.正如数组的长度无法更改,此列表的长度也无法更改.

如果要创建填充了数组元素的"真实"列表,请执行以下操作:

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