1

This is probably already asked, but it is a little difficult for me to understand. I created a for loop to add random integers into my array, but when the integer is already in the array, restart the loop. But I keep on getting the same integers into the array + when there already is a duplicate, the array size increases. Does anyone know what I'm doing wrong?

        Random r = new Random();
        int[] tes = new int[5];
        for (int i = 0; i < tes.length; i++) {
            int q = r.nextInt(10);
            for (int j = 0; j < i; j++) {
                if (q == tes[j]){
                    i=i-1;
                }
            }
            tes[i] = q;
            System.out.println(tes[i]);
        }

and the output:

enter image description here

dreamcrash
  • 47,137
  • 25
  • 94
  • 117
Liza Darwesh
  • 401
  • 1
  • 3
  • 20

5 Answers5

4

If you want a collection without duplicates you should use a Set:

    Random r = new Random();
    int desirableSize = 5;
    Set<Integer> uniques = new HashSet<>(desirableSize);
    while(uniques.size() < desirableSize){
        uniques.add(r.nextInt(10));
    }
    System.out.println(uniques);

The add method already ensures that a value is not added if it already exist on the set.

boolean add(E e)

Adds the specified element to this set if it is not already present (optional operation).

I have used HashSet, however if the insertion order is important for you, use instead LinkedHashSet:


As pjs have pointed out the aforementioned approach is good when:

desirableSize is much less than the pool size, but if the desirableSize is a substantial proportion of pool size you're better off shuffling the pool and selecting the first desirableSize elements.

Something as follows:

int start  = 0;
int end = 10;
int size = 5;
List<Integer> collect = IntStream.rangeClosed(start, end)
        .boxed()
        .limit(size)
        .collect(Collectors.toList());
Collections.shuffle(collect);
System.out.println(collect);

The rational is the following (quoting pjs):

With rejection-based schemes such as repeated attempts to add to a set, the expected number of iterations is O(poolsize * log(desirableSize)) with O(desirableSize) storage for the set. Shuffling is O(poolsize) but requires O(poolsize) storage for the shuffle. As desirableSize -> poolsize, shuffling wins on expected iterations and becomes competitive on storage. With partial shuffling implementations, the number of iterations for shuffling is O(desirableSize) although the storage remains the same.

Or more informally, the higher it is the unique finite set of numbers that will be pickup from a finite set of possible numbers, the more desirable it is to use the second approach.

For instance, if one generates numbers from 0 to 1000 and is only interested in 5 numbers, since the probability of picking randomly the same numbers is lower, one is better off with the first approach. However, if you would be (instead) interested in 800 numbers, then one would be better off generating and shuffling the 1000 numbers, and extracting the 800 unique values from them.

Memory-wise the first approach is better then second approach, however performance-wise it depends in the context as we have already described.

dreamcrash
  • 47,137
  • 25
  • 94
  • 117
1

i dont see a problem. Your System.out.println(tes[i]); is in loop

your array has only following ints: 5,9,2,7,1

make println in own loop

for (int i = 0; i < tes.length; i++) {
    System.out.println(tes[i]);
}

because you make i=i-1; one value is printed many times

anatoli
  • 1,663
  • 1
  • 17
  • 43
1

I managed to solve it in a different way:

List<Integer> tes = new ArrayList<>(5);

        Random r = new Random();

        for (int i = 0; i < 5; i++) {

            int testNummer = r.nextInt(10);
            if(!tes.contains(testNummer)) {
                tes.add(testNummer);
                System.out.println(testNummer);
            }else{
                i=i-1;
            }
        }

this way is more efficient, I have noticed.

Liza Darwesh
  • 401
  • 1
  • 3
  • 20
0

If you want an easy way to generate unique values you can do it with a stream.

Random r = new Random();
int minVal = 1;
int upperBound = 20;
int count = 10;

As long as count is less than upperBound - minVal it will finish without duplicates. For very large counts with the appropriate range, it may take some time.

int[] unique = r.ints(minVal, upperBound).distinct().limit(count).toArray();
System.out.println(Arrays.toString(unique));

Prints something like this.

[14, 1, 7, 13, 5, 16, 2, 8, 12, 4]

An easy way to generate random numbers of a fixed range is to simply shuffle the array.

Integer[] vals = new Integer[20];
for (int i = 0; i < vals.length; i++) {
    vals[i] = i+1;
}
// Object array will be shuffle since it backs up the list.
Collections.shuffle(Arrays.asList(vals));
System.out.println(Arrays.toString(vals));

Prints something like

[7, 20, 5, 10, 17, 18, 3, 13, 11, 1, 2, 8, 4, 9, 19, 12, 15, 16, 6, 14]


WJS
  • 36,363
  • 4
  • 24
  • 39
0

Some logic problem

  1. Increment i variable when you store value in array and don't decrement i variable just break inner loop when found duplicate.

  2. when duplicate found then restart outer loop. use if else condition for that try below code and for simple understanding i have changed outer loop in while

     int i = 0;
     while(i<5)
    
     {
         int q = r.nextInt(10);
         System.out.println("random value generated"+ q );
         int j=0;
         for (;j < i; j++)
         {
             if (q == tes[j])
             {
    
                 System.out.println("duplicate value found"+ q );
                 break;
             }
         }
         if(j!=i)
         {
             continue;
         }
         else 
         {
             if(j==i)
             {
                 tes[i] = q;
                 i=i+1;
             }
         }
         System.out.println("value at "+ tes[i]);
    
     }