Explain Codes LogoExplain Codes Logo

How to randomize two ArrayLists in the same fashion?

java
randomization
data-integrity
fisher-yates
Nikita BarsukovbyNikita Barsukov·Aug 3, 2024
TLDR
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)); // Shuffling is fun Collections.shuffle(list2, new Random(seed)); // Better not to shuffle real paperwork like this

In one fell swoop, you can uniformly shuffle two Lists: generate a shared seed, then shuffle each list with a newly minted Random object produced by that timeless seed.

Delving deeper: Beyond basics

Mastering the art of randomizing lists with preserved relationships requires more than the basics. Let's dive one level deeper, exploring multiple techniques for why and when we maintain data integrity in the shuffle process.

Pairing related elements like files with images or players with scores could be simplified by sealing them into a bundle. Here, encapsulation shines:

// No programmer was harmed during the creation of this mini class class DataPair { String file; String image; // Constructors, getters, setters... } List<DataPair> dataList = new ArrayList<>(); // Populate the list before party ... long seed = System.nanoTime(); Collections.shuffle(dataList, new Random(seed)); // Careful! Drunk shuffle may lead to unpaired socks

Applying Fisher-Yates shuffle: Dancing solo

If your jigsaw puzzle is primitive arrays or needing extra control you became best friends with Fisher-Yates shuffle. Just implement this algorithm and you're the DJ of the shuffle party:

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); // Swap: It's not awkward, it's just programming! Object a = array[index]; array[index] = array[i]; array[i] = a; } }

Ensuring data sanity post-shuffle: Paranoia or thoroughness?

Post-validation is crucial. Double-checking never hurt anyone, especially in a shuffle:

assert list1.size() == list2.size(); // Oops! An extra egg in the basket for (int i = 0; i < list1.size(); i++) { assert list1.get(i).relatedId == list2.get(i).id; // Each item is the key to another's heart }

Welcome Java Records: For Minimalists

Java records, available from Java 16, gives us cleaner and simpler solutions for related items management. Say goodbye to verbose code:

record DataPair(String file, String image){} // The tiny house of data structures ... List<DataPair> dataList = new ArrayList<>(); ...

Maps in action: Bigger datasets, wider scopes

Consider using maps for shuffling larger datasets and preserving relationships:

Map<Integer, DataPair> map = new HashMap<>(); // Map: Your new best friend ... List<Integer> keys = new ArrayList<>(map.keySet()); Collections.shuffle(keys, new Random(seed)); // Let's see who will land where

Validating data: Because nobody is perfect

Confirm that shuffle didn't mess up the connections:

for (int key : keys) { DataPair pair = map.get(key); // Opening Pandora's box // Check for integrity here }