Это метод SDK, который вы ищете для Collections.shuffle (Arrays.asList (array));
Луи Хонг
2
@ Луи Нет, это не работает. Это создаст List<int[]>одну запись. Смотрите мой ответ о том, как добиться этого с помощью Collections.shuffle().
Дункан Джонс
2
Не совсем ответ на первоначальный вопрос, но MathArrays.shuffle из библиотеки commons-math3 делает свою работу.
Сандрис
1
Этого недостаточно для того, чтобы получить ответ, но я помню действительно классную статью из книги «Graphics Gems», в которой говорилось о обходе массива в псевдослучайном порядке. На мой взгляд, это лучше, чем просто перетасовывать данные. C-реализация находится здесь github.com/erich666/GraphicsGems/blob/master/gems/Dissolve.c
import java.util.*;import java.util.concurrent.ThreadLocalRandom;classTest{publicstaticvoid main(String args[]){int[] solutionArray ={1,2,3,4,5,6,16,15,14,13,12,11};
shuffleArray(solutionArray);for(int i =0; i < solutionArray.length; i++){System.out.print(solutionArray[i]+" ");}System.out.println();}// Implementing Fisher–Yates shufflestaticvoid shuffleArray(int[] ar){// If running on Java 6 or older, use `new Random()` on RHS hereRandom rnd =ThreadLocalRandom.current();for(int i = ar.length -1; i >0; i--){int index = rnd.nextInt(i +1);// Simple swapint a = ar[index];
ar[index]= ar[i];
ar[i]= a;}}}
Чрезвычайно тривиальный придурок, но вы можете просто использовать println()вместо println(""). Яснее в намерениях я думаю :)
Коуэн
55
Было бы намного лучше использовать Collections.shuffle (Arrays.asList (array)); затем сделать себе перемешать.
Луи Хонг
21
@ Луи Collections.shuffle(Arrays.asList(array))не работает, потому что Arrays.asList(array)возвращается Collection<int[]>не так, Collection<Integer>как вы думали.
Адам Стельмащик
15
@exhuma Потому что, если у вас есть массив тысяч или миллионов примитивных значений для сортировки, оборачивать каждое из них в объект просто для того, чтобы выполнить сортировку, будет немного дорого, как в памяти, так и в процессоре.
Фил
14
Это не случайность Фишера-Йейтса. Это называется дурстенфельдский шаффл . Оригинальный тасовщик Фишер-Йейтса выполняется за время O (n ^ 2), что очень медленно.
Pacerier
164
Вот простой способ использования ArrayList:
List<Integer> solution =newArrayList<>();for(int i =1; i <=6; i++){
solution.add(i);}Collections.shuffle(solution);
Вы можете простоCollectons.shuffle(Arrays.asList(solutionArray));
FindOutIslamNow
@ Тиммос Ты не прав. Arrays.asList оборачивает исходный массив и, таким образом, изменяя его, изменяет исходный массив. Вот почему вы не можете добавлять или удалять, потому что массивы имеют фиксированный размер.
Nand
@ Не знаю, о чем я думал, но, глядя на исходный код, действительно, метод Arrays.asList создает ArrayList, поддерживаемый данным массивом. Спасибо за указание на это. Удален мой предыдущий комментарий (не могу его отредактировать).
Тиммос
100
Вот работающая и эффективная функция массива Фишера-Йейтса:
privatestaticvoid shuffleArray(int[] array){int index;Random random =newRandom();for(int i = array.length -1; i >0; i--){
index = random.nextInt(i +1);if(index != i){
array[index]^= array[i];
array[i]^= array[index];
array[index]^= array[i];}}}
или
privatestaticvoid shuffleArray(int[] array){int index, temp;Random random =newRandom();for(int i = array.length -1; i >0; i--){
index = random.nextInt(i +1);
temp = array[index];
array[index]= array[i];
array[i]= temp;}}
Проголосовал, потому что мне нужно было решение, которое не требовало больших затрат на создание коллекции
целых чисел
2
Разве вторая реализация не может заменить свой собственный индекс? random.nextInt(int bound)является эксклюзивным, но предоставление его i + 1в качестве аргумента позволит indexи iпотенциально может быть таким же.
bmcentee148
21
@ bmcentee148 Обмен элемента с самим собой допустим в случайном порядке. Непонимание этого ослабило Энигму и помогло Алану Тьюрингу взломать ее. en.wikipedia.org/wiki/…
Эллен Спертус
4
xorТрюк отлично подходит для замены регистров процессора , когда процессор не имеют инструкций подкачки и нет свободных регистров, но для замены элементов массива внутри цикла, я не вижу никакой пользы. Для временных локальных переменных нет причин объявлять их вне цикла.
Хольгер
1
Немного эффективнее объявить tempпеременную вне цикла. XORТрюк должен быть быстрее , чем при использовании tempпеременной , но единственный способ быть уверенным , что для выполнения теста бенчмарк.
Дэн Брей
25
Класс Collections имеет эффективный метод тасования, который можно скопировать, чтобы не зависеть от него:
/**
* Usage:
* int[] array = {1, 2, 3};
* Util.shuffle(array);
*/publicclassUtil{privatestaticRandom random;/**
* Code from method java.util.Collections.shuffle();
*/publicstaticvoid shuffle(int[] array){if(random ==null) random =newRandom();int count = array.length;for(int i = count; i >1; i--){
swap(array, i -1, random.nextInt(i));}}privatestaticvoid swap(int[] array,int i,int j){int temp = array[i];
array[i]= array[j];
array[j]= temp;}}
чтобы не зависеть от этого ? Я бы предпочел зависеть от этого, если бы это было возможно.
shmosel
@shmosel Тогда не стесняйтесь использовать его. Убедитесь, что вы импортировали требуемый класс и преобразовали массив в список с помощью Arrays.asList. Вы должны преобразовать полученный список в массив, тоже
KitKat
Вы не можете использовать Arrays.asList()примитивный массив. И вам не нужно конвертировать его обратно, потому что это просто оболочка.
Шмосель
13
Посмотрите на Collectionsкласс, в частности shuffle(...).
Как вы используете этот класс коллекций в Android? Вам нужно сделать специальный импорт (CRTL SHIFT O не работает), чтобы использовать его?
Юбер
@ Хьюберт, это должно быть частью пакета java.util. Это часть стандартной библиотеки начиная с версии 1.2.
MauganRa
3
Чтобы сделать ваш ответ более автономным, он должен содержать пример кода. IE:import java.util.Collections; shuffle(solutionArray);
Stevoisiak
10
Вот полное решение с использованием Collections.shuffleподхода:
publicstaticvoid shuffleArray(int[] array){List<Integer> list =newArrayList<>();for(int i : array){
list.add(i);}Collections.shuffle(list);for(int i =0; i < list.size(); i++){
array[i]= list.get(i);}}
Обратите внимание, что он страдает из-за неспособности Java плавно переводить между int[]и Integer[](и, следовательно, int[]и List<Integer>).
Ниже представлены три различных варианта воспроизведения в случайном порядке. Вы должны использовать Collections.shuffle, только если вы имеете дело с коллекцией. Нет необходимости заключать ваш массив в коллекцию только для его сортировки. Методы ниже очень просты в реализации.
Вы не синхронизируете одни и те же вещи, и вы синхронизируете каждое из них только один раз (тогда их порядок считается, и вы забываете оптимизацию времени выполнения). Вы должны вызывать range, toArrayи toPrimitiveперед любым таймингом, и цикл, чтобы иметь возможность что-либо завершить (псевдокод: сделать несколько раз {генерировать список, arr и iarr; список перетасовки времени; arr перетасовки времени; перестановку времени iarr}). Мои результаты: 1 - й: list: 36017ns, arr: 28262ns, iarr: 23334ns. Сотый: list: 18445ns, arr: 19995ns, iarr: 18657ns. Это просто показывает, что int [] предварительно оптимизирован (по коду), но они почти эквивалентны оптимизации времени выполнения.
Syme
9
Использование ArrayList<Integer>может помочь вам решить проблему перетасовки, не применяя много логики и не тратя меньше времени. Вот что я предлагаю:
ArrayList<Integer> x =newArrayList<Integer>();for(int i=1; i<=add.length(); i++){
x.add(i);}Collections.shuffle(x);
В этом коде нет ничего специфичного для Java8. Это работает с Java2. Ну, это будет работать, как только вы исправите несоответствие между первым использованием listи внезапным обращением к cardsList. Но так как вам нужно создать временный файл list, который вы пропустили, нет никакого преимущества по сравнению с Collections.shuffle(Arrays.asList(arr));подходом, показанным здесь несколько раз. Который также работает с Java2.
Хольгер
3
Вот версия Generics для массивов:
import java.util.Random;publicclassShuffle<T>{privatefinalRandom rnd;publicShuffle(){
rnd =newRandom();}/**
* Fisher–Yates shuffle.
*/publicvoid shuffle(T[] ar){for(int i = ar.length -1; i >0; i--){int index = rnd.nextInt(i +1);
T a = ar[index];
ar[index]= ar[i];
ar[i]= a;}}}
Учитывая, что ArrayList - это просто массив, может быть целесообразно работать с ArrayList вместо явного массива и использовать Collections.shuffle (). Тесты производительности, однако, не показывают какой-либо существенной разницы между приведенным выше и Collections.sort ():
Shuffe<Integer>.shuffle(...) performance:576084 shuffles per second
Collections.shuffle(ArrayList<Integer>) performance:629400 shuffles per second
MathArrays.shuffle(int[]) performance:53062 shuffles per second
Реализация Apache Commons MathArrays.shuffle ограничена int [], и снижение производительности, вероятно, связано с использованием генератора случайных чисел.
Похоже, вы можете перейти new JDKRandomGenerator()к MathArrays.shuffle. Интересно, как это влияет на производительность?
Брэндон
На самом деле ... похоже MathArrays#shuffleимеет распределение в своей основной петле: int targetIdx = new UniformIntegerDistribution(rng, start, i).sample();. Bizarre.
Брэндон
3
Random rnd =newRandom();for(int i = ar.length -1; i >0; i--){int index = rnd.nextInt(i +1);// Simple swapint a = ar[index];
ar[index]= ar[i];
ar[i]= a;}
Кстати, я заметил, что этот код возвращает ar.length - 1несколько элементов, поэтому, если ваш массив имеет 5 элементов, новый перемешанный массив будет иметь 4 элемента. Это происходит потому, что цикл for говорит i>0. Если вы измените на i>=0, вы получите все элементы перемешанными.
Просто наперед, вы можете переместить это в раздел комментариев вашего вопроса, так как он, вероятно, будет помечен, если будет оставлен как собственный ответ.
Джейсон Д
1
Это, кажется, отвечает на вопрос, поэтому я не уверен, о чем вы говорите @JasonD
Sumurai8
1
Код правильный, комментарий неправильный. Если вы измените i>0на i>=0, вы тратите время, меняя элемент 0с собой.
jcsahnwaldt восстановить Монику
3
Вот решение с использованием Apache Commons Math 3.x (только для массивов int []):
Я видел некоторую информацию о пропусках в некоторых ответах, поэтому решил добавить новую.
Java коллекции Arrays.asList занимает VAR-ARG типа T (T ...). Если вы передадите примитивный массив (массив int), метод asList выведет и сгенерируетList<int[]> , представляющий собой список из одного элемента (один элемент - это массив примитивов). если вы перемешаете этот список из одного элемента, он ничего не изменит.
Итак, сначала вы должны преобразовать свой примитивный массив в массив объектов Wrapper. для этого вы можете использовать ArrayUtils.toObjectметод из apache.commons.lang. затем передайте сгенерированный массив в List и, наконец, перемешайте его.
int[] intArr ={1,2,3};List<Integer> integerList =Arrays.asList(ArrayUtils.toObject(array));Collections.shuffle(integerList);//now! elements in integerList are shuffled!
publicList<Integer> shuffleArray(List<Integer> a){List<Integer> b =newArrayList<Integer>();while(a.size()!=0){int arrayIndex =(int)(Math.random()*(a.size()));
b.add(a.get(arrayIndex));
a.remove(a.get(arrayIndex));}return b;}
Выберите случайное число из исходного списка и сохраните его в другом списке. Затем удалите число из исходного списка. Размер исходного списка будет уменьшаться на единицу, пока все элементы не будут перемещены в новый список.
Это позволит отсортировать все элементы списка массивов случайным образом, что приведет к архивированию желаемого результата перемешивания всех элементов.
Я взвешиваю этот очень популярный вопрос, потому что никто не написал версию в случайном порядке. Стиль сильно заимствован Arrays.java, потому что, кто не грабит технологии Java в наши дни? Общие и intреализации включены.
/**
* Shuffles elements from {@code original} into a newly created array.
*
* @param original the original array
* @return the new, shuffled array
* @throws NullPointerException if {@code original == null}
*/@SuppressWarnings("unchecked")publicstatic<T> T[] shuffledCopy(T[] original){int originalLength = original.length;// For exception priority compatibility.Random random =newRandom();
T[] result =(T[])Array.newInstance(original.getClass().getComponentType(), originalLength);for(int i =0; i < originalLength; i++){int j = random.nextInt(i+1);
result[i]= result[j];
result[j]= original[i];}return result;}/**
* Shuffles elements from {@code original} into a newly created array.
*
* @param original the original array
* @return the new, shuffled array
* @throws NullPointerException if {@code original == null}
*/publicstaticint[] shuffledCopy(int[] original){int originalLength = original.length;Random random =newRandom();int[] result =newint[originalLength];for(int i =0; i < originalLength; i++){int j = random.nextInt(i+1);
result[i]= result[j];
result[j]= original[i];}return result;}
publicclassKnuth{// this class should not be instantiatedprivateKnuth(){}/**
* Rearranges an array of objects in uniformly random order
* (under the assumption that <tt>Math.random()</tt> generates independent
* and uniformly distributed numbers between 0 and 1).
* @param a the array to be shuffled
*/publicstaticvoid shuffle(Object[] a){int n = a.length;for(int i =0; i < n; i++){// choose index uniformly in [i, n-1]int r = i +(int)(Math.random()*(n - i));Object swap = a[r];
a[r]= a[i];
a[i]= swap;}}/**
* Reads in a sequence of strings from standard input, shuffles
* them, and prints out the results.
*/publicstaticvoid main(String[] args){// read in the dataString[] a =StdIn.readAllStrings();// shuffle the arrayKnuth.shuffle(a);// print results.for(int i =0; i < a.length; i++)StdOut.println(a[i]);}}
Самое простое решение для этой случайной перестановки в массиве.
String location[]={"delhi","banglore","mathura","lucknow","chandigarh","mumbai"};int index;String temp;Random random =newRandom();for(int i=1;i<location.length;i++){
index = random.nextInt(i+1);
temp = location[index];
location[index]= location[i];
location[i]= temp;System.out.println("Location Based On Random Values :"+location[i]);}
publicstaticvoid randomizeArray(int[] arr){Random rGenerator =newRandom();// Create an instance of the random class for(int i =0; i< arr.length;i++){//Swap the positions...int rPosition = rGenerator.nextInt(arr.length);// Generates an integer within the range (Any number from 0 - arr.length)int temp = arr[i];// variable temp saves the value of the current array index;
arr[i]= arr[rPosition];// array at the current position (i) get the value of the random generated
arr[rPosition]= temp;// the array at the position of random generated gets the value of temp}for(int i =0; i<arr.length; i++){System.out.print(arr[i]);//Prints out the array}}
Пожалуйста, добавьте описание, связанное с вашим ответом.
Анкит Сутар
0
import java.util.ArrayList;import java.util.Random;publicclass shuffle {publicstaticvoid main(String[] args){int a[]={1,2,3,4,5,6,7,8,9};ArrayList b =newArrayList();int i=0,q=0;Random rand =newRandom();while(a.length!=b.size()){int l = rand.nextInt(a.length);//this is one option to that but has a flaw on 0// if(a[l] !=0)// {// b.add(a[l]);// a[l]=0;// // }// // this works for every no. if(!(b.contains(a[l]))){
b.add(a[l]);}}// for (int j = 0; j <b.size(); j++) {// System.out.println(b.get(j));// // }System.out.println(b);}}
Random r =newRandom();int n = solutionArray.length;List<Integer> arr =Arrays.stream(solutionArray).boxed().collect(Collectors.toList());for(int i =0; i < n-1; i++){
solutionArray[i]= arr.remove( r.nextInt(arr.size()));// randomize base on size}
solutionArray[n-1]= arr.get(0);
Одним из решений является использование перестановки для предварительного вычисления всех перестановок и сохранения в ArrayList
Java 8 представила новый метод, ints (), в классе java.util.Random. Метод ints () возвращает неограниченный поток псевдослучайных значений int. Вы можете ограничить случайные числа между указанным диапазоном, указав минимальное и максимальное значения.
Random genRandom =newRandom();int num = genRandom.nextInt(arr.length);
С помощью генерации случайного числа, вы можете перебрать цикл и поменять местами текущий индекс со случайным числом. Вот так вы можете сгенерировать случайное число с O (1) пространственной сложностью.
List<int[]>
одну запись. Смотрите мой ответ о том, как добиться этого с помощьюCollections.shuffle()
.Ответы:
Использование коллекций для перемешивания массива примитивных типов - это немного излишне ...
Достаточно просто реализовать эту функцию самостоятельно, например, с помощью перемешивания Фишера-Йейтса :
источник
println()
вместоprintln("")
. Яснее в намерениях я думаю :)Collections.shuffle(Arrays.asList(array))
не работает, потому чтоArrays.asList(array)
возвращаетсяCollection<int[]>
не так,Collection<Integer>
как вы думали.Вот простой способ использования
ArrayList
:источник
Collectons.shuffle(Arrays.asList(solutionArray));
Вот работающая и эффективная функция массива Фишера-Йейтса:
или
источник
random.nextInt(int bound)
является эксклюзивным, но предоставление егоi + 1
в качестве аргумента позволитindex
иi
потенциально может быть таким же.xor
Трюк отлично подходит для замены регистров процессора , когда процессор не имеют инструкций подкачки и нет свободных регистров, но для замены элементов массива внутри цикла, я не вижу никакой пользы. Для временных локальных переменных нет причин объявлять их вне цикла.temp
переменную вне цикла.XOR
Трюк должен быть быстрее , чем при использованииtemp
переменной , но единственный способ быть уверенным , что для выполнения теста бенчмарк.Класс Collections имеет эффективный метод тасования, который можно скопировать, чтобы не зависеть от него:
источник
Arrays.asList
. Вы должны преобразовать полученный список в массив, тожеArrays.asList()
примитивный массив. И вам не нужно конвертировать его обратно, потому что это просто оболочка.Посмотрите на
Collections
класс, в частностиshuffle(...)
.источник
java.util
. Это часть стандартной библиотеки начиная с версии 1.2.import java.util.Collections; shuffle(solutionArray);
Вот полное решение с использованием
Collections.shuffle
подхода:Обратите внимание, что он страдает из-за неспособности Java плавно переводить между
int[]
иInteger[]
(и, следовательно,int[]
иList<Integer>
).источник
У вас есть несколько вариантов здесь. Список немного отличается от массива, когда дело доходит до перемешивания.
Как вы можете видеть ниже, массив быстрее, чем список, а примитивный массив быстрее, чем массив объектов.
Длительность образца
Ниже представлены три различных варианта воспроизведения в случайном порядке. Вы должны использовать Collections.shuffle, только если вы имеете дело с коллекцией. Нет необходимости заключать ваш массив в коллекцию только для его сортировки. Методы ниже очень просты в реализации.
ShuffleUtil Class
Основной метод
Перемешивание общего списка
Перетасовка универсального массива
Перетасовка примитивного массива
Полезные методы
Простые служебные методы для копирования и преобразования массивов в списки и наоборот.
Range Class
Создает диапазон значений, аналогичный
range
функции Python .источник
range
,toArray
иtoPrimitive
перед любым таймингом, и цикл, чтобы иметь возможность что-либо завершить (псевдокод: сделать несколько раз {генерировать список, arr и iarr; список перетасовки времени; arr перетасовки времени; перестановку времени iarr}). Мои результаты: 1 - й:list: 36017ns, arr: 28262ns, iarr: 23334ns
. Сотый:list: 18445ns, arr: 19995ns, iarr: 18657ns
. Это просто показывает, что int [] предварительно оптимизирован (по коду), но они почти эквивалентны оптимизации времени выполнения.Использование
ArrayList<Integer>
может помочь вам решить проблему перетасовки, не применяя много логики и не тратя меньше времени. Вот что я предлагаю:источник
Следующий код достигнет случайного порядка в массиве.
от: http://www.programcreek.com/2012/02/java-method-to-shuffle-an-int-array-with-random-order/
источник
Вы можете использовать Java 8 сейчас:
источник
list
и внезапным обращением кcardsList
. Но так как вам нужно создать временный файлlist
, который вы пропустили, нет никакого преимущества по сравнению сCollections.shuffle(Arrays.asList(arr));
подходом, показанным здесь несколько раз. Который также работает с Java2.Вот версия Generics для массивов:
Учитывая, что ArrayList - это просто массив, может быть целесообразно работать с ArrayList вместо явного массива и использовать Collections.shuffle (). Тесты производительности, однако, не показывают какой-либо существенной разницы между приведенным выше и Collections.sort ():
Реализация Apache Commons MathArrays.shuffle ограничена int [], и снижение производительности, вероятно, связано с использованием генератора случайных чисел.
источник
new JDKRandomGenerator()
кMathArrays.shuffle
. Интересно, как это влияет на производительность?MathArrays#shuffle
имеет распределение в своей основной петле:int targetIdx = new UniformIntegerDistribution(rng, start, i).sample();
. Bizarre.Кстати, я заметил, что этот код возвращает
ar.length - 1
несколько элементов, поэтому, если ваш массив имеет 5 элементов, новый перемешанный массив будет иметь 4 элемента. Это происходит потому, что цикл for говоритi>0
. Если вы измените наi>=0
, вы получите все элементы перемешанными.источник
i>0
наi>=0
, вы тратите время, меняя элемент0
с собой.Вот решение с использованием Apache Commons Math 3.x (только для массивов int []):
http://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/util/MathArrays.html#shuffle (INT [])
Кроме того, Apache Commons Lang 3.6 представил новые методы перемешивания в
ArrayUtils
классе (для объектов и любого примитивного типа).http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/ArrayUtils.html#shuffle-int:A-
источник
Я видел некоторую информацию о пропусках в некоторых ответах, поэтому решил добавить новую.
Java коллекции Arrays.asList занимает VAR-ARG типа T
(T ...)
. Если вы передадите примитивный массив (массив int), метод asList выведет и сгенерируетList<int[]>
, представляющий собой список из одного элемента (один элемент - это массив примитивов). если вы перемешаете этот список из одного элемента, он ничего не изменит.Итак, сначала вы должны преобразовать свой примитивный массив в массив объектов Wrapper. для этого вы можете использовать
ArrayUtils.toObject
метод из apache.commons.lang. затем передайте сгенерированный массив в List и, наконец, перемешайте его.источник
Вот еще один способ перемешать список
Выберите случайное число из исходного списка и сохраните его в другом списке. Затем удалите число из исходного списка. Размер исходного списка будет уменьшаться на единицу, пока все элементы не будут перемещены в новый список.
источник
Простое решение для Groovy:
Это позволит отсортировать все элементы списка массивов случайным образом, что приведет к архивированию желаемого результата перемешивания всех элементов.
источник
Используя Guava
Ints.asList()
это так же просто, как:источник
Я взвешиваю этот очень популярный вопрос, потому что никто не написал версию в случайном порядке. Стиль сильно заимствован
Arrays.java
, потому что, кто не грабит технологии Java в наши дни? Общие иint
реализации включены.источник
Это алгоритм Knuth Shuffle.
источник
Есть и другой способ, еще не пост
так проще, зависит от контекста
источник
Самое простое решение для этой случайной перестановки в массиве.
источник
int[]
доInteger[]
Arrays.asList
методомПеремешать с
Collections.shuffle
методомисточник
Простейший код для перемешивания:
источник
Использование случайного класса
источник
источник
источник
похоже без использования свопа б
источник
Одним из решений является использование перестановки для предварительного вычисления всех перестановок и сохранения в ArrayList
Java 8 представила новый метод, ints (), в классе java.util.Random. Метод ints () возвращает неограниченный поток псевдослучайных значений int. Вы можете ограничить случайные числа между указанным диапазоном, указав минимальное и максимальное значения.
С помощью генерации случайного числа, вы можете перебрать цикл и поменять местами текущий индекс со случайным числом. Вот так вы можете сгенерировать случайное число с O (1) пространственной сложностью.
источник
Без случайного решения:
источник