web-dev-qa-db-ja.com

2つのセットを組み合わせるときのjava.lang.UnsupportedOperationException

HashMapの2つの異なるインスタンスがあります

両方の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)

コンパイルの警告やエラーは表示されません。

From Java docこれは動作するはずです。追加されたコレクションがセットでも:

boolean addAll(Collection c)

指定されたコレクション内のすべての要素がこのセットに追加されます(オプションの操作)。指定されたコレクションもセットである場合、addAll操作はこのセットを効果的に変更して、その値が2つのセットの和集合になるようにします。操作の進行中に指定されたコレクションが変更された場合、この操作の動作は未定義です。

33
user1236048

HashMap#keySet() メソッドのドキュメントを見ると、答え(エンファシスマイニング)が得られます。

このマップに含まれるキーのSetビューを返します。セットはマップに連動しているため、マップへの変更はセットに反映され、その逆も同様です。セットの反復が進行中にマップが変更された場合(反復子の独自の削除操作を除く)、反復の結果は未定義です。セットは、Iterator.remove、Set.remove、removeAll、retainAll、およびclear操作を介して、マップから対応するマッピングを削除する要素の削除をサポートします。 addまたはaddAll操作はサポートしていません。

そのため、keySet()によって返されるSetに要素を追加する代わりに、新しいセットを作成してすべての要素を追加する必要があります。

45
SudoRahul

keySet() の結果は、要素の追加をサポートしていません。

変更しようとしていない場合hashMap1しかし、2つのマップのキーの和集合を含むセットが必要な場合は、以下を試してください。

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

Map.keySet()からのSetの性質上、サポートしていません。 remove、removeAll、retainAll、およびclear操作のみをサポートします。

ドキュメント をお読みください

1
VinayVeluri

上記の答えはすべて正しいです。実装の詳細を知りたい場合(jdk 8)

hashMap1.keySet() returns a KeySet<E>および

_KeySet<E>   extends AbstractSet<E>
AbstractSet<E> extends AbstractCollection<E> 
_

AbstractCollectionで、

_public boolean add(E e) {
        throw new UnsupportedOperationException();
    }
_

addAll() calls add()そして、それがUOExceptionを取得している理由です

0
nantitv