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

1. 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[/code] đã đượ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.

1.1. 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.

1.2. 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:

// 1st
 
Random Integer: -2066769060
Random Long: -8130094582138669218
Random Float: 0.7775575
Random Double: 0.893498676660781
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 : ��&amp;��`d'

1.3. 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.

2. 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.

2.1. 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.maixuanviet.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&#91;&#93;){
        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));
    }
}
&#91;/code&#93;
<!-- /wp:shortcode -->

<!-- wp:paragraph -->
<p>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:</p>
<!-- /wp:paragraph -->

<!-- wp:shortcode -->

randomString1: 65cihDTo
randomString1: GbEMJBVH
randomString1: WJF7hZ3c
randomPassword1: #f|XD/W3
randomPassword2: |M$=}=2A

2.2. 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.maixuanviet;
  
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,
    }
}

2.3. 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 ().

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

Related posts:

Java Program to Perform Partial Key Search in a K-D Tree
Java Program to Find ith Largest Number from a Given List Using Order-Statistic Algorithm
What is Thread-Safety and How to Achieve it?
Java Program to Implement Multi-Threaded Version of Binary Search Tree
A Quick Guide to Using Keycloak with Spring Boot
Java Program to Perform Cryptography Using Transposition Technique
A Guide to Spring Cloud Netflix – Hystrix
Copy a List to Another List in Java
Introduction to Spring Data REST
Hashing a Password in Java
Java Program to Find Strongly Connected Components in Graphs
Entity To DTO Conversion for a Spring REST API
Biểu thức Lambda trong Java 8 – Lambda Expressions
Java Program to Find Shortest Path Between All Vertices Using Floyd-Warshall’s Algorithm
Java Program to Implement Hopcroft Algorithm
Spring Boot: Customize the Jackson ObjectMapper
Java Program to Implement Hash Tables chaining with Singly Linked Lists
Java Program to Implement Sorting of Less than 100 Numbers in O(n) Complexity
Retrieve User Information in Spring Security
Java Program to Implement Ternary Search Tree
Java Program to Implement Bellman-Ford Algorithm
Java Program to Find Median of Elements where Elements are Stored in 2 Different Arrays
Apache Camel with Spring Boot
Spring 5 WebClient
Java Program to Construct an Expression Tree for an Infix Expression
Spring Boot - Sending Email
Spring REST API with Protocol Buffers
Spring Boot - Batch Service
Quick Guide on Loading Initial Data with Spring Boot
Java Program to Implement Booth Algorithm
Giới thiệu Swagger – Công cụ document cho RESTfull APIs
A Guide To UDP In Java