使用 Streams 生成随机字符串

创建随机 Strings 有时很有用,可能是作为 Web 服务的 Session-ID 或注册应用程序后的初始密码。这可以使用 Streams 轻松实现。

首先,我们需要初始化一个随机数生成器。为了增强生成的 Strings 的安全性,使用 SecureRandom 是个好主意。

注意 :创建 SecureRandom 是非常昂贵的,所以最好只做一次并且不时调用其中一种 setSeed() 方法来重新种植它。

private static final SecureRandom rng = new SecureRandom(SecureRandom.generateSeed(20)); 
//20 Bytes as a seed is rather arbitrary, it is the number used in the JavaDoc example

在创建随机 String 时,我们通常希望它们仅使用某些字符(例如,仅字母和数字)。因此,我们可以创建一个返回 boolean 的方法,以后可以用来过滤 Stream

//returns true for all chars in 0-9, a-z and A-Z
boolean useThisCharacter(char c){
    //check for range to avoid using all unicode Letter (e.g. some chinese symbols)
    return c >= '0' && c <= 'z' && Character.isLetterOrDigit(c);
}

接下来,我们可以利用 RNG 生成一个特定长度的随机字符串,其中包含通过 useThisCharacter 检查的字符集。

public String generateRandomString(long length){
    //Since there is no native CharStream, we use an IntStream instead
    //and convert it to a Stream<Character> using mapToObj.
    //We need to specify the boundaries for the int values to ensure they can safely be cast to char
    Stream<Character> randomCharStream = rng.ints(Character.MIN_CODE_POINT, Character.MAX_CODE_POINT).mapToObj(i -> (char)i).filter(c -> this::useThisCharacter).limit(length);

    //now we can use this Stream to build a String utilizing the collect method.
    String randomString = randomCharStream.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString();
    return randomString;
}