获得第n个nextInt值的最快方法是什么?

时间:2019-05-25 17:01:13

标签: java arrays arraylist random int

我必须找到每个数组元素的第n个nextInt。 下面的代码确实很慢,因为数组元素超过40k,每个数组元素超过一百万。

int[] numbers ={1000000,1004300,2204000,1306000...40k+};
for (int i = 0; i <numbers.length; i++) {
Random ran = new Random(1234);
    int nex = 0;
    for (int n = 0; n <numbers[i]; n++) {
        nex = ran.nextInt();
    }
    System.out.println("Next int value: " + nex);
}

是否有更快的方法来获取百万分之一的nextInt?如果是,请如何?

2 个答案:

答案 0 :(得分:0)

您正在设置随机数生成器的“种子”值。这意味着每次运行此代码时,它将产生相同的随机数序列,因此该序列是可预测的。

如果您确实是在生成随机数,那么生成百万分之一的随机数将与生成第一个随机数相同,因为没人能分辨出这两个不可预测的结果之间的差异。

因此,第一个潜在的优化方法是:不要使用可预测的序列,而采用第一个随机数。这将需要一个很小的恒定时间。

接下来,如果您需要这种可重复性,则可以对其进行预先计算,并且您的代码将包含该结果表。然后,您可以在恒定时间内查看结果。

如果您需要看起来像随机的可重复序列,但不一定非要使用此特定序列,则可以使用其他伪随机数生成器。例如,您可以使用分组密码对“索引”(在您的示例中为100万)进行加密,然后从结果中使用一些字节。这也是恒定时间算法,与索引无关。

这是最后一个想法的实现:

public class PredictableSequenceGenerator {

  private final int[] numbers;

  public PredictableSequenceGenerator(int[] numbers) {
    this.numbers = Objects.requireNonNull(numbers);
  }

  public int[] generate(long seed) {
    ByteBuffer src = ByteBuffer.wrap(new byte[16]);
    ByteBuffer dst = ByteBuffer.wrap(new byte[16]);
    src.putLong(seed).putLong(seed);
    SecretKey key = new SecretKeySpec(src.array(), "AES");
    Cipher cipher;
    try {
      cipher = Cipher.getInstance("AES/ECB/NoPadding");
      cipher.init(Cipher.ENCRYPT_MODE, key);
    } catch (GeneralSecurityException ex) {
      throw new IllegalStateException("Failed to initialize generator.", ex);
    }
    int[] results = new int[numbers.length];
    for (int idx = 0; idx < numbers.length; ++idx) {
      src.clear();
      src.putInt(0, idx);
      dst.clear();
      try {
        cipher.doFinal(src, dst);
      } catch (GeneralSecurityException ex) {
        throw new IllegalStateException("Failed to transform index.", ex);
      }
      results[idx] = dst.flip().getInt();
    }
    return results;
  }

  public static void main(String... argv) {
    int[] numbers = { 1000000, 1004300, 2204000, 1306000, /* 40k+ */ };
    PredictableSequenceGenerator gen = new PredictableSequenceGenerator(numbers);
    int[] random = gen.generate(1234);
    for (int r : random)
      System.out.println(r);
  }

}

答案 1 :(得分:0)

您是否真的需要种子,以便每次的随机序列都相同?然后,您可以对数字数组进行升序排序。然后,对于第二个元素,您无需重置随机生成器,而只需继续您离开的位置即可。这样一来,您只需调用nextInt的次数就可以与数组中最高的次数相同,而不是400亿次