Javaで一定の文字列を含めたり、抜いた文字列を作成する

Dev/Java
Java

更新日時 : 2021/03/09 13:08
投稿日時 : 2021/03/07 10:39

概要

Stream式の復習やcommons-lang3のRandomStringUtilsの動作検証を兼ねて次のようなサンプルプログラムを書いた。

  • パスワードなど特定の種類の文字列を必ず含めたランダムな文字列を作成する
    • 記号を含めない(こっちはついで)
    • java.util.Randomのでのランダム文字列生成は偏りがあるらしいが今回考慮しない
  • クーポンコードなどの文字列を生成する際、Iや1などの入力間違いしやすい文字を抜いた文字列を作成する
  • あえてStringで定数は書かずに、charでStream式を書く
    • Stringでやった方がぶっちゃけ簡単(変更することないし)

ランダムな文字列生成

org.apache.commons.lang3.RandomStringUtilsクラスを使用した。
randomAlphanumericメソッドで英数字のランダムな文字列を生成可能。

String randomValue = RandomStringUtils.randomAlphanumeric(8);

特定の種類を必ず含める

他のメソッド調査すればできそうな気もしたが、文字列チェック(org.apache.commons.lang3.StringUtils.containsAnyメソッド)と回帰処理で実現してみた。
チェックの際は定数はStreamで定義している。(解説はしない)


private final int VALUE_LENGTH = 8;
private final char[] NUMBER = IntStream.rangeClosed('0', '9')
            .mapToObj(c -> "" + (char) c).collect(Collectors.joining()).toCharArray();
private final char[] LOWERCASE_ALPHABETS = IntStream.rangeClosed('a', 'z').mapToObj(c -> "" + (char) c).collect(Collectors.joining()).toCharArray();
private final char[] UPPERCASE_ALPHABETS = IntStream.rangeClosed('A', 'Z').mapToObj(c -> "" + (char) c).collect(Collectors.joining()).toCharArray();

public String randomValueForPassword() {
  String randomValue = RandomStringUtils.randomAlphanumeric(VALUE_LENGTH);
  while (isInValidRandomFormat(randomValue)) {
    randomValue = this.randomValueForPassword();
  }
  return randomValue;
}
private boolean isInValidRandomFormat(String value) {
  return !(StringUtils.containsAny(value, NUMBER) &&
         StringUtils.containsAny(value, LOWERCASE_ALPHABETS) &&
         StringUtils.containsAny(value, UPPERCASE_ALPHABETS));
}

特定の文字列を抜いた文字列を生成する

クーポン向けのコードは入力間違い防止を目的として、Ilなどの似た文字を抜いたりすることがある。RandomStringUtils.randomメソッドは特定の文字を指定して抜くことができるので、それを利用した。

# 上記のコード例で定義済みの定数やメソッドは省略
private final Set<Character> FORBIDDEN_CODE_CODE = new HashSet<>(Arrays.asList('1', 'l', 'I', 'o', 'O', '0'));
private final char[] COUPON_CODE_CHARACTERS = IntStream.rangeClosed(0x30, 0x7a)
        .filter(c -> Character.isLetterOrDigit(c) && !FORBIDDEN_CODE_CODE.contains((char) c))
        .mapToObj(c -> (char) c + "").collect(Collectors.joining()).toCharArray();
public String randomValueForCouponCode() {
  String randomValue = RandomStringUtils.random(VALUE_LENGTH, COUPON_CODE_CHARACTERS);
  while (isInValidRandomFormat(randomValue)) {
    randomValue = this.randomValueForCouponCode();
  }
  return randomValue;
}

まとめ

  • メソッドの使い方よりStream式で文字列指定や抜く方が詰まった。
    • !FORBIDDEN_CODE_CODE.contains((char) c))で、charの型変換しないとダメだとか
  • 簡単なプログラム書くときにRandomStringUtils便利

サンプルコード

https://github.com/vagivagi/demo-random-value