Вот схема решения, использующего алгоритм Фишера-Йейтса shuffle .Идея состоит в том, чтобы вычислить хэш для каждого сгенерированного случайного порядка и использовать этот хэш для проверки того, что порядок не повторяется
public static void main(String[] args) {
String[] words = new String[] {"bananas", "oranges", "apples", "peaches"};
int randomCount = 10; //this needs to <= (words.length)!
Iterator<String[]> randomIterator = new Iterator<>() {
Set<Integer> hashes = new HashSet<>();
@Override
public boolean hasNext() {
return hashes.size() < randomCount;
}
@Override
public String[] next() {
int i = words.length;
while(i > 1) {
i--;
int j = new Random().nextInt(i + 1);
String temp = words[i];
words[i] = words[j];
words[j] = temp;
}
int h = Arrays.hashCode(words);
if(hashes.contains(h)) next();
hashes.add(h);
return words;
}
};
int c = 1;
while(randomIterator.hasNext()) {
System.out.println(c++ + " " + Arrays.toString(randomIterator.next()));
}
}
Это приводит к выводу:
1 [apples, oranges, bananas, peaches]
2 [apples, peaches, bananas, oranges]
3 [oranges, apples, peaches, bananas]
4 [bananas, peaches, oranges, apples]
5 [bananas, oranges, apples, peaches]
6 [oranges, bananas, apples, peaches]
7 [apples, bananas, peaches, oranges]
8 [peaches, apples, oranges, bananas]
9 [peaches, oranges, bananas, apples]
10 [bananas, apples, peaches, oranges]
Используя итератор, мы можемубедитесь, что алгоритм тасования выполняется только столько раз, сколько необходимо, прежде чем мы повторим шаблон.Вы можете изменить механизм ввода / вывода на нужный вам метод.
Это может быть улучшено в зависимости от варианта использования.Например, вы можете очистить набор хэшей, когда все шаблоны будут сгенерированы один раз, и избежать ошибки StackOverflow Error
, пропустив n! повторений.Вы также можете использовать List
вместо Array
и использовать Collections.shuffle()
, чтобы получить новый случайный порядок, как предполагает другой ответ.