Apache Commons Text:特殊字符的随机字符串java

iam*_*nos 0 java random apache-commons java-8

我正在使用 apachecommons-text:RandomStringGenerator来生成这样的随机数String

//Utilities
private static RandomStringGenerator generator(int minimumCodePoint, int maximumCodePoint, CharacterPredicates... predicates) {
    return new RandomStringGenerator.Builder()
            .withinRange(minimumCodePoint, maximumCodePoint)
            .filteredBy(predicates)
            .build();
}

public static String randStringAlpha(int length) {
    return generator('A', 'z', CharacterPredicates.LETTERS).generate(length);
}

public static String randStringAlphaNum(int length) {
    return generator('1', 'z', CharacterPredicates.LETTERS, CharacterPredicates.DIGITS).generate(length);
}

//Generation
private void foo() {
    String alpha = randStringAlpha(255);
    String num = randStringAlphaNum(255);
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种使用相同库生成以下内容的方法:

  • A - 特殊字符(可能仅限于键盘特殊字符)
  • B - 阿尔法 + A
  • C - 数字 + A
  • D - 字母 + 数字 + A

    我已经检查过,CharacterPredicates enum但它只有LETTERSDIGITS用于过滤。任何帮助将非常感激!

    编辑:================================================

    我决定搁置我当前的解决方案以支持这个答案。
    为了澄清“特殊字符”的范围,我实际上是在寻找这个子集: 在此处输入图片说明

    案例 A 的片段:

    public static CharSequence asciiSpecial() {
        return asciiCharacters().toString().replaceAll("(\\d|[A-z])","");
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • Hol*_*ger 5

    你的类别“特殊字符”是安静的模糊。只要保持在 ASCII 范围内,所有字符都是字母、数字或“特殊”,但可以用普通键盘输入。换句话说,您根本不需要为此指定过滤器。另一方面,当您离开 ASCII 范围时,您必须关注多种字符类别(例如,您不想在任意点插入随机组合字符),此外,没有一般测试是否可以用键盘输入字符(因为没有通用键盘)...

    但请注意,您尝试使用该库的代码已经比执行实际工作的代码大。例如,要获取随机字母字符串,您可以使用

    public static String randStringAlpha(int size) {
        return ThreadLocalRandom.current().ints('A', 'z'+1)
            .filter(Character::isLetter)
            .limit(size)
            .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
            .toString();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    或者可能更有效的变体

    public static String randStringAlpha(int size) {
        return ThreadLocalRandom.current().ints(size, 'A', 'Z'+1)
            .map(c -> ThreadLocalRandom.current().nextBoolean()? c: Character.toLowerCase(c))
            .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
            .toString();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    没有任何 3rd 方库。

    同样,您可以使用

    public static String randomString(int size, CharSequence validChars) {
        return ThreadLocalRandom.current().ints(size, 0, validChars.length())
            .map(validChars::charAt)
            .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
            .toString();
    }
    public static String randomString(int minSizeIncl, int maxSizeIncl, CharSequence valid) {
        return randomString(
            ThreadLocalRandom.current().nextInt(minSizeIncl, maxSizeIncl), valid);
    }
    public static CharSequence asciiLetters() {
        return IntStream.concat(IntStream.rangeClosed('A','Z'), IntStream.rangeClosed('a','z'))
            .collect(StringBuilder::new,StringBuilder::appendCodePoint,StringBuilder::append);
    }
    public static CharSequence asciiLetterOrDigit() {
        return IntStream.concat(asciiLetters().chars(),IntStream.rangeClosed('0', '9'))
            .collect(StringBuilder::new,StringBuilder::appendCodePoint,StringBuilder::append);
    }
    public static CharSequence asciiCharacters() {
        return IntStream.rangeClosed('!', '~')
            .collect(StringBuilder::new,StringBuilder::appendCodePoint,StringBuilder::append);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    您可以通过组合两种方法来使用,例如
    RandomString.randomString(10, asciiLetters()),
    RandomString.randomString(10, asciiLetterOrDigit()), or
    RandomString.randomString(10, asciiCharacters()), resp。他们的可变大小对应物,如RandomString.randomString(10, 20, asciiCharacters()).

    CharSequenceS能多串产生通话之间可以重复使用,将类似于构建RandomStringGenerator和多次使用它。