简体   繁体   English

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

[英]Java: Why does calling `remove()` on a List throw UnsupportedOperation exception?

For some reason, I'm getting an UnsupportedOpeationException with the following code. 出于某种原因,我使用以下代码获得UnsupportedOpeationException Examining it in the debugger, it looks like the object I'm calling remove() on is a list. 在调试器中检查它,看起来我正在调用remove() on的对象是一个列表。

// 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;
}

The exception: 例外:

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)

Why is this happening? 为什么会这样?

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

If you look at the API docs for the List interface you will see that a number of them are "optional operations". 如果查看List接口API文档,您将看到其中许多是“可选操作”。 That means that a concrete class is permitted to throw the UnsupportedOperationException. 这意味着允许具体类抛出UnsupportedOperationException。

If, for example, the List was converted to an unmodifiable list it could not allow the remove operation to actually remove something (or the list would be modified). 例如,如果将List转换为不可修改的列表,则无法允许删除操作实际删除某些内容(或者列表将被修改)。

So for the Set< List<>> part of the code one or mnre of the lists does not allow you to remove from it. 因此,对于代码的Set <List <>>部分,列表中的一个或多个不允许您从中删除。

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

It is optional for a class implementing the Collection interface to allow objects to be removed (see Collection#remove() which is an optional operation). 实现Collection接口的类是可选的,允许删除对象(请参阅Collection#remove()这是一个可选操作)。 As stated in the javadoc, it throws 如javadoc中所述,它会抛出

UnsupportedOperationException - if the remove operation is not supported by this collection UnsupportedOperationException - 如果此集合不支持remove操作

You are likely in that case (eg if your set contains a list returned by Arrays.asList as pointed out by Jeffrey). 在这种情况下你很可能(例如,如果你的集合包含由Jeffrey指出的Arrays.asList返回的列表)。

Could it be that the Lists you pass in the set are derived from AbstractList and do not implement (support) the remove() method? 可能是您在集合中传递的列表是从AbstractList派生的,并且不实现(支持) remove()方法?

Also, it seems that location always maps to 0 for all list object that are mapped in the location HashMap? 此外,对于在HashMap位置映射的所有列表对象, location似乎总是映射到0

The remove() method in the Collection interface is explicitly specified as an optional operation: Collection接口中的remove()方法显式指定为可选操作:

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

Lists do not have to support in. In fact, there is no clear semantics for it. 列表不必支持。事实上,它没有明确的语义。 Lists are not meant for that sort of random-access. 列表不适用于那种随机访问。 Rather than provide some default implementation that may be inefficient or inaccurate, you get the exception. 您可以获得异常,而不是提供可能效率低下或不准确的默认实现。

You can write your own utility method with a for-each loop to do this if it is critical. 您可以使用for-each循环编写自己的实用程序方法,以便在关键时执行此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM