Подтвердить что ты не робот

Почему List.remove(int) throw java.lang.UnsupportedOperationException?

Я пытаюсь удалить элементы из 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
            }
        }
    }

и я получаю

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)

ПРИМЕЧАНИЕ. Это помечено как дубликат remove() в списке, созданном Arrays.asList(), который выдает UnsupportedOperationException, но это существенно отличается. Этот плакат знал, в чем проблема, и хотел объяснения; Я не знал, в чем проблема, и не смог найти ее на SO, разместив текущий вопрос. Java 6 docs (http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html) не дает никаких намеков на проблему (ее подпись бросает IndexOutOfBoundsException). Предыдущий вопрос также использовал removeAll(), в то время как этот вопрос касался remove(int), поэтому лексический поиск менее точен.

Поэтому я спросил о SO и получил быстрые и полезные ответы. Потому что я сформулировал название точно (в отличие от предыдущего вопроса), чтобы другим было легко найти этот ответ. Менее чем через день у него уже почти столько же голосов, сколько и предыдущий вопрос за год (и более 100 просмотров), что говорит о том, что он будет значительно полезнее. Поскольку этот вопрос теперь связан с предыдущим, я думаю, что он добавляет общую полезность без загрязнения SO. (Текущие ответы короткие и не требуют повторного повторения информации.)

Я редактировал вопрос, чтобы удалить посторонний код. Если бы этот вопрос был доступен, когда я столкнулся с проблемой, это спасло бы меня через час!

4b9b3361

Ответ 1

Вы используете его в реализации List, возвращенной Arrays.asList(), которая возвращает коллекцию фиксированной длины, поэтому remove не поддерживается.

Ответ 2

Arrays#asList создает немодифицируемый список:

Возвращает список фиксированного размера, поддерживаемый указанным массивом.

Попробуйте сделать:

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

Вместо:

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

Ответ 3

Это потому, что Arrays.asList() создает список оберток по массиву. Точно так же, как длина массива не может быть изменена, длина этого списка также не может быть изменена.

Если вы хотите создать "настоящий" список, заполненный элементами вашего массива, выполните следующие действия:

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