Синхронная перестановка элементов в двух ArrayList Java
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
import java.util.Collections;
import java.util.List;
import java.util.Random;
List<String> list1 = // ...;
List<Integer> list2 = // ...;
long seed = System.nanoTime();
Collections.shuffle(list1, new Random(seed));
Collections.shuffle(list2, new Random(seed));
Для равномерного перемешивания двух списков достаточно сгенерировать общий seed и использовать его при создании экземпляра класса Random
для каждого из списков.
Углубляемся: От основ к мелочам
Если вам необходимо освоить тонкости случайного распределения списков, при этом сохраняя связь между элементами, стоит обратить внимание на методы, позволяющие сохранять целостность данных в процессе перемешивания.
Сопоставление связанных элементов: Встречаем инкапсуляцию
Когда требуется создать связь между элементами, например, между именами файлов и изображениями или игроками и их баллами, оптимальным решением будет инкапсуляция данных в одном классе:
class DataPair {
String file;
String image;
// Конструкторы, геттеры, сеттеры...
}
List<DataPair> dataList = new ArrayList<>();
...
long seed = System.nanoTime();
Collections.shuffle(dataList, new Random(seed));
Применим алгоритм Фишера — Йетса: Когда кружит в танце
Для массивов примитивных типов или когда нужен особенный контроль над процессом, можно применить алгоритм Фишера — Йетса:
void shuffleArray(Object[] array, long seed) {
Random rnd = new Random(seed);
for (int i = array.length – 1; i > 0; i--) {
int index = rnd.nextInt(i + 1);
Object a = array[index];
array[index] = array[i];
array[i] = a;
}
}
Контроль корректности данных после перемешивания: Бдительность в деле
Необходимо обязательно проверять данные после их перемешивания:
assert list1.size() == list2.size();
for (int i = 0; i < list1.size(); i++) {
assert list1.get(i).relatedId == list2.get(i).id;
}
Приветствуем Java Records: Минимализм в действии
Java Records (доступны, начиная с Java 16), облегчает работу со связанными данными:
record DataPair(String file, String image){}
...
List<DataPair> dataList = new ArrayList<>();
...
Визуализация
Придставим перед собой две колоды карт:
Колода A (ArrayList1): [Туз ♠️, Король ♣️, Дама ♥️]
Колода B (ArrayList2): [Яблоко 🍎, Банан 🍌, Вишня 🍒]
Используя общий идентификатор (seed) для перемешивания:
Collections.shuffle(Колода A, new Random(seed));
Collections.shuffle(Колода B, new Random(seed));
Колоды равномерно перемешаются:
Перемешанная Колода A: [Дама ♥️, Туз ♠️, Король ♣️]
Перемешанная Колода B: [Вишня 🍒, Яблоко 🍎, Банан 🍌]
Таким образом, каждому элементу из первой колоды будет соответствовать элемент из второй колоды.
Применение карт (maps): Объемные датасеты, широкие возможности
Для обработки больших объемов данных с сохранением взаимосвязей применяйте карты (maps):
Map<Integer, DataPair> map = new HashMap<>();
...
List<Integer> keys = new ArrayList<>(map.keySet());
Collections.shuffle(keys, new Random(seed));
Проверка данных: Никто не застрахован от ошибок
После перемешивания обязательно убедитесь, что взаимосвязи между данными сохранены:
for (int key : keys) {
DataPair pair = map.get(key);
// Проверка корректности связи
}