Bill Sara
Bill Sara

Reputation: 3

i would like to random number but no repetition im coding above is it correct?

What I am trying to do is generate random number but no repetition i'm coding above is it correct?

public static void main(String[] args) {
    ArrayList<Integer> arrayLast = new ArrayList<Integer>();
    for (int arrayitems : getArray(10, 100)) {
        arrayLast.add(arrayitems);
    }
}

public static ArrayList<Integer> getArray(int arraysize, int range){
    ArrayList<Integer> array = new ArrayList<Integer>();
    ArrayList<Integer> arraybase = new ArrayList<Integer>();
    Random rnd = new Random();
    for (int i = 1; i <= range; i++) {
        arraybase.add(new Integer(i));
    }

    int k =0;       
    for (int j = 0; j < arraysize; j++) {
        if(range>arraysize) {
            int sayi = rnd.nextInt(range-arraysize);
            array.add(arraybase.get(sayi));
            arraybase.remove(sayi);
        }
        else {  
            int sayi = rnd.nextInt(arraysize-k);
            array.add(arraybase.get(sayi));
            arraybase.remove(sayi);
            k++;
        }
    }
    Collections.shuffle(array);         
    return array;
}  

Upvotes: 0

Views: 94

Answers (3)

WJS
WJS

Reputation: 40062

I recommend doing it this way. If the size and range are significantly different then using sets or streams with distinct is fine. But if the size and range are close those methods can take a relatively long time to complete.

The downside to this algorithm is that it initializes an internal array first. I find this is insignificant in most cases and the increase in speed for large values of both size and range is very significant.

It works as follows:

  • assume an array of ints from 0 to N.
  • generate a random int k between 0 and N
  • assign that value to the return array.
  • replace the k'th value with the Nth value
  • then decrease N by 1
  • and repeat until N == 0

Since k has been effectively removed from the list of available values and replaced with the unassigned Nth value, that value will never be selected again.

     public static   int [] getRandom(int size, int range) {
         Random r = new Random();
         int[] ret = new int[size];
         // initialize number pool
         int[] nums = IntStream.range(0,range).toArray();

         for (int i = 0; i < size; i++) {
            int k = r.nextInt(range);
            ret[i] = nums[k];
            range--;
            nums[k] = nums[range];
         }
         return ret;
       }

To test this, I recommend the following. The set is filled just to show there are no duplicates. Ironically, filling the set to prove a point takes more time than the actual generation of values.

        int[] v = getRandom(10_000_000, 10_000_000);
        System.out.println("Done! Filling set");
        Set<Integer> set = Arrays.stream(v)
                 .boxed()
                 .collect(Collectors.toCollection(LinkedHashSet::new));
        System.out.printf("%,d%n",set.size());
        System.out.printf("%,d%n",v.length);

Prints

Done! Filling set.
10,000,000
10,000,000

Upvotes: 0

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79435

Your logic is unnecessarily complex. A simpler way is as follows:

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<Integer>();
        final int SIZE = 10;
        final int RANGE = 100;
        Random random = new Random();
        while (set.size() != SIZE) {
            set.add(random.nextInt(RANGE));
        }
        System.out.println(set);
    }
}

A sample run:

[83, 67, 86, 39, 56, 26, 92, 60, 13, 94]

Note that a Set keep only unique values. So, any duplicate random number added to it will be automatically discarded.


Alternatively,

import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        final int SIZE = 10;
        final int RANGE = 100;
        Random random = new Random();
        List<Integer> list = IntStream.generate(() -> random.nextInt(RANGE)).distinct().limit(SIZE).boxed()
                .collect(Collectors.toList());
        System.out.println(list);
    }
}

A sample run:

[54, 62, 14, 5, 30, 76, 7, 9, 63, 61]

Upvotes: 1

Miss Chanandler Bong
Miss Chanandler Bong

Reputation: 4258

Using Stream API in Java 8+, you can generate n distinct integers with a range from origin (inclusive) to bound (exclusive) by using this method:

public static List<Integer> randomInts(int n, int origin, int bound) {
    return ThreadLocalRandom.current().ints(origin, bound)
            .distinct()
            .limit(n)
            .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}

Example:

// generate 15 distinct random numbers greater than or equal to 10 and less than 90
List<Integer> randoms = randomInts(15, 10, 90);

Upvotes: 0

Related Questions