Create a unique random number for each array value

I have this method that generates a number (1-10) for each array value specified in this method. I want the whole set of numbers to appear as a set of unique numbers. How to do it?

public static int generateNumbers(int[] lotteryNumbers) { Random randNum = new Random(); lotteryNumbers[0] = randNum.nextInt(10); lotteryNumbers[1] = randNum.nextInt(10); lotteryNumbers[2] = randNum.nextInt(10); lotteryNumbers[3] = randNum.nextInt(10); lotteryNumbers[4] = randNum.nextInt(10); return lotteryNumbers[4]; } 
+5
source share
4 answers

A simple solution is to generate a list of ten digits, shuffle this list and get the first five elements:

 List<Integer> list = new ArrayList<>(10); for (int i = 0; i < 10; i++) { list.add(i); } Collections.shuffle(list); Integer[] lotteryNumbers = list.subList(0, 5).toArray(new Integer[10]); 

Collections.shuffle(list) is a utility method that arbitrarily rearranges a given list.

If you are using Java 8, this can be written as:

 List<Integer> list = IntStream.range(0, 10).boxed().collect(Collectors.toList()); Collections.shuffle(list); int[] loterryNumbers = list.subList(0, 5).stream().mapToInt(i -> i).toArray(); 
+5
source

The naive method is to randomly select in the set that you want to "shuffle":

 public static int[] generateNumbers(int exclusiveMaxValue) { List<Integer> values = new ArrayList<>(exclusiveMaxValue); for (int i=0 ; i<values.size() ; i++) values.add(i); int[] result = new int[exclusiveMaxValue]; Random rd = new Random(); for (int i=0 ; i<result.length ; i++) { result[i] = values.remove(rd.nextInt(values.size())); } return result; } 

However, List.remove usually O(n) , so the whole method is quadratic, which is very expensive. You can do the shuffling in O(n) by simply replacing the elements in place (this is what Collections.shuffle does):

 public static int[] generateNumbers(int exclusiveMaxValue) { int[] result = new int[exclusiveMaxValue]; for (int i=0 ; i<result.length ; i++) result[i] = i; Random rd = new Random(); for (int i=result.length - 1 ; i>=0 ; i--) { swap(result, i, rd.nextInt(i + 1)); } return result; } private static swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } 
+3
source

This method generates a sequence of length N unique numbers in the range [0, N -1].

 public static int[] generateNumbers(int length) { final int[] array = new int[length]; for (int i = 0; i < length; ++i) { array[i] = i; } shuffle(array); return array; } 

For shuffling, the Fisher-Yate algorithm was used:

 public static void shuffle(final int[] array) { final Random random = new Random(); for (int i = array.length - 1; i > 0; --i) { final int randomIdx = random.nextInt(i + 1); final int temp = array[i]; array[i] = array[randomIdx]; array[randomIdx] = temp; } } 
  • Thanks ( Ronald Fisher and Frank Yates ), O (n) time algorithm complexity
  • This implementation works with arrays (with primitives), and not with collections (with instances of the Integer class, which wraps the value of the primitive type int in the object) - it matters if the size of the array is large enough
+1
source

Here is an alternative method that uses a set and fills it until it reaches the required size. It generates numbersToDraw various random numbers ranging from min to max (inclusive). It also preserves the order in which the numbers were drawn (this uses the LinkedHashSet).

 private static Set<Integer> drawNumbers(int min, int max, int numbersToDraw) { if (max < min) { throw new IllegalArgumentException("Minimum must be less than maximum."); } if (max < 0 || min < 0) { throw new IllegalArgumentException("Both range numbers must be positive."); } final int countOfNumbers = max - min + 1; if (countOfNumbers < numbersToDraw) { throw new IllegalArgumentException("Range is not big enough."); } final Random randomizer = new SecureRandom(); final Set<Integer> numbersDrawn = new LinkedHashSet<>(); while (numbersDrawn.size() < numbersToDraw) { final int randomNumber = min + randomizer.nextInt(countOfNumbers); numbersDrawn.add(randomNumber); } return numbersDrawn; } 

If you do not want the numbers to be unique, you can use this in Java 8:

 final Random randomizer = new SecureRandom(); final List<Integer> numbersDrawn = IntStream .range(0, numbersToDraw) .mapToObj(i -> min + randomizer.nextInt(max - min + 1)) .collect(Collectors.toList()); 

If you do not want the numbers to be unique, BUT you want to print your individual values ​​(is this your original question?):

 final Random randomizer = new SecureRandom(); final Set<Integer> numbersDrawn = IntStream .range(0, numbersToDraw) .mapToObj(i -> min + randomizer.nextInt(max - min + 1)) .collect(Collectors.toSet()); 

And one more option for your specific case:

 final Set<Integer> distinctNumbers = Arrays .stream(lotteryNumbers) .distinct() // you can leave this as the set is distinct automatically .boxed() .collect(Collectors.toSet()); 
0
source

All Articles