Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating Unique Random Numbers in Java

Tags:

java

random

I'm trying to get random numbers between 0 and 100. But I want them to be unique, not repeated in a sequence. For example if I got 5 numbers, they should be 82,12,53,64,32 and not 82,12,53,12,32 I used this, but it generates same numbers in a sequence.

Random rand = new Random(); selected = rand.nextInt(100); 
like image 668
Ömer Faruk AK Avatar asked Nov 13 '11 23:11

Ömer Faruk AK


People also ask

How do you generate 5 unique random numbers in Java?

add(6); sampleList. add(7); sampleList. add(8); Now from the sampleList we will produce five random numbers that are unique.


Video Answer


2 Answers

  • Add each number in the range sequentially in a list structure.
  • Shuffle it.
  • Take the first 'n'.

Here is a simple implementation. This will print 3 unique random numbers from the range 1-10.

import java.util.ArrayList; import java.util.Collections;  public class UniqueRandomNumbers {          public static void main(String[] args) {         ArrayList<Integer> list = new ArrayList<Integer>();         for (int i=1; i<11; i++) {             list.add(i);         }         Collections.shuffle(list);         for (int i=0; i<3; i++) {             System.out.println(list.get(i));         }     } } 

The first part of the fix with the original approach, as Mark Byers pointed out in an answer now deleted, is to use only a single Random instance.

That is what is causing the numbers to be identical. A Random instance is seeded by the current time in milliseconds. For a particular seed value, the 'random' instance will return the exact same sequence of pseudo random numbers.

like image 114
Andrew Thompson Avatar answered Nov 02 '22 19:11

Andrew Thompson


With Java 8+ you can use the ints method of Random to get an IntStream of random values then distinct and limit to reduce the stream to a number of unique random values.

ThreadLocalRandom.current().ints(0, 100).distinct().limit(5).forEach(System.out::println); 

Random also has methods which create LongStreams and DoubleStreams if you need those instead.

If you want all (or a large amount) of the numbers in a range in a random order it might be more efficient to add all of the numbers to a list, shuffle it, and take the first n because the above example is currently implemented by generating random numbers in the range requested and passing them through a set (similarly to Rob Kielty's answer), which may require generating many more than the amount passed to limit because the probability of a generating a new unique number decreases with each one found. Here's an example of the other way:

List<Integer> range = IntStream.range(0, 100).boxed()         .collect(Collectors.toCollection(ArrayList::new)); Collections.shuffle(range); range.subList(0, 99).forEach(System.out::println); 
like image 38
Alex - GlassEditor.com Avatar answered Nov 02 '22 18:11

Alex - GlassEditor.com