Menghasilkan Angka Acak di Jawa

1. Ikhtisar

Dalam tutorial ini, kita akan mengeksplorasi berbagai cara menghasilkan angka acak di Java.

2. Menggunakan Java API

Java API memberi kita beberapa cara untuk mencapai tujuan kita. Mari kita lihat beberapa di antaranya.

2.1. java.lang.Math

The acak metode dari Math kelas akan mengembalikan ganda nilai berkisar dari 0,0 (inklusif) ke 1,0 (eksklusif). Mari kita lihat bagaimana kita akan menggunakannya untuk mendapatkan nomor acak dalam kisaran tertentu yang ditentukan oleh min dan max :

int randomWithMathRandom = (int) ((Math.random() * (max - min)) + min);

2.2. java.util.Random

Sebelum Java 1.7, cara paling populer untuk menghasilkan bilangan acak adalah menggunakan nextInt . Ada dua cara untuk menggunakan metode ini, dengan dan tanpa parameter. Pemanggilan tanpa parameter mengembalikan salah satu nilai int dengan probabilitas yang kira-kira sama. Jadi, kemungkinan besar kita akan mendapatkan angka negatif:

Random random = new Random(); int randomWithNextInt = random.nextInt();

Jika kita menggunakan pemanggilan netxInt dengan parameter terikat , kita akan mendapatkan angka dalam rentang:

int randomWintNextIntWithinARange = random.nextInt(max - min) + min;

Ini akan memberi kita angka antara 0 (inklusif) dan parameter (eksklusif). Jadi, parameter terikat harus lebih besar dari 0. Jika tidak, kita akan mendapatkan java.lang.IllegalArgumentException .

Java 8 memperkenalkan metode ints baru yang mengembalikan java.util.stream.IntStream. Mari kita lihat bagaimana cara menggunakannya.

The int Metode tanpa parameter mengembalikan aliran terbatas int nilai-nilai:

IntStream unlimitedIntStream = random.ints();

Kami juga dapat mengirimkan satu parameter untuk membatasi ukuran aliran:

IntStream limitedIntStream = random.ints(streamSize);

Dan, tentu saja, kami dapat menetapkan maksimum dan minimum untuk rentang yang dihasilkan:

IntStream limitedIntStreamWithinARange = random.ints(streamSize, min, max);

2.3. java.util.concurrent.ThreadLocalRandom

Rilis Java 1.7 memberi kami cara baru dan lebih efisien untuk menghasilkan nomor acak melalui kelas ThreadLocalRandom . Yang ini memiliki tiga perbedaan penting dari kelas Random :

  • Kami tidak perlu secara eksplisit memulai contoh baru ThreadLocalRandom . Ini membantu kami menghindari kesalahan dalam membuat banyak contoh yang tidak berguna dan membuang waktu pengumpul sampah
  • Kami tidak dapat menetapkan benih untuk ThreadLocalRandom , yang dapat menyebabkan masalah nyata. Jika kita perlu mengatur seed, maka kita harus menghindari cara menghasilkan angka acak ini
  • Kelas acak tidak bekerja dengan baik di lingkungan multi-utas

Sekarang, mari kita lihat cara kerjanya:

int randomWithThreadLocalRandomInARange = ThreadLocalRandom.current().nextInt(min, max);

Dengan Java 8 atau lebih tinggi, kami memiliki kemungkinan baru. Pertama, kami memiliki dua variasi untuk metode nextInt :

int randomWithThreadLocalRandom = ThreadLocalRandom.current().nextInt(); int randomWithThreadLocalRandomFromZero = ThreadLocalRandom.current().nextInt(max);

Kedua, dan yang lebih penting, kita dapat menggunakan metode ints :

IntStream streamWithThreadLocalRandom = ThreadLocalRandom.current().ints();

2.4. java.util.SplittableRandom

Java 8 juga memberi kita generator yang sangat cepat - kelas SplittableRandom .

Seperti yang bisa kita lihat di JavaDoc, ini adalah generator untuk digunakan dalam komputasi paralel. Penting untuk diketahui bahwa instance tidak aman untuk thread. Jadi, kami harus berhati-hati saat menggunakan kelas ini.

Kami telah menyediakan metode nextInt dan ints . Dengan nextInt kita dapat mengatur secara langsung rentang atas dan bawah menggunakan dua parameter pemanggilan:

SplittableRandom splittableRandom = new SplittableRandom(); int randomWithSplittableRandom = splittableRandom.nextInt(min, max);

Cara menggunakan ini memeriksa bahwa parameter maks lebih besar dari min . Jika tidak, kita akan mendapatkan IllegalArgumentException . Namun, itu tidak memeriksa apakah kita bekerja dengan bilangan positif atau negatif. Jadi, salah satu parameternya bisa negatif. Selain itu, kami memiliki pemanggilan satu dan nol parameter yang tersedia. Mereka bekerja dengan cara yang sama seperti yang telah kami jelaskan sebelumnya.

Kami juga telah menyediakan metode ints . Ini berarti kita bisa dengan mudah mendapatkan aliran nilai int . Untuk memperjelas, kita dapat memilih untuk memiliki streaming terbatas atau tidak terbatas. Untuk aliran terbatas, kami dapat mengatur bagian atas dan bawah untuk rentang pembangkitan nomor:

IntStream limitedIntStreamWithinARangeWithSplittableRandom = splittableRandom.ints(streamSize, min, max);

2.5. java.security.SecureRandom

Jika kami memiliki aplikasi yang sensitif terhadap keamanan, kami harus mempertimbangkan untuk menggunakan SecureRandom . Ini adalah generator yang kuat secara kriptografis. Instance yang dibuat secara default tidak menggunakan seed yang acak secara kriptografis. Jadi, kita harus:

  • Atur benih - akibatnya, benih tidak dapat diprediksi
  • Setel properti sistem java.util.secureRandomSeed ke true

Kelas ini mewarisi dari java.util.Random . Jadi, kami telah menyediakan semua metode yang kami lihat di atas. Misalnya, jika kita perlu mendapatkan salah satu nilai int , maka kita akan memanggil nextInt tanpa parameter:

SecureRandom secureRandom = new SecureRandom(); int randomWithSecureRandom = secureRandom.nextInt();

Di sisi lain, jika kita perlu mengatur range, kita bisa memanggilnya dengan parameter terikat :

int randomWithSecureRandomWithinARange = secureRandom.nextInt(max - min) + min;

We must remember that this way of using it throws IllegalArgumentException if the parameter is not bigger than zero.

3. Using Third-Party APIs

As we have seen, Java provides us with a lot of classes and methods for generating random numbers. However, there are also third-party APIs for this purpose.

We're going to take a look at some of them.

3.1. org.apache.commons.math3.random.RandomDataGenerator

There are a lot of generators in the commons mathematics library from the Apache Commons project. The easiest, and probably the most useful, is the RandomDataGenerator. It uses the Well19937c algorithm for the random generation. However, we can provide our algorithm implementation.

Let’s see how to use it. Firstly, we have to add dependency:

 org.apache.commons commons-math3 3.6.1 

The latest version of commons-math3 can be found on Maven Central.

Then we can start working with it:

RandomDataGenerator randomDataGenerator = new RandomDataGenerator(); int randomWithRandomDataGenerator = randomDataGenerator.nextInt(min, max);

3.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

Certainly, this is one of the fastest random number generator implementations. It has been developed at the Information Sciences Department of the Milan University.

The library is also available at Maven Central repositories. So, let's add the dependency:

 it.unimi.dsi dsiutils 2.6.0 

Generator ini mewarisi dari java.util.Random . Namun, jika kita melihat JavaDoc, kita menyadari bahwa hanya ada satu cara untuk menggunakannya - melalui metode nextInt . Di atas segalanya, metode ini hanya tersedia dengan pemanggilan parameter nol dan satu. Salah satu pemanggilan lainnya akan langsung menggunakan metode java.util.Random .

Misalnya, jika kita ingin mendapatkan nomor acak dalam suatu rentang, kita akan menulis:

XoRoShiRo128PlusRandom xoroRandom = new XoRoShiRo128PlusRandom(); int randomWithXoRoShiRo128PlusRandom = xoroRandom.nextInt(max - min) + min;

4. Kesimpulan

Ada beberapa cara untuk menerapkan pembuatan nomor acak. Namun, tidak ada cara terbaik. Karenanya, kita harus memilih salah satu yang paling sesuai dengan kebutuhan kita.

Contoh lengkapnya dapat ditemukan di GitHub.