0

With the below code if we try to generate random numbers from 1 to 10, I some times get duplicate values.

Below code should generate 5 unique values for random numbers between 1 to 10.

When I print the array it happens uniqueness is not guaranteed. Output was 2,1,9,10,2.

2 was repeated in this case.

        Random random = new Random(System.currentTimeMillis());
        random.setSeed(System.currentTimeMillis());
        int[] myUniqueValues = new int[5];
        for (int i = 0; i < 5; i++) {
            myUniqueValues[i] = random.nextInt(10) + 1;
        }
        return myUniqueValues;
NNikN
  • 3,720
  • 6
  • 44
  • 86
  • 1
    afaik, java's random and several other random implementations have the tendency to generate the same set of number for a given seeds. checked the docs and it said, **"If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers. In order to guarantee this property, particular algorithms are specified for the class Random."** if you wanted for a non-deterministic output, you might want to try `SecureRandom`. – Bagus Tesa Apr 09 '22 at 06:14
  • I mean partially but I don't want to use set here, would leave that job for class Random to give me unique values. One thing I found, if we increase the range from 10 to 100, uniqueness increases. But yeah as mentioned earlier by @BagusTesa i think SecureRandom is a better option. With current code I m not sharing the seed. So I just the program once get duplicate values, run it next time get again duplicate values. – NNikN Apr 09 '22 at 06:19

2 Answers2

0

One way of doing this would be to create a list and pick randoms from it:

Random r = new Random();
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i=0: i<10; i++){
    list.add(i);
}

private int getUniqueRandom(){
    int index = r.nextInt(list.size());
    int number = list.get(index);
    list.remove(index); // Check that it removes the Index not the value from list
    return number;
}

Another way if you have a lot of numbers and dont want to store them in memory

Random r = new Random();
ArrayList<Integer> list = new ArrayList<Integer>();

for(int i=0; i<5; i++){
    do{
        int number = r.nextInt(10);
    }while(!list.contains(number))
    list.add(number);
}

The way with Set as suggested by steven7mwesigwa
This works because Sets can only contain unique values

Random r = new Random();
        HashSet<Integer> list = new HashSet<Integer>();
        while (list.size() < 5) {
            list.add(r.nextInt(10));
        }

A one liner from https://stackoverflow.com/a/31656679/11355399

int[] array = ThreadLocalRandom.current().ints(0, 10).distinct().limit(5).toArray();
Huhngut
  • 402
  • 6
  • 13
0

We can use Set Collection here to remove duplicates inside loop itself. Set has method called contains which will check weather output of random function is already present in our result set or not. if it is present we can skip that iteration. if not we can random to our result set. please check below snippet.

Random random = new Random(System.currentTimeMillis());
    random.setSeed(System.currentTimeMillis());
    Set<Integer> myUniqueValues2 = new HashSet<>();
    int k=0;
    while(k<5) {
        int test = random.nextInt(10) + 1;
        if(!myUniqueValues2.contains(test)) {
            myUniqueValues2.add(test);  
            k++;
        }       
    }
    
    for(int i: myUniqueValues2)
        System.out.println(i+" ");
    
  • 1
    Why not simply `while(myUniqueValues.size() < 5)`? You don't need the extra variable `k` and you certainly don't need to call `contains` in every iteration because a `Set` won't have duplicates anyway. – QBrute Apr 09 '22 at 08:25