【问题标题】:remove() on List created by Arrays.asList() throws UnsupportedOperationExceptionArrays.asList() 创建的 List 上的 remove() 抛出 UnsupportedOperationException
【发布时间】:2011-10-25 06:45:15
【问题描述】:

我有一个集合 c1<MyClass> 和一个数组 a<MyClass>。我正在尝试将数组转换为集合c2 并执行c1.removeAll(c2),但这会引发UnsupportedOperationException。我发现Arrays类的asList()返回Arrays.ArrayList类,而这个类从AbstractList()继承removeAll(),其实现抛出UnsupportedOperationException

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

有什么办法可以去掉元素吗?请帮忙

【问题讨论】:

标签: java


【解决方案1】:

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

要解决此问题,您必须通过复制包装列表的内容来创建一个新的可修改列表。这很容易通过使用带有CollectionArrayList 构造函数来实现:

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

【讨论】:

  • 我正在查看java.util.Arrays asList() 方法的源代码,它似乎返回了一个ArrayList。但是,当我执行System.out.println(list.getClass()); 时,我得到class java.util.Arrays$ArrayList。所以它使用内部的ArrayList 类,它没有addremove 方法。我只是想知道拥有一个内部 ArrayList 类而不是使用 java.util.ArrayList 有什么意义,为什么不使用 add()remove() 方法?
  • 更正我上面的评论:它确实有 addremove 方法
  • @Abdul 因为没有固定大小的东西java.util.ArrayList。你想要一个 List 的实现,如果你用它做一些非法的事情(例如添加或删除),它会抛出一个异常,而 ArrayList 不满足这个要求。
  • @Abdul Arrays.asList 只是创建一个包装器List。但它仍然是java.util.List,所以它必须有那些方法。但是它们不能被应用,因为这会导致创建一个不同大小的新数组。这是无法完成的,因为您仍然可以进行的修改可以通过返回的 List 和原始数组来完成。如果返回的 List 可以更改,以至于它基本上会丢弃原始数组引用,这将是不可能的。
【解决方案2】:

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

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

【讨论】:

  • 列表是可修改的,但只能通过 set()。返回的集合是固定大小的。
  • 我实际上从未说过它是不可修改的。只是为了获得(完全)可修改的列表,您必须使用ArrayList。不过,差异可能不太明显。 :-) 列表是否可修改是一个定义问题,在我看来它是“半可修改的”但不是完全可修改的。
【解决方案3】:

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

如果您想删除元素,请创建new ArrayList(Arrays.asList(..) 或直接从数组中删除元素(这样会降低效率且难以编写)

【讨论】:

  • +1 这个答案是唯一正确的:Arrays.asList() 返回一个 unmodifiable 列表——这就是引发异常的原因。这与“由数组支持”等无关... 所有 ArrayLists 由数组支持 - 很重要。
  • 但是,如果您进一步阅读文档,您会意识到它实际上并非不可修改...“返回由指定数组支持的固定大小的列表。(对返回的更改list "write through" 到数组。)" -1,Etienne 说的很对。
  • @Steven 是的,这就是为什么它说“固定大小”而不是“不可修改”或“只读”。实际上,我现在会去编辑我的答案以反映这一点。
  • @Bohemian,返回的集合实际上是“可修改的”,因为可以调用“set”方法。
  • 如果你要选择这样的 nits,你还不如说“它抛出 UnsupportedOperationException 因为代码中有一个 throw UnsupportedOperationException 语句”之类的乏味的话。 API 的使用者不关心哪个 AbstractBlah 超类抛出异常,他们关心他们使用的类的契约和期望是什么。在 JVM v+1 中,类库完全有可能在抛出异常的地方发生变化——但契约不会改变。
猜你喜欢
  • 2015-07-22
  • 2013-02-26
  • 2022-01-22
  • 2014-01-30
  • 1970-01-01
  • 1970-01-01
  • 2013-06-15
  • 2016-02-24
相关资源
最近更新 更多