1. ホーム
  2. java

[解決済み] リストから要素を削除しようとすると、UnsupportedOperationExceptionが発生するのはなぜですか?

2022-01-30 09:26:06

質問

このようなコードがあります。

public static String SelectRandomFromTemplate(String template,int count) {
   String[] split = template.split("|");
   List<String> list=Arrays.asList(split);
   Random r = new Random();
   while( list.size() > count ) {
      list.remove(r.nextInt(list.size()));
   }
   return StringUtils.join(list, ", ");
}

これが分かるんです。

06-03 15:05:29.614: ERROR/AndroidRuntime(7737): java.lang.UnsupportedOperationException
06-03 15:05:29.614: ERROR/AndroidRuntime(7737):     at java.util.AbstractList.remove(AbstractList.java:645)

これはどうするのが正しいのでしょうか?Java.15

どのように解決するのですか?

あなたのコードにはかなり多くの問題があります。

について Arrays.asList 固定サイズのリストを返す

APIから

Arrays.asList : を返します。 サイズ固定リスト 指定された配列にバックアップされます。

はできません。 add を、それに対して remove を作成します。を構造的に変更することはできません。 List .

修正

を作成します。 LinkedList をサポートし、より高速な remove .

List<String> list = new LinkedList<String>(Arrays.asList(split));


について split 正規表現

APIから

String.split(String regex) : この文字列を、指定された文字列にマッチする箇所で分割します。 正規表現 .

| は正規表現のメタキャラクタであり、リテラルな | にエスケープする必要があります。 \| であり、Java の文字列リテラルとしては "\\|" .

修正する

template.split("\\|")


より良いアルゴリズムについて

を呼び出す代わりに remove をランダムなインデックスで一度に生成し、その範囲内で十分な数の乱数を生成し、さらに List を使って一度だけ listIterator() を呼び出す。 remove() を適当なインデックスで指定します。stackoverflowには、与えられた範囲内でランダムだが明確な数を生成する方法についての質問があります。

この場合、アルゴリズムは次のようになります。 O(N) .