mike-neckのブログ

Java or Groovy or Swift or Golang

昨日書いたダメなコード

毎日残念なコード書いてるので続けてみる

前提

  • Java7(今日は関係ない)

やりたいこと

  • 指定した範囲のランダムな long の値がほしい

書いたコード

例 : 上限値(long かつ max > 0)を受け取ってランダムな値を返す

final Random random = new Random();

long randomLong(final long max) {
  while(true) {
    final long generated = random.nextLong();
    if (0 <= generated && generated < max) {
      return generated;
    }
  }
}

ダメなところ

max の値が小さいと時間がかかりすぎるというかほぼ無理ゲー

どう書くのがよかったか

ThreadLocalRandom を使う

long randomLong(final long max) {
  return ThreadLocalRandom.current().nextLong(max);
}

ThreadLocalRandom では seed を設定できないため(setSeedUnsupportedOperationException を投げる)、 seed を使いたい場合は元の Random を使うしかないので、 BigInteger を強引に用いる

final Random random = ...;
long randomLong(final long max) {
  final int bitLength = BigInteger.valueOf(max).bitLength();
  while(true) {
    final long generated = new BigInteger(bitLength, random).longValue();
    if (generated < max) {
      return generated;
    }
  }
}

実は ThreadLocalRandom はつい今しがた知ったので、実際は下の方法を使った