私はこのコードを持っています:
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
を一度に1つずつ呼び出すのではなく、範囲内で十分な乱数を生成してから、listIterator()
でList
を1回トラバースし、適切なインデックスでremove()
を呼び出します。与えられた範囲でランダムだが異なる数を生成する方法については、スタックオーバーフローについての質問があります。
これで、あなたのアルゴリズムはO(N)
になるでしょう。
これは私を何度も燃やしました。 Arrays.asList
は変更不可能なリストを作成します。 Javadocから:指定された配列を基にした 固定長 のリストを返します。
同じ内容の新しいリストを作成します。
newList.addAll(Arrays.asList(newArray));
これは少し余分なゴミを作成しますが、あなたはそれを変異させることができるでしょう。
おそらくあなたが 修正不可能なラッパー を使っているからです。
この行を変更してください。
List<String> list = Arrays.asList(split);
この行に:
List<String> list = new LinkedList<>(Arrays.asList(split));
私はそれを置き換えると思います:
List<String> list = Arrays.asList(split);
と
List<String> list = new ArrayList<String>(Arrays.asList(split));
問題を解決します。
Arrays.asList()
によって返されるリストは不変かもしれません。試してもらえますか
List<String> list = new ArrayList(Arrays.asList(split));
AsListメソッドのJavaDocを読んでください。
指定された配列内のオブジェクトの{@code List}を返します。 {@code List}のサイズは変更できません。つまり、追加と削除はサポートされていませんが、要素は設定できます。要素を設定すると、基になる配列が変更されます。
これはJava 6からのものですが、Android Javaでも同じです。
_編集_
結果のリストの型はArrays.ArrayList
です。これはArrays.class内のプライベートクラスです。実際には、これはArrays.asList
で渡した配列のリストビューに他なりません。その結果、配列を変更するとリストも変更されます。また、配列はサイズ変更できないため、削除と追加の操作はサポートされていません。
Arrays.asList()は、サイズに影響する操作を許可しないリストを返します(これは「変更不可能」と同じではないことに注意してください)。
実際のコピーを作成するためにnew ArrayList<String>(Arrays.asList(split));
を実行することもできますが、自分が何をしようとしているのかを確認するための追加の提案があります(その下にO(n^2)
アルゴリズムがあります)。
リストからlist.size() - count
(これをk
と呼びましょう)ランダム要素を削除します。無作為の要素をいくつでも選んで、それらをリストの最後のk
の位置に交換してから、その範囲全体を削除してください(たとえば、subList()およびclear()を使用して)。それは無駄のないそしてO(n)
アルゴリズムを意味するでしょう(O(k)
はより正確です)。
更新 :下記のように、このアルゴリズムは要素が順序付けられていない場合にのみ意味を持ちます。リストがバッグを表す場合一方、リストに意味のある順序がある場合、このアルゴリズムはそれを保持しません(代わりにpolygenelubricantsのアルゴリズムが保持します)。
更新2 :それでは振り返ってみると、より良い(線形、順序を維持するがO(n)乱数を使った)アルゴリズムは次のようになるだろう。
LinkedList<String> elements = ...; //to avoid the slow ArrayList.remove()
int k = elements.size() - count; //elements to select/delete
int remaining = elements.size(); //elements remaining to be iterated
for (Iterator i = elements.iterator(); k > 0 && i.hasNext(); remaining--) {
i.next();
if (random.nextInt(remaining) < k) {
//or (random.nextDouble() < (double)k/remaining)
i.remove();
k--;
}
}
私はその問題に対する別の解決策を得ました:
List<String> list = Arrays.asList(split);
List<String> newList = new ArrayList<>(list);
newList
;)で作業する
このUnsupportedOperationExceptionは、コレクションに対して許可されていない操作を実行しようとしたときに発生します。この場合、Arrays.asList
を呼び出してもJava.util.ArrayList
は返されません。不変リストであるJava.util.Arrays$ArrayList
を返します。あなたはそれに追加することはできませんし、あなたはそれから削除することはできません。
はい、Arrays.asList
では固定サイズのリストを返します。
リンクリストを使用する以外に、単にaddAll
メソッドリストを使用してください。
例:
String idList = "123,222,333,444";
List<String> parentRecepeIdList = new ArrayList<String>();
parentRecepeIdList.addAll(Arrays.asList(idList.split(",")));
parentRecepeIdList.add("555");
Arraylist narraylist = Arrays.asList(); //不変の配列リストを返します可変ソリューションを作成するには、Arraylist narraylist = new ArrayList(Arrays.asList());
削除することも、固定サイズの配列リストに追加することもできません。
しかし、あなたはそのリストからあなたのサブリストを作成することができます。
list = list.subList(0, list.size() - (list.size() - count));
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 = list.subList(0, list.size() - (list.size() - count));
}
return StringUtils.join(list, ", ");
}
*他の方法は
ArrayList<String> al = new ArrayList<String>(Arrays.asList(template));
これは、Arrays.asListのように固定サイズではないArrayListを作成します。
交換する
List<String> list=Arrays.asList(split);
に
List<String> list = New ArrayList<>();
list.addAll(Arrays.asList(split));
または
List<String> list = new ArrayList<>(Arrays.asList(split));
または
List<String> list = new ArrayList<String>(Arrays.asList(split));
または(要素を削除する方が良い)
List<String> list = new LinkedList<>(Arrays.asList(split));
以下は配列のコードの一部です。
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
/**
* @serial include
*/
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, Java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
そのため、asListメソッドが呼び出されると、AbstractListのadd関数を配列の要素に格納することをオーバーライドしない、独自のプライベート静的クラスバージョンのリストが返されます。そのため、デフォルトでは抽象リストのaddメソッドは例外をスローします。
そのため、通常の配列リストではありません。
Arrays.asList()
は内部的に固定サイズの配列を使います。
thisArrays.asList()
に動的に追加または削除することはできません
これを使って
Arraylist<String> narraylist=new ArrayList(Arrays.asList());
narraylist
では、アイテムを簡単に追加または削除できます。