Arrays.asList()によって作成されたリストのremove()がUnsupportedOperationExceptionをスローする


91

コレクションc1<MyClass>と配列がありa<MyClass>ます。私は配列をコレクションに変換しようc2としていますがc1.removeAll(c2)、これはスローされUnsupportedOperationExceptionます。asList()of ArraysクラスがArrays.ArrayListクラスを返し、thisクラスが実装をスローするremoveAll()from AbstractList()を継承することがわかりましたUnsupportedOperationException

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

要素を削除する方法はありますか?助けてください


回答:


170

Arrays.asListList配列のラッパーを返します。このラッパーのサイズは固定されており、配列によって直接サポートされているsetため、への呼び出しによって配列が変更され、リストを変更する他のメソッドによってがスローされますUnsupportedOperationException

これを修正するには、ラッパーリストの内容をコピーして、変更可能な新しいリストを作成する必要があります。これは、ArrayListをとるコンストラクタを使用することで簡単に行えますCollection

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

1
java.util.Arrays asList()メソッドのソースコードを見ていましたが、を返すようArrayListです。ただし、を実行するとSystem.out.println(list.getClass());、が取得されclass java.util.Arrays$ArrayListます。そのためArrayListaddor removeメソッドを持たない内部クラスを使用します。内部ArrayListクラスを使用する代わりに内部クラスを使用することの意味は何なのかjava.util.ArrayListadd()そしてand remove()メソッドがないのはなぜですか?
Abdul

上記の私のコメントの修正:addand removeメソッドがあります
Abdul

1
@Abdul固定サイズなどないからjava.util.ArrayListList不正な操作(追加や削除など)を行い、ArrayListその要件を満たさない場合に、例外のスローを実装する必要があります。
Etienne de Martel

@Abdul Arrays.asListはラッパーを作成するだけListです。しかし、それはまだなjava.util.Listので、これらのメソッドが必要です。ただし、サイズの異なる新しい配列を作成することになるため、適用できません。実行できる変更は、返されたリストと元の配列の両方で実行できるため、実行できません。返されたリストが変更され、基本的に元の配列参照が破棄される場合、これは不可能です。
AdamHošek17年

13

うん、これArrays.asList(..)は拡張または縮小できないコレクションです(元の配列によってサポートされており、サイズを変更できないため)。

要素を削除する場合new ArrayList(Arrays.asList(..)は、配列から要素を直接作成するか削除します(効率が低下し、記述が難しくなります)。


+1これが唯一正しい答えです。Arrays.asList()は変更できないリストを返します-これが例外をスローしているものです。「配列に基づく」などとは関係ありません... すべての ArrayListは配列に支えられています-大したことです。
ボヘミアン

1
しかし、ドキュメントをさらに読むと、実際には変更できないわけではないことがわかります... "指定された配列に基づく固定サイズのリストを返します。 。) "-1、エティエンヌはまったく正しい。
Steven Schlansker、2011年

1
@Stevenはい、そのため、「変更不可」または「読み取り専用」ではなく「固定サイズ」と表示されます。実際、それを反映するために今すぐ私の回答を編集します。
Etienne de Martel

1
@Bohemian、「set」メソッドを呼び出すことができるため、返されるコレクションはそのまま「変更可能」です。
javalearner

2
そのようなnitを選択する場合は、「コードにthrow UnsupportedOperationExceptionステートメントがあるため、UnsupportedOperationExceptionをスローする」などの無駄なことを言うこともできます。APIのコンシューマーは、どのAbstractBlahスーパークラスが例外をスローしているかを気にせず、使用するクラスのコントラクトと期待値を気にします。JVM v + 1では、例外がスローされる場所でクラスライブラリが変更される可能性がありますが、コントラクトは変更されません。
Steven Schlansker、2011年

7

これは、Array.asList()配列によって直接サポートされているため、機能します。完全に変更可能なリストを取得するには、コレクションを自分で作成したコレクションに複製する必要があります。

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

1
リストは変更可能ですが、set()を介してのみ変更できます。返されるコレクションは固定サイズです。
javalearner '25

実際に変更できないと言ったことはありません。(完全に)変更可能なリストを取得するには、を使用する必要がありますArrayList。違いはおそらくあまり明確ではなかったでしょう。:-)リストが変更可能かどうかは、定義の問題ですが、「準変更可能」ですが、私の見解では完全に変更可能ではありません。
ヘンコ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.