使用 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;
}