วิธีสร้างเลขสุ่มใน Java
⚡ สรุปอย่างชาญฉลาด
ตัวเลขสุ่มใน Java มาจากตัวเลือกไลบรารีมาตรฐานที่เกี่ยวข้องสี่แบบ ได้แก่ คลาส Random, Math.random, ThreadLocalRandom และ SecureRandom ซึ่งแต่ละแบบครอบคลุมส่วนผสมที่แตกต่างกันของความเร็ว ความปลอดภัยในการทำงานแบบมัลติเธรด และความแข็งแกร่งทางด้านการเข้ารหัสลับสำหรับการใช้งานจริง

ตัวเลขสุ่มปรากฏอยู่ทุกหนทุกแห่ง Javaตั้งแต่ข้อมูลสำหรับการทดสอบหน่วยและเกมทอยลูกเต๋า ไปจนถึงโทเค็นเซสชันและสำรับไพ่ที่สับแล้ว บทช่วยสอนนี้จะอธิบายวิธีการสร้างตัวเลขสุ่มใน Java การใช้งานทุกตัวเลือกในไลบรารีมาตรฐาน และวิธีการเลือกตัวเลือกที่เหมาะสมสำหรับงานนั้นๆ
สร้างตัวเลขสุ่มใน Java
การขอ Java ไลบรารีมาตรฐานมีวิธีการสร้างเลขสุ่มอยู่ 4 วิธีที่ใช้กันทั่วไป:
java.util.Randomเป็นคลาสอเนกประสงค์ สามารถสร้างค่าบูลีน, จำนวนเต็ม, จำนวนเต็มยาว, จำนวนทศนิยม และจำนวนทศนิยมสองเท่า ผ่านเมธอดต่างๆ เช่นnextInt,nextLongและnextDouble.Math.randomเป็นฟังก์ชันช่วยแบบคงที่ที่ส่งค่ากลับเป็นเลขทศนิยมระหว่าง 0.0 (รวม) และ 1.0 (ไม่รวม) โดยใช้ตัวแปรที่ใช้ร่วมกันRandomภายในThreadLocalRandominjava.util.concurrentแต่ละเธรดจะมีตัวสร้างของตัวเอง ทำให้หลายเธรดไม่แย่งกันใช้ตัวสร้างเดียวSecureRandominjava.securityสร้างเลขสุ่มเทียมที่มีความแข็งแกร่งทางด้านการเข้ารหัสสำหรับรหัสผ่าน ตัวระบุเซสชัน และคีย์
ส่วนด้านล่างนี้แสดงวิธีการสร้างตัวเลขสุ่มสิบตัวด้วยแต่ละวิธี
ตัวอย่าง: สร้างตัวเลขสุ่มโดยใช้ Java คลาสสุ่ม
ตัวอย่างแรกใช้ java.util.Random เพื่อสร้างจำนวนเต็มสิบจำนวนในช่วง 0 ถึง 99 รวมทั้งสองจำนวน:
import java.util.Random; public class RandomNumbers { public static void main(String[] args) { Random objGenerator = new Random(); for (int iCount = 0; iCount < 10; iCount++) { int randomNumber = objGenerator.nextInt(100); System.out.println("Random No : " + randomNumber); } } }
Output:
Random No : 17 Random No : 57 Random No : 73 Random No : 48 Random No : 68 Random No : 86 Random No : 34 Random No : 97 Random No : 73 Random No : 18
ตัวอย่างของ Random ถูกสร้างขึ้นเป็น objGeneratorส่วน nextInt(int bound) เมธอดนี้จะส่งคืนค่าระหว่าง 0 (รวม 0 ด้วย) และขอบเขตที่กำหนด (ไม่รวม 0 ด้วย) ดังนั้น nextInt(100) ให้ค่าตั้งแต่ 0 ถึง 99 หากต้องการให้ลำดับนั้นสามารถสร้างซ้ำได้ ให้ส่งค่าเริ่มต้น (seed) ไปยังตัวสร้าง เช่น new Random(42)เมล็ดพันธุ์เดียวกันจะให้ลำดับเดียวกันเสมอ ซึ่งมีประโยชน์ในการทดสอบและการจำลอง
ตัวอย่าง: การใช้ Java คณิตศาสตร์สุ่ม
เพื่อสร้างค่าสุ่มสิบค่าในช่วง 0.0 ถึง 1.0 ให้เรียกใช้ฟังก์ชันคงที่ Math.random วิธีการภายใน ห่วงนี่เป็นวิธีที่เร็วที่สุดในการสร้างตัวเลขทศนิยมแบบสุ่มโดยไม่ต้องสร้างอ็อบเจ็กต์ตัวสร้าง:
public class DemoRandom { public static void main(String[] args) { for (int xCount = 0; xCount < 10; xCount++) { System.out.println(Math.random()); } } }
Output:
0.46518450373334297 0.14859851177803485 0.5628391820492477 0.6323378498048606 0.1740198445692248 0.9140544122258946 0.9167350036262347 0.49251219841030147 0.7426056725722353 0.2039418871298877
ภายใต้ประทุน Math.random สร้างค่าคงที่เดียว Random ในการใช้งานครั้งแรกและการโทร nextDouble บนนั้น ตัวสร้างข้อมูลร่วมตัวเดียวนั้นเหมาะสมสำหรับการสาธิต แต่จะกลายเป็นคอขวดภายใต้ภาระการทำงานแบบมัลติเธรดหนักๆ ซึ่งส่วนถัดไปจะกล่าวถึง
สร้างเลขสุ่มในช่วงที่กำหนดเอง
โปรแกรมที่ใช้งานจริงมักต้องการค่าสุ่มภายในช่วงที่กำหนด เช่น จำนวนเต็มระหว่าง 1 ถึง 6 สำหรับการทอยลูกเต๋า หรือจำนวนทศนิยมระหว่าง 10.0 ถึง 20.0 สำหรับการจำลอง โดยมีรูปแบบสองแบบที่ครอบคลุมเกือบทุกกรณี
จำนวนเต็มสุ่มระหว่างค่าต่ำสุดและค่าสูงสุด (รวมทั้งค่าต่ำสุดและค่าสูงสุด):
import java.util.Random; public class RangeDemo { public static void main(String[] args) { Random rnd = new Random(); int min = 1; int max = 6; // nextInt(max - min + 1) returns 0..(max-min), then shift by min int dice = rnd.nextInt(max - min + 1) + min; System.out.println("Dice roll : " + dice); } }
สุ่มสองเท่าระหว่างค่าต่ำสุดและค่าสูงสุด:
double min = 10.0; double max = 20.0; double value = min + (max - min) * Math.random(); System.out.println("Value : " + value);
ทั้งสองรูปแบบทำงานโดยการดึงค่าจากช่วงค่าดั้งเดิมของตัวสร้าง ปรับขนาดให้เข้ากับความกว้างของช่วงค่าเป้าหมาย และเลื่อนขึ้นไปตามค่าต่ำสุด หากคุณกำลังใช้งานอยู่ Java สำหรับเวอร์ชัน 8 หรือใหม่กว่า จะให้ผลลัพธ์เดียวกันผ่านเวอร์ชันใหม่กว่า ints, longsและ doubles วิธีการสตรีมบน Random, ตัวอย่างเช่น rnd.ints(10, 1, 7).forEach(System.out::println) สำหรับการทอยลูกเต๋า 10 ครั้ง
ThreadLocalRandom สำหรับมัลติเธรด Code
การแบ่งปันเพียงครั้งเดียว Random ปลอดภัยต่อการใช้งานแบบมัลติเธรด แต่จะทำงานช้าลงเมื่อเกิดการแย่งชิงทรัพยากร เนื่องจากทุกเธรดต้องซิงโครไนซ์กับ seed ภายในเดียวกัน ThreadLocalRandomเพิ่มใน Java 7 และอาศัยอยู่ใน java.util.concurrentโดยแต่ละเธรดจะมีตัวสร้างของตัวเอง จึงไม่มีปัญหาการแย่งชิงล็อกเกิดขึ้น
import java.util.concurrent.ThreadLocalRandom; public class ThreadLocalDemo { public static void main(String[] args) { // random int in [1, 100] int i = ThreadLocalRandom.current().nextInt(1, 101); // random long in [1000, 5000] long l = ThreadLocalRandom.current().nextLong(1000L, 5001L); // random double in [0.0, 1.0) double d = ThreadLocalRandom.current().nextDouble(); System.out.println(i + " " + l + " " + d); } }
ใช้ ThreadLocalRandom.current() ภายในเธรดการทำงาน สตรีมแบบขนาน และงานพร้อมกันใดๆ โปรดทราบว่า setSeed พ่น UnsupportedOperationExceptionดังนั้นจึงไม่รองรับการใช้ seed เพื่อการทำซ้ำ หากคุณต้องการ seed ที่คงที่ ให้ใช้ seed แบบธรรมดา Random.
SecureRandom สำหรับการสุ่มแบบคำนึงถึงความปลอดภัย Numbers
อินสแตนซ์ของ Random และ ThreadLocalRandom ไม่มีความปลอดภัยทางด้านการเข้ารหัส หากมีตัวอย่างผลลัพธ์เพียงไม่กี่ตัวอย่าง ผู้โจมตีก็สามารถสร้างสถานะภายในขึ้นใหม่และคาดเดาค่าในอนาคตได้ สำหรับรหัสผ่าน โทเค็นเซสชัน ค่าเกลือ และคีย์การเข้ารหัส ให้ใช้ java.security.SecureRandom แต่ในทางกลับกัน มันดึงข้อมูลเริ่มต้นจากแหล่งเอนโทรปีของระบบปฏิบัติการ และสร้างค่าที่ไม่สามารถคาดเดาได้
import java.security.SecureRandom; public class SecureDemo { public static void main(String[] args) { SecureRandom secure = new SecureRandom(); byte[] token = new byte[16]; secure.nextBytes(token); // 128-bit random token int otp = secure.nextInt(1_000_000); // 6-digit one-time code System.out.println("OTP : " + String.format("%06d", otp)); } }
SecureRandom ช้ากว่า Random เนื่องจากใช้อัลกอริทึมที่ทรงพลังกว่าและข้อมูลเริ่มต้นที่ละเอียดกว่า ควรสงวนไว้สำหรับงานด้านความปลอดภัย และใช้ตัวสร้างข้อมูลที่เร็วกว่าสำหรับเกม การจำลอง และข้อมูลทดสอบ
