Tạo số và chuỗi ngẫu nhiên trong Java

56854

Bài viết được sự cho phép của tác giả Giang Phan

Tạo số ngẫu nhiên – Random number

Trong Java để tạo một số ngẫu nhiên chúng ta có thể sử dụng class java.util.Random đã được hợp trong JDK. Có rất nhiều trường hợp sử dụng random, trong bài này tôi sẽ hướng dẫn các bạn sử dụng Random trong một số trường hợp thường gặp.

Tuyển dụng Java không yêu cầu kinh nghiệm

Khởi tạo Random Generator

Để tạo một trình tạo số ngẫu nhiên (generator), đơn giản chỉ việc tạo một new instance của Random.

Random generator = new Random();

Khi sử dụng hàm tạo này, bạn sẽ nhận ra rằng các trình tạo số ngẫu nhiên thuật toán không thực sự ngẫu nhiên, chúng thực sự là các thuật toán tạo ra một chuỗi số cố định nhưng trông ngẫu nhiên.

Khi tạo một generator, nó sẽ khởi tạo chuỗi của nó từ một giá trị được gọi là “seed” của nó. Khi chúng ta sử dụng constructor không có tham số, nó sẽ tạo seed có một giá trị khác biệt với bất kỳ lời gọi nào khác của constructor này. Nhưng chúng ta không kiểm soát được giá trị đó là gì, hoặc thậm chí đảm bảo hoàn toàn rằng nó sẽ khác với seed được sử dụng bởi các lời gọi khác trên constructor này.

Nếu thích, chúng ta cũng có thể chỉ định một giá trị bất kỳ thuộc kiểu “long” để khởi tạo cho seed. Ví dụ:

Random generator = new Random(19900828);

Sau khi đã có generator, gọi các phương thức nextXxx() để tạo các giá trị ngẫu nhiên:

  • nextInt() : trả về một số ngẫu nhiên trong khoảng giá trị của int value (từ -2^31 đến 2^31-1).
  • nextInt(maxNumber) : trả về một số int ngẫu nhiên từ 0 đến giá trị < maxNumber.
  • nextLong() : trả về một số ngẫu nhiên kiểu long. Vì Random sử dụng giá trị seed chỉ 48bits, nên thuật toán random không thể trả về tất cả các giá trị thuộc kiểu long.
  • nextFloat(): trả về một số ngẫu nhiên trong khoảng 0.0 và <1.0
  • nextDouble() : tương tự như nextFloat() như độ dài phần thập phân lớn hơn.
  • nextBoolean() : trả về giá trị true, false ngẫu nhiên.

Ví dụ Random

Random generator = new Random(); System.out.println("Random Integer: " + generator.nextInt()); System.out.println("Random Long: " + generator.nextLong()); System.out.println("Random Float: " + generator.nextFloat()); System.out.println("Random Double: " + generator.nextDouble()); System.out.println("Random Boolean: " + generator.nextBoolean()); byte[] bytes = "gpcoder.com".getBytes(); System.out.println("Before Random Bytes : " + new String(bytes)); generator.nextBytes(bytes); System.out.println("After Random Bytes : " + new String(bytes));

Chạy chương trình trên nhiều lần, mỗi lần bạn sẽ thấy kết quả khác nhau:

Random Double: 0.89349867666ần, mỗi lần bạn sẽ thấy kết quả khác nhau:
// 1st Random Integer: -2066769060 Random Long: -8130094582138669218
Random Float: 0.77755750781 Random Boolean: false Before Random Bytes : gpcoder.com After Random Bytes : oyl͚��Iz // 2nd Random Integer: 169814716 Random Long: -8850209899969366472 Random Float: 0.15561897 Random Double: 0.3569224569686996 Random Boolean: false Before Random Bytes : gpcoder.com After Random Bytes : ��&��`d'

Ví dụ giới hạn giá trị Random Number

Đôi khi chúng ta cần số ngẫu nhiên nằm trong một phạm vi khác nhau. Chúng ta có thể làm cho các số ngẫu nhiên nằm trong một phạm vi rộng hơn hoặc hẹp hơn bằng cách nhân chúng với một hệ số tỷ lệ. Chúng ta cũng có thể đặt các số ngẫu nhiên nằm trong một phạm vi được chuyển sang các số lớn hơn hoặc nhỏ hơn so với ban đầu bằng cách cộng thêm (hoặc trừ) một phần bù từ các số ngẫu nhiên.

Ví dụ 1: chúng ta có một game có 4 người chơi, mỗi người có 1 số từ một đến 4. Chương trình của chúng ta sẽ random từ 1 đến 4 để lựa chọn người may mắn có số trùng với số được random. Đơn giản chỉ việc gọi hàm nextInt(4), hàm này sẽ trả về giá trị từ 0 đến 3, nên chúng ta cần cộng thêm 1 để có kết quả như ý muốn.

int value = generator.nextInt(4) + 1;

Ví dụ 2: Cần vẽ random một line có góc từ 0 đến 360 độ.

double value = generator.nextDouble() * 360.0;

Ví dụ 3: Random int number trong khoảng được chỉ định.

int value = generator.nextInt((max - min) + 1) + min;

Ví dụ 4: Trong một số ứng dụng đăng nhập bằng số điện thoại như Google, sau khi nhập số điện thoại, Google sẽ gửi một mã xác nhận số điện thoại gồm 6 số ngẫu nhiên. Chúng ta cũng có thể tạo số ngẫu nhiên này với Random.

int code = (int) Math.floor(((Math.random() * 899999) + 100000));

Lưu ý: Instances của java.util.Random là Thread safe. Tuy nhiên, việc sử dụng đồng thời cùng một đối tượng java.util.Random trong môi trường đa luồng (multi-thread) có thể gặp phải sự tranh chấp và hiệu suất kém. Thay vào đó hãy xem xét sử dụng ThreadLocalRandom trong các thiết kế đa luồng. Nếu cần Security random có thể sử dụng SecureRandom.

Tạo chuỗi ngẫu nhiên – Random string

Có nhiều trường hợp chúng ta cần tạo chuỗi ngẫu nhiên, chẳng hạn tạo ra mã captcha để chống spam, gửi mã code xác nhận tài khoản, …. Có nhiều cách để tạo chuỗi ngẫu nhiên, trong bài này tôi sẽ hướng dẫn các bạn tự tạo chuỗi ngẫu nhiên và sử dụng thư viện Apache common.

Tự tạo chuỗi ngẫu nhiên

Để tạo một chuỗi ngẫu nhiên, chúng ta sẽ định nghĩa một chuỗi các ký tự được phép xuất hiện trong chuỗi ngẫu nhiên. Sau đó sẽ sử dụng Random để tạo một giá trị index ngẫu nhiên từ chuỗi đã định nghĩa trước đó. Cứ thực hiện random index và truy xuất ký tự từ index cho đến khi đầy đủ số lượng ký tự mong muốn.

Trong ví dụ này, tôi sẽ tạo 2 phương thức:

  • randomAlphaNumeric(): Tạo một chuỗi ngẫu nhiên chỉ bao gồm các ký tự từ a-z, A-Z và 0-9, không bao gồm các ký tự đặc biệt.
  • randomPassword(): Tạo một chuỗi password ngẫu nhiên bao gồm ít nhất 1 ký tự đặc biệt và 1 ký tự số.
package com.gpcoder.random; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import java.util.function.Consumer; public class RandomStringExmple {     private static final String alpha = "abcdefghijklmnopqrstuvwxyz"; // a-z     private static final String alphaUpperCase = alpha.toUpperCase(); // A-Z     private static final String digits = "0123456789"; // 0-9     private static final String specials = "~=+%^*/()[]{}/!@#$?|";     private static final String ALPHA_NUMERIC = alpha + alphaUpperCase + digits;     private static final String ALL = alpha + alphaUpperCase + digits + specials;     private static Random generator = new Random()
     /**      * Random string with a-zA-Z0-9, not included special characters      */     public String randomAlphaNumeric(int numberOfCharactor) {         StringBuilder sb = new StringBuilder();         for (int i = 0; i < numberOfCharactor; i++) {             int number = randomNumber(0, ALPHA_NUMERIC.length() - 1);             char ch = ALPHA_NUMERIC.charAt(number);             sb.append(ch);         }         return sb.toString();     }     /**      * Random string password with at least 1 digit and 1 special character      */     public String randomPassword(int numberOfCharactor) {         List<String> result = new ArrayList<>();         Consumer<String> appendChar = s -> {             int number = randomNumber(0, s.length() - 1);             result.add("" + s.charAt(number));         };         appendChar.accept(digits);         appendChar.accept(specials);         while (result.size() < numberOfCharactor) {             appendChar.accept(ALL);         }         Collections.shuffle(result, generator);         return String.join("", result);     }     public static int randomNumber(int min, int max) {         return generator.nextInt((max - min) + 1) + min;     }     public static void main(String a[]){         int numberOfCharactor = 8;         RandomStringExmple rand = new RandomStringExmple();             System.out.println("randomString1: " + rand.randomAlphaNumeric(numberOfCharactor));         System.out.println("randomString1: " + rand.randomAlphaNumeric(numberOfCharactor));         System.out.println("randomString1: " + rand.randomAlphaNumeric(numberOfCharactor));         System.out.println("randomPassword1: " + rand.randomPassword(numberOfCharactor));         System.out.println("randomPassword2: " + rand.randomPassword(numberOfCharactor));     } }

Chạy chương trình trên nhiều lần, chúng ta sẽ thấy các kết quả khác nhau:

randomString1: 65cihDTo randomString1: GbEMJBVH randomString1: WJF7hZ3c randomPassword1: #f|XD/W3 randomPassword2: |M$=}=2A
  10 Java Web Framework tốt nhất
  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java

Sử dụng lớp commons.lang3.text.RandomStringUtils

Một số phương thức hỗ trợ tạo chuỗi và số ngẫu nhiên trong lớp RandomStringUtils:

  • random(int count) : Tạo một chuỗi ngẫu nhiên có chiều dài là số ký tự được chỉ định, không giới hạn loại ký tự được trả về.
  • randomAscii(int count) : Tạo một chuỗi ngẫu nhiên có chiều dài là số ký tự được chỉ định, bao gồm các ký tự có giá trị ASCII từ 32 đến 126.
  • randomNumeric(int count) : Tạo một chuỗi số ngẫu nhiên có chiều dài là số ký tự được chỉ định, bao gồm các ký tự số 0-9.
  • randomAlphabetic(int count) : Tạo một chuỗi số ngẫu nhiên có chiều dài là số ký tự được chỉ định, bao gồm các ký tự chữ Latin (a-z, A-Z).
  • randomAlphanumeric(int count) : Tạo một chuỗi số ngẫu nhiên có chiều dài là số ký tự được chỉ định, bao gồm các ký tự chữ Latin (a-z, A-Z) và số 0-9.
  • random(int count, String input) : Tạo một chuỗi số ngẫu nhiên có chiều dài là số ký tự được chỉ định, chỉ bao gồm các ký tự được xác định trong input.

Ví dụ:

package com.gpcoder; import org.apache.commons.lang3.RandomStringUtils; public class RandomStringUtilsExample {     public static void main(String[] args) {         System.out.println(RandomStringUtils.random(4)); //          System.out.println(RandomStringUtils.random(6)); // 㚔쬩́㽩         System.out.println(RandomStringUtils.randomAscii(4)); // qe51         System.out.println(RandomStringUtils.randomAscii(6)); // MqQ^X         System.out.println(RandomStringUtils.randomNumeric(4)); // 9808         System.out.println(RandomStringUtils.randomNumeric(6)); // 338756         System.out.println(RandomStringUtils.randomAlphabetic(4)); // kvMu         System.out.println(RandomStringUtils.randomAlphabetic(6)); // PeykyQ         System.out.println(RandomStringUtils.randomAlphanumeric(4)); // MavC         System.out.println(RandomStringUtils.randomAlphanumeric(6)); // fR2BEf         String input = "abcd1234!@#$%^&*()-=_+;:<>,.?/";         System.out.println(RandomStringUtils.random(4, input)); // 1)+(         System.out.println(RandomStringUtils.random(6, input)); // -c=,a,     } }

Sử dụng java.util.UUID

UUID (Universally Unique Identifier) hay còn được biết đến như là GUID (Globally Unique Identifier), là một chuỗi đại diện cho một mã định danh duy nhất, không thể thay đổi (immutable), và có giá trị dài 128 bit.

UUID được sử dụng để tạo tên file ngẫu nhiên, id session trong ứng dụng web, id transaction, …

Phương thức java.util.UUID.randomUUID() được sử dụng để sinh ra một chuỗi ngẫu nhiên có độ dài 32 ký tự (128 bit) được biểu diễn ở hệ hệ thập lục phân (hex: 0-9A-F) và 4 ký tự phân tách ().

Tạo số và chuỗi ngẫu nhiên trong Java

Ví dụ:

UUID uuid = UUID.randomUUID(); System.out.println("UUID: " + uuid.toString()); System.out.println("variant: " + uuid.variant()); System.out.println("version: " + uuid.version());

Chạy chương trình, chúng ta có kết quả như sau:

UUID: ef41d4cb-5d1b-4a83-a4c1-f1397e3fcdb7 variant: 2 version: 4

Bài viết gốc được đăng tải tại gpcoder.com

Xem thêm các việc làm Java hấp dẫn tại TopDev