0

リストをランダム化するメソッドを作成しました:

public <T> List<T> randomize(List<T> list) {
    LinkedList<T> randomizedList = new LinkedList<>();
    Random random = new Random(list.size());
    for (int i = random.nextInt(); i < list.size(); i++) {
        randomizedList.add(list.get(i));
    }
    return randomizedList;
}

このメソッドに渡すリストには、たとえば 5 つの要素が含まれています。私が作成Random random = new Random(list.size());しているとき、何を呼び出すrandom.nextInt()と、リスト要素のインデックスとなるランダムな整数が返されると期待しています。

しかし、(返されると予想される)random.nextInt();間隔から数値を返す代わりに呼び出すと、 for eg: の値が返されます。これは私に.[0, 4]-349120689java.lang.IndexOutOfBoundsException: Index: -349120689, Size: 5

なぜこれが起こっているのですか、これを解決する方法は?

4

5 に答える 5

3
  1. new Random(list.size());これにより、乱数ジェネレーターのシードが に設定されます。list.size();変更することをお勧めしnew Random()ます (これにより、システムの現在の時刻に基づいてシードが得られます)。ただし、できれば常に同じ Random オブジェクトを再利用することをお勧めします。

  2. random.nextInt();random.nextInt(list.size());これは、0 から list.size() - 1 までの数値を与える場所です。

  3. 上記の変更を行っても、コードは、ランダムなインデックスから始まり、最後まで続くリストのサブリストを提供するだけです。Collections.shuffle(list)代わりに使用してください。

実際のシャッフルを行うには、どの要素を挿入したか、または挿入しなかったかを「覚えておく」必要があります。疑似コードでは、次のことができます。

  • 元のリストを新しいリストにコピーします。それを「orig」と呼びましょう
  • 新しい空のリストを作成し、それを「結果」と呼びましょう
  • 元のリストに要素がある限り、ランダムなインデックスで要素を取得し、結果リストに追加します。選択した要素を orig リストから削除します。
  • 結果リストを返します。
于 2013-02-08T12:24:26.367 に答える
2

random.nextInt() を呼び出すと、リスト要素のインデックスとなるランダムな整数が返されると思います。

Random(long)コンストラクタの目的を誤解しています。そのコンストラクターの目的は、リストのシードを指定することです。これは、サイズ 5 のすべてのコレクションが常に同じ方法でシャッフルされることを意味します

を呼び出すたびに範囲を指定しますnextInt。したがって、0 (含む) から (含まない) までの乱数が必要な場合は、次のようmaxにします。

int value = random.nextInt(max);

ただし、これを行うために独自のコードを作成する代わりに使用する方がはるかに優れています-シャッフルが本当に必要Collections.shuffleであると仮定します(これは、とにかく現在のアプローチでは得られないものです-呼び出しを修正した後でも、終了しますは一度しか呼び出されないため、基本的にサブリストを使用します.したがって、最初の呼び出しが(5つのリストで)2を返す場合、最後の3つの要素を含む新しいリストを返すことになります.それはあなたがそうであったものではないと強く思いますしようとしています。nextIntnextInt()nextInt()

補足として、API が期待どおりに動作しない理由を知りたい場合は、ドキュメントをお読みくださいRandom(long)コンストラクターのドキュメントは、Random.nextInt()明らかに期待した動作ではありません。

于 2013-02-08T12:24:53.157 に答える
0

これを使って

public <T> List<T> randomize(List<T> list) {
    LinkedList<T> randomizedList = new LinkedList<>();
    Random random = new Random();
    for (int i = random.nextInt(list.size()); i < list.size(); i++) {
        randomizedList.add(list.get(i));
    }
    return randomizedList;
}
于 2013-02-08T12:23:41.077 に答える
0

コンストラクターへの引数Randomは、返されるものの最大値ではなく、ランダム シードです。

代わりに最大数を渡しnextInt()ます。

于 2013-02-08T12:24:03.333 に答える
0

nextInt(n)(ランダム化の上限) への引数とコンストラクターへの引数 (ランダム シード) を混同しています。を使用する必要nextInt(list.size)があり、おそらく を使用して Random オブジェクトを初期化しますnew Random()

于 2013-02-08T12:24:12.823 に答える