Я хотел бы случайное число, но без повторения я кодирования выше это правильно? - PullRequest
0 голосов
/ 15 апреля 2020

Что я пытаюсь сделать, это сгенерировать случайное число, но без повторения, которое я кодирую выше, это правильно?

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;
}  

Ответы [ 3 ]

1 голос
/ 15 апреля 2020

Ваша логика c излишне сложна. Более простой способ заключается в следующем:

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);
    }
}

Пример прогона:

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

Обратите внимание, что Set сохраняет только уникальные значения. Таким образом, любое дублированное случайное число, добавленное к нему, будет автоматически отброшено.


В качестве альтернативы,

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);
    }
}

Пример выполнения:

[54, 62, 14, 5, 30, 76, 7, 9, 63, 61]
0 голосов
/ 19 апреля 2020

Я рекомендую сделать это так. Если размер и диапазон значительно отличаются, тогда можно использовать sets или streams с distinct. Но если размер и диапазон близки, выполнение этих методов может занять относительно много времени.

Недостатком этого алгоритма является то, что он сначала инициализирует внутренний массив. Я считаю, что это незначительно в большинстве случаев, и увеличение скорости для больших значений как размера, так и диапазона очень значительно.

Это работает следующим образом:

  • предполагает массив целых чисел от 0 до N.
  • генерирует случайное значение int k между 0 и N
  • , присваивает это значение массиву возврата.
  • замените k-е значение на N-е значение
  • , затем уменьшите N на 1
  • и повторяйте до N == 0

С k был фактически удален из списка доступных значений и заменен на неназначенное значение Nth, это значение больше никогда не будет выбрано.

     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;
       }

Чтобы проверить это, я рекомендую следующее. Набор заполнен только для того, чтобы показать, что нет дубликатов. По иронии судьбы, заполнение набора для подтверждения точки занимает больше времени, чем фактическое создание значений.

        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);

Печать

Done! Filling set.
10,000,000
10,000,000
0 голосов
/ 15 апреля 2020

Используя Stream API в Java 8+, вы можете сгенерировать n различных целых чисел с диапазоном от origin (включительно) до bound (эксклюзивно), используя этот метод:

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);
}

Пример:

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