Arrays.asList()创建的列表上的remove()抛出UnsupportedOperationException


91

我有一个集合c1<MyClass>和一个数组a<MyClass>。我试图将数组转换为集合c2并执行操作c1.removeAll(c2),但这会抛出异常UnsupportedOperationException。我发现,asList()Arrays类收益Arrays.ArrayList类和这个类继承removeAll()AbstractList()其实现抛出UnsupportedOperationException

    Myclass la[] = getMyClass();
    Collection c = Arrays.asList(la);
    c.removeAll(thisAllreadyExistingMyClass);

有什么办法可以删除元素?请帮忙


Answers:


170

Arrays.asList返回List数组的包装器。此包装具有固定的大小,并直接由数组支持,因此对的调用set将修改数组,而其他任何修改列表的方法都将引发UnsupportedOperationException

要解决此问题,您必须通过复制包装器列表的内容来创建新的可修改列表。通过使用ArrayList带有的构造函数,这很容易做到Collection

Collection c = new ArrayList(Arrays.asList(la));

1
我正在查看java.util.Arrays asList()方法的源代码,并且似乎返回ArrayList。但是,当我执行a时System.out.println(list.getClass());,我得到了class java.util.Arrays$ArrayList。因此,它使用ArrayList没有addremove方法的内部类。我只是想知道拥有一个内部ArrayList类而不是使用一个内部类有什么意义,java.util.ArrayList为什么不拥有add()and remove()方法呢?
阿卜杜勒

我对上述评论的更正:它确实具有addand remove方法
Abdul

1
@Abdul因为没有固定大小的东西java.util.ArrayListList如果您对某项操作进行了非法操作(例如添加或删除),并且ArrayList不满足该要求,则希望该实现会引发异常。
Etienne de Martel

@Abdul Arrays.asList只是创建一个包装器List。但是它仍然是java.util.List,因此必须具有这些方法。但是无法应用它们,因为这将导致创建一个具有不同大小的新数组。之所以无法完成,是因为您仍然可以通过返回的List和原始数组来完成修改。如果返回的List可以更改,从而基本上可以丢弃原始数组引用,则将不可能。
亚当·霍谢克(AdamHošek),

13

Arrays.asList(..)是的,不能扩展或缩小的is集合(因为它由原始数组支持,并且无法调整大小)。

如果要删除元素,请创建一个new ArrayList(Arrays.asList(..)或直接从数组中删除元素(这样效率较低,更难编写)


+1这个答案是唯一正确的答案:Arrays.asList()返回一个不可修改的列表-这就是引发异常的原因。与“由数组支持”等无关... 所有 ArrayLists都由数组支持-大不了。
波希米亚

1
但是,如果您进一步阅读文档,您会意识到它实际上并不是不可修改的……“返回由指定数组支持的固定大小的列表。(更改为返回列表的“直写”到数组。)“ -1,Etienne是正确的。
史蒂文·斯兰斯克

1
@Steven是的,这就是为什么它说“固定大小”而不是“不可修改”或“只读”的原因。实际上,我现在就去编辑我的答案以反映这一点。
Etienne de Martel

1
@Bohemian,返回的集合实际上是“可修改的”,因为可以调用“ set”方法。
javalearner11年

2
如果您要像这样采摘尼特,您最好说一些诸如“由于代码中有抛出UnsupportedOperationException语句而抛出UnsupportedOperationException的异常之类的事情”。API的使用者不在乎哪个AbstractBlah超类抛出异常,他们在乎所使用的类的契约和期望是什么。在JVM v + 1中,类库完全有可能在引发异常的位置发生更改-但协定不会更改。
史蒂文·斯兰斯克

7

这是可行的方法Array.asList(),因为它直接由数组支持。要获得完全可修改的列表,您必须将集合克隆到您自己创建的集合中。

Collection c = new ArrayList(Arrays.asList(la))

1
该列表是可修改的,但只能通过set()进行。返回的集合是固定大小的。
javalearner11年

我从来没有说过它是不可修改的。只是要获得(完全)可修改的列表,您就必须使用ArrayList。区别也许不是很清楚。:-)列表是否可修改是定义的问题,我认为它是“半可修改的”,但不能完全修改。
henko 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.