В этом ответе предлагаются некоторые стратегии получения того, что вы хотите, и обеспечения их в случайном порядке с использованием некоторых уже известных алгоритмов.
Существует версия алгоритма случайного перемешивания Фишера-Йейтса, называемая версией Дюрстенфельда, которая случайным образом распределяет последовательно полученные элементы в массивы и коллекции при загрузке массива или коллекции.
Одна вещь, которую нужно помнить, это то, что случайное использование Fisher-Yates (AKA Knuth) или версия Durstenfeld, используемая во время загрузки, очень эффективно для массивов объектов, поскольку перемещается только ссылочный указатель на объект, а сам объект не ' Это должно быть изучено или сравнено с любым другим объектом как часть алгоритма.
Я приведу оба алгоритма ниже.
Если вам нужны действительно огромные случайные числа, порядка 1024 байта или более, то вам подойдет действительно хороший генератор случайных чисел, который может генерировать беззнаковые байты или слова за раз. Произвольно сгенерируйте столько байтов или слов, сколько вам нужно, чтобы составить число, превратить его в объект со ссылочным указателем на него, и, привет, заранее, у вас действительно огромное случайное целое число. Если вам нужен конкретный действительно большой диапазон, вы можете добавить базовое значение нулевых байтов к младшему концу последовательности байтов, чтобы сместить значение вверх. Это может быть вашим лучшим вариантом.
Если вам нужно исключить дубликаты действительно огромных случайных чисел, то это сложнее. Даже при наличии действительно огромных случайных чисел удаление дубликатов также делает их существенно предвзятыми и вовсе не случайными. Если у вас есть действительно большой набор недублированных действительно огромных случайных чисел, и вы случайным образом выбираете из еще не выбранных, то смещение - это только смещение в создании огромных значений для действительно огромного набора чисел, из которого можно выбирать. Обратную версию Дюрстенфельдской версии Yates-Fisher можно использовать для случайного выбора значений из действительно огромного их набора, удаления их из оставшихся значений, из которых можно выбирать, и вставки их в новый массив, который является подмножеством и может выполнять это только с исходным и целевым массивами на месте. Это было бы очень эффективно.
Это может быть хорошей стратегией для получения небольшого числа случайных чисел с огромными значениями из действительно большого их набора, в котором они не дублируются. Просто выберите случайное место в исходном наборе, получите его значение, поменяйте его местами с верхним элементом в исходном наборе, уменьшите размер исходного набора на единицу и повторите с исходным набором уменьшенного размера, пока вы не выберете достаточно значений. Это, в сущности, Дюрстенфельдская версия Фишера-Йейтса в обратном порядке. Затем можно использовать версию алгоритма Фишера-Йейтса по Дюрзенфельду, чтобы вставить полученные значения в набор назначения. Тем не менее, это излишне, поскольку они должны выбираться случайным образом и случайным образом, как указано здесь.
Оба алгоритма предполагают, что у вас есть некоторый метод экземпляра случайного числа, nextInt (int setSize), который генерирует случайное целое число от нуля до setSize, что означает наличие возможных значений setSize. В этом случае это будет размер массива, поскольку последний индекс массива имеет размер-1.
Первый алгоритм - это дюрстенфельдская версия алгоритма тасования Фишера-Йейтса (он же Кнут), применяемая к массиву произвольной длины, который просто случайным образом позиционирует целые числа от 0 до длины массива в массиве. Массив не обязательно должен быть массивом целых чисел, но может быть массивом любых объектов, которые получаются последовательно, что фактически делает его массивом ссылочных указателей. Это просто, коротко и очень эффективно
int size = someNumber;
int[] int array = new int[size]; // here is the array to load
int location; // this will get assigned a value before used
// i will also conveniently be the value to load, but any sequentially acquired
// object will work
for (int i = 0; i <= size; i++) { // conveniently, i is also the value to load
// you can instance or acquire any object at this place in the algorithm to load
// by reference, into the array and use a pointer to it in place of j
int j = i; // in this example, j is trivially i
if (i == 0) { // first integer goes into first location
array[i] = j; // this may get swapped from here later
} else { // subsequent integers go into random locations
// the next random location will be somewhere in the locations
// already used or a new one at the end
// here we get the next random location
// to preserve true randomness without a significant bias
// it is REALLY IMPORTANT that the newest value could be
// stored in the newest location, that is,
// location has to be able to randomly have the value i
int location = nextInt(i + 1); // a random value between 0 and i
// move the random location's value to the new location
array[i] = array[location];
array[location] = j; // put the new value into the random location
} // end if...else
} // end for
Вуаля, теперь у вас уже есть рандомизированный массив.
Если вы хотите случайным образом перемешать массив, который у вас уже есть, вот стандартный алгоритм Фишера-Йейтса.
type[] array = new type[size];
// some code that loads array...
// randomly pick an item anywhere in the current array segment,
// swap it with the top element in the current array segment,
// then shorten the array segment by 1
// just as with the Durstenfeld version above,
// it is REALLY IMPORTANT that an element could get
// swapped with itself to avoid any bias in the randomization
type temp; // this will get assigned a value before used
int location; // this will get assigned a value before used
for (int i = arrayLength -1 ; i > 0; i--) {
int location = nextInt(i + 1);
temp = array[i];
array[i] = array[location];
array[location] = temp;
} // end for
Для последовательных коллекций и наборов, то есть для некоторого типа объекта списка, вы можете просто использовать добавления или вставки со значением индекса, которое позволяет вставлять элементы в любое место, но оно должно разрешать добавление или добавление после текущего последнего элемента Избегайте смещения в рандомизации.