簡體   English   中英

Java:為什么在List上調用`remove()`會拋出UnsupportedOperation異常?

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

出於某種原因,我使用以下代碼獲得UnsupportedOpeationException 在調試器中檢查它,看起來我正在調用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;
}

例外:

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)

為什么會這樣?

您收到的List的底層實現很可能是固定長度的,例如由Arrays#asList創建的Arrays#asList

如果查看List接口API文檔,您將看到其中許多是“可選操作”。 這意味着允許具體類拋出UnsupportedOperationException。

例如,如果將List轉換為不可修改的列表,則無法允許刪除操作實際刪除某些內容(或者列表將被修改)。

因此,對於代碼的Set <List <>>部分,列表中的一個或多個不允許您從中刪除。

如果您要從List中刪除項目,那么您應該使用ListIterator,而不是使用for-each循環來遍歷列表,而是使用ListIterator,它以安全的方式支持remove()(即不會在列表或指向無處的索引)。

實現Collection接口的類是可選的,允許刪除對象(請參閱Collection#remove()這是一個可選操作)。 如javadoc中所述,它會拋出

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

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

可能是您在集合中傳遞的列表是從AbstractList派生的,並且不實現(支持) remove()方法?

此外,對於在HashMap位置映射的所有列表對象, location似乎總是映射到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循環編寫自己的實用程序方法,以便在關鍵時執行此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM