0

I am going to implement the unique random number generator. But when running this, it sometimes generates same number as previous . How to ensure that the numbers generated are not repeated in this case ?

The below is my code

    int refno = 0;

    SecureRandom r = new SecureRandom();
    refno = r.nextInt(999999999);
Jeff Bootsholz
  • 2,971
  • 15
  • 70
  • 141

3 Answers3

8

Random and also SecureRandom return a random number. Random numbers are never unique (else they would not be random).

To create a unique identifier use the class java.util.UUID.

Uwe Plonus
  • 9,803
  • 4
  • 41
  • 48
2

A random number generator creates numbers in a finite range, so it has to repeat itself sooner or later.

When the range of numbers you generate is small (like when you want to simulate a deck of cards), you can create a list with all possible values, shuffle it randomly and return the elements in the now randomized order.

 class UniqueRandom {
      private LinkedList<Integer> results;

      public UniqueRandom(int range) {
           results = new LinkedList<Integer>(range);
           for (var i = 0; i < range; i++) {
                results.add(i);
           }

           Collection.shuffle(results, new SecureRandom());
      }

      public int nextInt() throws NoSuchElementException {
           return results.pop(); // will throw NoSuchElementException when all values are used up
      }
 }

When this is unfeasible because the range is too large, you could store the numbers which have already been generated in a Set. Before you return a result, check if it is already in that set, and when it is, reroll.

 class UniqueRandom {
      private Set<Integer> used = new HashSet<Integer>();
      private Random rand = new SecureRandom();

      public int nextInt(int max) {
          Integer ret = null;
          do {             
             ret = rand.nextInt(max);
          } while (used.add(ret) == false); 
          return ret;
      }
 }

Warning: The latter algorithm will become slower and slower the more numbers you generate and will finally enter an infinite loop when all values are used up, so only use it when you can be sure that the range of results will never be exhausted. Alternatively, you could check the size of used and throw an exception when it gets too large.

Philipp
  • 67,764
  • 9
  • 118
  • 153
1

You can use UUID.

UUID.randomUUID();

Since UUID is 128 bit number, you will have to convert it to BigInteger.

darijan
  • 9,725
  • 25
  • 38
  • I believe UUIDs are hexidecimal (eg I just generated one and it was 02c9c6b0-2f9b-4ae5-a6e5-c2a2a59b4382), is this going to cause difficulties storing it in a BigInteger? – Richard Tingle Jun 24 '13 at 08:37
  • Also; why convert it at all? – Richard Tingle Jun 24 '13 at 08:39
  • Well, if he MUST have an integer representation. And it wouldn't be hard. Take a look at the UUID API. It has `long getMostSigBits()` and `long getLeastSigBits()` methods. – darijan Jun 24 '13 at 08:41