当合并两个集合时出现java.lang.UnsupportedOperationException异常

54

我有两个不同的HashMap实例。

我想要合并这两个HashMap的键集;

代码:

Set<String> mySet = hashMap1.keySet();
mySet.addAll(hashMap2.keySet());

异常:

java.lang.UnsupportedOperationException
    at java.util.AbstractCollection.add(AbstractCollection.java:238)
    at java.util.AbstractCollection.addAll(AbstractCollection.java:322)

我没有收到编译警告或错误。

根据Java文档,这应该是有效的。 即使添加的集合也是一个Set:

boolean addAll(Collection c)

如果指定的集合中的元素(可选操作)尚未存在于此集合中,则将指定集合中的所有元素添加到此集合中。 如果指定的集合也是一个Set,则addAll操作会有效地修改此集合,以使其值为两个集合的并集。 如果在操作正在进行时修改了指定的集合,则此操作的行为是未定义的。


请注意,如果其中一个集合是不可变的,则也可能发生这种情况。 - user1156544
5个回答

61
如果您查看HashMap#keySet()方法的文档,您就可以得到答案(强调我)。
返回此映射中所包含键的Set视图。该Set由映射支持,因此对映射的更改会反映在Set中,反之亦然。如果在遍历Set时修改了映射(除非通过迭代器自己的删除操作),则遍历结果是未定义的。该Set支持元素删除,可以通过Iterator.remove、Set.remove、removeAll、retainAll和clear操作从映射中删除相应的映射。它不支持add或addAll操作。 因此,您需要创建一个新的Set并将所有元素添加到其中,而不是将元素添加到keySet()返回的Set中。

34

keySet() 方法返回的结果不支持添加元素。

如果你不想修改 hashMap1,只是想要一个包含两个映射的键并集的集合,请尝试:

Set<String> mySet = new HashSet<String>();
mySet.addAll(hashMap1.keySet());
mySet.addAll(hashMap2.keySet());

1
由于它来自map.keySet()的本质,不支持。它仅支持remove、removeAll、retainAll和clear操作。
请阅读文档

1

以上所有答案都是正确的。如果你仍然想知道确切的实现细节(jdk 8)

hashMap1.keySet() 返回一个 KeySet<E>,并且

KeySet<E>   extends AbstractSet<E>
AbstractSet<E> extends AbstractCollection<E> 

在AbstractCollection中,
public boolean add(E e) {
        throw new UnsupportedOperationException();
    }

addAll() 调用 add(),这就是为什么你会得到一个 UOException 的原因。


0
只需像这样使用 Map 的键创建自己的 Set:
Set set = new HashSet(map.keySet()); 

然后你可以添加任何你想要的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接