Java Collections.shuffle Method
Last modified: April 20, 2025
The Collections.shuffle
method is part of Java's Collections
Framework. It randomly permutes the specified list using a default or specified
source of randomness. This method is useful for randomization tasks in Java.
Shuffling is commonly needed in applications like games, simulations, and statistical sampling. The method operates in linear time and modifies the original list rather than returning a new shuffled list.
Collections.shuffle Overview
The Collections.shuffle
method has two overloaded versions. One
takes just a List, using a default random source. The other takes both a List
and a Random object for controlled randomness. Both versions shuffle in-place.
The method uses the Fisher-Yates shuffle algorithm internally. This algorithm produces a uniformly random permutation of the list elements. The time complexity is O(n) where n is the list size.
Basic Shuffle Example
This example demonstrates the simplest use of Collections.shuffle
.
We create a list of numbers and shuffle them. The output shows the list before
and after shuffling.
package com.zetcode; import java.util.Arrays; import java.util.Collections; import java.util.List; public class BasicShuffle { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); System.out.println("Original list: " + numbers); Collections.shuffle(numbers); System.out.println("Shuffled list: " + numbers); } }
This code creates an immutable list of numbers using Arrays.asList
.
We print the original order, then call Collections.shuffle
to
randomize the list. Finally, we print the shuffled result.
Each run produces different output because the shuffle is random. The original list remains unchanged if you need to preserve it, create a copy first.
Shuffling with Custom Random Source
This example shows how to use a specific Random object with
Collections.shuffle
. Using a seeded Random allows reproducible
shuffles, which is useful for testing and debugging.
package com.zetcode; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Random; public class SeededShuffle { public static void main(String[] args) { List<String> colors = Arrays.asList("Red", "Green", "Blue", "Yellow"); Random random = new Random(42); // Fixed seed for reproducibility System.out.println("Original: " + colors); Collections.shuffle(colors, random); System.out.println("First shuffle: " + colors); // Reshuffle with same seed random.setSeed(42); Collections.shuffle(colors, random); System.out.println("Second shuffle: " + colors); } }
We create a list of colors and a Random object with seed 42. The first shuffle randomizes the list. By resetting the seed and shuffling again, we get identical results both times.
This technique is valuable when you need predictable randomness, such as in unit tests or when debugging shuffle-related issues. The same seed always produces the same shuffle order.
Shuffling a List of Custom Objects
Collections.shuffle
works with any List implementation containing
any object type. This example demonstrates shuffling a list of custom Person
objects.
package com.zetcode; import java.util.ArrayList; import java.util.Collections; import java.util.List; class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return name + " (" + age + ")"; } } public class ShuffleCustomObjects { public static void main(String[] args) { List<Person> people = new ArrayList<>(); people.add(new Person("Alice", 25)); people.add(new Person("Bob", 30)); people.add(new Person("Charlie", 22)); people.add(new Person("Diana", 28)); System.out.println("Original order:"); people.forEach(System.out::println); Collections.shuffle(people); System.out.println("\nShuffled order:"); people.forEach(System.out::println); } }
We define a simple Person class with name and age fields. After creating and
populating a list of Person objects, we shuffle it using
Collections.shuffle
. The output shows the random reordering.
This demonstrates that shuffle works with any object type, not just primitive wrappers or Strings. The Person objects maintain their integrity while their order in the list changes.
Shuffling Part of a List
To shuffle only a portion of a list, we can use List.subList
to
create a view of the desired range. This example shows how to shuffle just the
first half of a list.
package com.zetcode; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class PartialShuffle { public static void main(String[] args) { List<Integer> numbers = new ArrayList<>(); for (int i = 1; i <= 10; i++) { numbers.add(i); } System.out.println("Original list: " + numbers); // Shuffle first half int halfSize = numbers.size() / 2; Collections.shuffle(numbers.subList(0, halfSize)); System.out.println("Half-shuffled: " + numbers); } }
We create a list of numbers 1 through 10. Using subList(0, halfSize)
,
we create a view of the first half of the list. Shuffling this sublist affects
only those elements in the original list.
The output shows the first five numbers randomized while the last five remain in their original order. This technique is useful when you need to randomize only a specific section of a list.
Shuffling Arrays via List Conversion
While Collections.shuffle
works on Lists, we can shuffle arrays by
first converting them to a List. This example demonstrates the technique using
Arrays.asList
.
package com.zetcode; import java.util.Arrays; import java.util.Collections; import java.util.List; public class ShuffleArray { public static void main(String[] args) { Integer[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9}; System.out.println("Original array: " + Arrays.toString(numbers)); // Convert to List and shuffle List<Integer> list = Arrays.asList(numbers); Collections.shuffle(list); System.out.println("Shuffled array: " + Arrays.toString(numbers)); } }
We create an Integer array (note: this won't work with primitive int arrays).
Arrays.asList
creates a List view of the array. Shuffling this
list shuffles the underlying array.
The output shows the array elements in their new random order. Remember that
Arrays.asList
returns a fixed-size list backed by the array, so
structural modifications aren't allowed.
Performance Considerations
This example compares the performance of shuffling different list implementations. ArrayList and LinkedList have different shuffle performance characteristics due to their internal structures.
package com.zetcode; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Random; public class ShufflePerformance { static final int SIZE = 100000; public static void main(String[] args) { // Create lists List<Integer> arrayList = new ArrayList<>(SIZE); List<Integer> linkedList = new LinkedList<>(); Random random = new Random(); for (int i = 0; i < SIZE; i++) { int num = random.nextInt(); arrayList.add(num); linkedList.add(num); } // Time ArrayList shuffle long start = System.currentTimeMillis(); Collections.shuffle(arrayList); long duration = System.currentTimeMillis() - start; System.out.println("ArrayList shuffle time: " + duration + "ms"); // Time LinkedList shuffle start = System.currentTimeMillis(); Collections.shuffle(linkedList); duration = System.currentTimeMillis() - start; System.out.println("LinkedList shuffle time: " + duration + "ms"); } }
We populate an ArrayList and LinkedList with the same random numbers. We then
time how long Collections.shuffle
takes for each implementation.
ArrayList is generally faster due to better memory locality.
The output shows the time difference between shuffling the two list types. For large lists, ArrayList can be significantly faster. Choose your list implementation based on your application's needs.
Thread-Safe Shuffling
This example demonstrates thread-safe shuffling using synchronized wrappers. When sharing collections between threads, proper synchronization is crucial to avoid concurrent modification issues.
package com.zetcode; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class ThreadSafeShuffle { public static void main(String[] args) { List<String> unsafeList = new ArrayList<>(); Collections.addAll(unsafeList, "A", "B", "C", "D", "E"); // Create synchronized wrapper List<String> safeList = Collections.synchronizedList(unsafeList); // Shuffle safely in multi-threaded context synchronized (safeList) { Collections.shuffle(safeList); System.out.println("Shuffled safely: " + safeList); } } }
We first create a regular ArrayList, then wrap it using
Collections.synchronizedList
. To perform the shuffle safely, we
synchronize on the list object during the operation.
This ensures no other thread can modify the list during shuffling. While the synchronized wrapper provides thread-safe access, compound operations still require external synchronization.
Source
Java Collections.shuffle Documentation
In this tutorial, we've explored the Collections.shuffle
method in
depth. We've covered basic usage, custom randomness, performance considerations,
and thread safety. Shuffling is a fundamental operation for many applications.
Author
List all Java tutorials.