Java:为什么在List上调用`remove()`会抛出UnsupportedOperation异常?

时间:2009-11-20 21:28:15

标签: java

出于某种原因,我正在使用以下代码获得UnsupportedOpeationException。在调试器中检查它,看起来我正在调用的对象remove()是一个列表。

// to optimize, remove totalSize. After taking an item from lowest, if lowest is empty, remove it from `lists`
// lists are sorted to begin with
public static <T extends Comparable<? super T>> List<T> merge(Set<List<T>> lists) {
    List<T> result = new ArrayList<T>();
    HashMap<List<T>, Integer> location = new HashMap<List<T>, Integer>();

    int totalSize = 0; // every element in the set
    for (List<T> l : lists) {
        location.put(l, 0);
        totalSize += l.size();
    }

    boolean first;
    List<T> lowest = lists.iterator().next(); // the list with the lowest item to add
    int index;

    while (result.size() < totalSize) { // while we still have something to add
        first = true;

        for (List<T> l : lists) {
            if (! l.isEmpty()) {
                if (first) {
                    lowest = l;
                }
                else if (l.get(location.get(l)).compareTo(lowest.get(location.get(lowest))) <= 0) {
                    lowest = l;
                }
            }
        }
        index = location.get(lowest);
        result.add(lowest.get(index));
        lowest.remove(index); //problem here
    }
    return result;
}

例外:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.remove(Unknown Source)
    at interview.questions.MergeLists.merge(MergeLists.java:72)
    at interview.questions.MergeLists.main(MergeLists.java:32)

为什么会这样?

6 个答案:

答案 0 :(得分:19)

您收到的List的基础实现很可能是固定长度的,例如由Arrays#asList创建的实现。

答案 1 :(得分:4)

如果查看API docs for the List interface,您会看到其中一些是“可选操作”。这意味着允许具体类抛出UnsupportedOperationException。

例如,如果列表已转换为unmodifiable list,则无法允许删除操作实际删除某些内容(或列表将被修改)。

所以对于Set&lt;列表与LT;&GT;&GT;部分代码中的一个或多个列表不允许您从中删除。

答案 2 :(得分:2)

如果要从List中删除项目,而不是使用for-each循环遍历列表,则应该使用ListIterator,它以安全的方式支持remove()(即不离开列表中的孔或指向无处的索引。

答案 3 :(得分:1)

实现Collection接口的类是可选的,允许删除对象(参见Collection#remove()这是一个可选操作)。正如javadoc中所述,它会抛出

  

UnsupportedOperationException - 如果此集合不支持remove操作

在这种情况下你很可能(例如,如果你的集合包含由Jeffrey指出的Arrays.asList返回的列表)。

答案 4 :(得分:0)

您在集合中传递的列表是否来自AbstractList并且未实现(支持)remove()方法?

此外,对于在HashMap位置映射的所有列表对象,location似乎总是映射到0

答案 5 :(得分:0)

Collection接口中的remove()方法显式指定为可选操作:

remove(Object o)
          Removes a single instance of the specified element from this collection, if it is present (optional operation).

列表不必支持。事实上,它没有明确的语义。列表不适用于那种随机访问。您可以获得例外,而不是提供可能效率低下或不准确的默认实现。

如果关键,可以使用for-each循环编写自己的实用程序方法。