生成任意长度的随机字符串。我知道这个问题已被多次询问,我在下面编写了这段代码,我只是想知道有没有更好的方法,然后我写下面的代码?或者我们可以使下面的代码更有效率?
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();
}
答案 0 :(得分: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);
}
总结:
Random
实例。这可能是最大的优化,因为创建实例通常涉及系统调用以获取随机种子。 StringBuilder
工作正常时,请勿使用char[]
。charAt
。(/ li>)的(小)开销
(请注意,第3点和第4点可能不值得;即JIT编译器可能足够聪明,可以为您进行相同的优化...如果你只是让它。)
答案 1 :(得分:2)
由于您事先知道长度,因此请使用容量设置StringBuilder:
StringBuilder sb = new StringBuilder(length);
仅此一项就消除了StringBuilder中内部数组的不必要的大小调整。
话虽这么说,你最好使用char []数组而不是StringBuilder,并且只是将子集表示为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数组会更有效。
答案 2 :(得分:1)
您可以将String
投射到int
并直接使用char
,而不是使用// 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)));
}
}
。
char[]
其他可能的优化:
StringBuilder
而不是subset
。static
字符串定义为final
和String
。当然,这些优化非常简单,在这个问题的背景下对你的程序没有太大的影响。
如果您需要使用一组固定的字符生成随机String
,那么我上面提到的方法将无效。您必须使用包含字符的{{1}},就像您在帖子中所做的那样。
答案 3 :(得分: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);
答案 4 :(得分:0)
如果要最小化对随机生成器的调用,可以从每个随机整数生成5个字符。但此实现仅适用于您精确的36个字符集:0123456789abcdefghijklmnopqrstuvwxyz
(请参阅Integer.toString() Javadoc)。
并且不可能的是,这种实施的模糊性可以补偿性能增益。
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
的出现频率会比其他角色慢得多)。