不清楚getRandomChar() 做了什么,是否值得围绕它构建另一个 Stream 操作。首先,流式传输随机值要简单得多。
例如,以下代码生成由A-Z 范围内的大写字母组成的随机字符串:
public static String nextString() {
return ThreadLocalRandom.current().ints(stringLength, 'A', 'Z'+1)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
}
如果预期字符不形成连续范围,您可以使用字符串常量命名允许的字符,例如
public static String nextString() {
String allowed = "XO+";
return ThreadLocalRandom.current().ints(stringLength, 0, allowed.length())
.map(allowed::charAt)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
}
当然,这个收集器不会像Collectors.joining() 那样隐藏StringBuilder,但另一方面,这个操作没有装箱开销,也不会创建临时字符串。
你可以使用类似的操作来构建字符池String:
static final String ASCII_LETTERS_AND_NUMBERS =
IntStream.concat(IntStream.concat(
IntStream.rangeClosed('A', 'Z'), IntStream.rangeClosed('a', 'z')),
IntStream.rangeClosed('0', '9'))
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
public static String nextString() {
return ThreadLocalRandom.current()
.ints(stringLength, 0, ASCII_LETTERS_AND_NUMBERS.length())
.map(ASCII_LETTERS_AND_NUMBERS::charAt)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
}
或者,挑战随机字符串的读者:
static final String ALL_LETTERS_AND_NUMBERS =
IntStream.rangeClosed(32, Character.MAX_VALUE)
.filter(Character::isLetterOrDigit)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
public static String nextString() {
return ThreadLocalRandom.current()
.ints(stringLength, 0, ALL_LETTERS_AND_NUMBERS.length())
.map(ALL_LETTERS_AND_NUMBERS::charAt)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
}