Reputation: 3
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
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:
0
to N
.k
between 0
and N
N
by 1
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
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
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