4

特定の長さのランダムな文字列を生成します。私はこの質問が何度も聞かれていることを知っています、私はこのコードを以下に書きました、私はただ私が書いた以下のコードよりも良いアプローチがあるか知りたいですか?または、以下のコードをより効率的にすることができますか?

public static void main(String[] args) {
    String s = randomString(25);
    System.out.println(s);
}

public static String randomString(final int length) {
    StringBuilder sb = new StringBuilder();
    Random r = new Random();
    String subset = "0123456789abcdefghijklmnopqrstuvwxyz";
    for (int i = 0; i < length; i++) {
        int index = r.nextInt(subset.length());
        char c = subset.charAt( index );
        sb.append( c );
    }
    return sb.toString();
}
4

5 に答える 5

4

事前に長さがわかっているので、次の容量でStringBuilderをセットアップします。

StringBuilder sb = new StringBuilder(length);

これだけで、StringBuilder内の内部配列の不要なサイズ変更がなくなります。

そうは言っても、StringBuilderの代わりにchar []配列を使用し、サブセットをchar[]として表す方がおそらく良いでしょう。

private static final char [] subset = "0123456789abcdefghijklmnopqrstuvwxyz".toCharArray();

char buf[] = new char[length];
for (int i=0;i<buf.length;i++) {
  int index = r.nextInt(subset.length);
  buf[i] = subset[index];
}

return new String(buf);

「charAt」および「append」への関数呼び出しのオーバーヘッドを回避することにより、ここで得られる微妙な利点がいくつかあります。また、StringBuilderのメモリと割り当て時間のオーバーヘッドの一部を排除します。一般に、作成する文字列のサイズがわかっている場合は、char配列を直接操作する方が少し効率的です。

于 2012-05-27T02:52:45.210 に答える
3

まず、このメソッドのパフォーマンスを改善する必要がない可能性があります。メソッドが頻繁に呼び出されないため、メソッドを最適化すると、アプリケーションの全体的なパフォーマンスに顕著な違いが生じる可能性があります。このレベルで最適化する前に、アプリケーションのプロファイルを作成する必要があります。そうしないと、違いがないものに時間を浪費するリスクがあります。

次に、これが価値のある最適化である場合でも、アプリケーションのプロファイルを作成して、どの最適化が最も効果的か、そして最適化の取り組みが実際に何らかの違いをもたらしたかどうかを判断する必要があります。


(仮に)これをできるだけ速く行おうとするとしたら、これを試してみます。

private static final char[] subset = 
        "0123456789abcdefghijklmnopqrstuvwxyz".toCharArray();
private static final Random prng = new Random();
...
public static String randomString(final int length) {
    char[] chars = new char[length];
    final int subsetLength = subsetLength;
    for (int i = 0; i < length; i++) {
        int index = prng.nextInt(subsetLength);
        chars[i] = subset[index];
    }
    return new String(chars);
}

要約すれば:

  1. Random毎回新しいインスタンスを作成しないでください。インスタンスの作成には通常、ランダムシードを取得するためのシステムコールが含まれるため、これはおそらくこの最大の最適化です。
  2. うまく機能するStringBuilder場合は、を使用しないでください。char[]
  3. の(小さな)オーバーヘッドを避けてくださいcharAt
  4. 可能な場合は、ループやメソッド呼び出しから1回限りのタスクを引き上げます。

(ポイント3と4は価値がないことが判明する可能性があることに注意してください。つまり、JITコンパイラーは、同じ最適化を実行できるほど賢い可能性があります。

于 2012-05-27T03:03:50.510 に答える
1

指定した文字列と長さのみを使用してランダムな文字列を作成します。RandomStringUtilsを使用します。ランダムな文字列を生成する場合例: RandomStringUtils#random :指定された文字列と長さは25です

private static final SecureRandom RANDOM = new SecureRandom();
private static final char[] PASSWORD_CHARS=("0123456789abcdefghijklmnopqrstuvwxyz").toCharArray();
String passwd=RandomStringUtils.random(25, 0, PASSWORD_CHARS.length, false, false, PASSWORD_CHARS, RANDOM);
于 2012-05-27T09:30:43.830 に答える
1

sを操作するのではなく、直接Stringキャストintcharて使用することができます。

// 36 total alpha-numeric characters
int size = 36;

for (int i=0; i<length; i++) {
    // num is an integer from 0-35
    int num = r.nextInt(size);

    if (num < 26) {
        // Then we add a lowercase character
        sb.append((char)('a'+num));
    } else {
        // then we add a digit 0-9
        sb.append((char)('0'+(num-26)));
    }
}

その他の可能な最適化:

  1. char[]ではなく、固定サイズで作業しStringBuilderます。
  2. subset文字列をとにstatic定義しますfinal

もちろん、これらの最適化は非常に簡単であり、この質問のコンテキストではプログラムに大きな影響を与えることはありません。


編集:

固定された文字セットでランダムを生成する必要がある場合String、上記のアプローチは機能しません。String投稿で行ったように、文字を含むものを操作する必要があります。

于 2012-05-27T02:18:56.667 に答える
0

ランダムジェネレーターへの呼び出しを最小限に抑えたい場合は、各乱数から5文字を生成できます。ただし、この実装は、正確な36文字セットに対してのみ機能します( Integer.toString()Javadoc0123456789abcdefghijklmnopqrstuvwxyzを参照)。そして、この実装のあいまいさがパフォーマンスの向上を補う可能性はほとんどありません。

private static final int range = 36 * 36 * 36 * 36 * 36; // 36^5 is less than 2^31
private static Random rand = new Random();
private static String zeroes="00000";

public static String generate(int length) {
    StringBuilder sb = new StringBuilder(length+5);
    while (sb.length() < length) {
        String x = Integer.toString(rand.nextInt(range), 36);
        if(x.length()<5)
            sb.append(zeroes.substring(0, 5-x.length()));
        sb.append(x);
    }
    return sb.substring(0, length);
}

ゼロ追加は、文字が均一にランダムであることを保証します(ゼロ追加がないと、文字0は他の文字よりもわずかに少ない頻度で表示されます)。

于 2012-05-27T03:36:56.013 に答える