Collections Utility Methods in Java – Complete Guide

Overview

The java.util.Collections class provides static methods that operate on or return collections. These utility methods include sorting, searching, shuffling, and synchronization wrappers.

Sorting Methods

sort() - Natural Ordering

import java.util.*; public class SortExamples { public static void main(String[] args) { // Sorting List with natural ordering List<String> names = new ArrayList<>(); names.add("John"); names.add("Alice"); names.add("Bob"); names.add("Diana"); System.out.println("Original: " + names); Collections.sort(names); System.out.println("Sorted (natural): " + names); // Sorting integers List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9); System.out.println("Original numbers: " + numbers); Collections.sort(numbers); System.out.println("Sorted numbers: " + numbers); // Sorting with custom comparator List<String> customSort = new ArrayList<>(names); Collections.sort(customSort, Collections.reverseOrder()); System.out.println("Reverse order: " + customSort); // Case-insensitive sorting List<String> mixedCase = Arrays.asList("apple", "Banana", "cherry", "Date"); Collections.sort(mixedCase, String.CASE_INSENSITIVE_ORDER); System.out.println("Case-insensitive sort: " + mixedCase); } }

sort() with Custom Comparator

import java.util.*; class Employee { String name; int age; double salary; public Employee(String name, int age, double salary) { this.name = name; this.age = age; this.salary = salary; } @Override public String toString() { return name + " (" + age + ", $" + salary + ")"; } } public class CustomSorting { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee("John", 30, 50000), new Employee("Alice", 25, 60000), new Employee("Bob", 35, 45000), new Employee("Diana", 28, 70000) ); // Sort by age List<Employee> byAge = new ArrayList<>(employees); Collections.sort(byAge, (e1, e2) -> e1.age - e2.age); System.out.println("Sorted by age: " + byAge); // Sort by salary (descending) List<Employee> bySalary = new ArrayList<>(employees); Collections.sort(bySalary, (e1, e2) -> Double.compare(e2.salary, e1.salary)); System.out.println("Sorted by salary (desc): " + bySalary); // Sort by name List<Employee> byName = new ArrayList<>(employees); Collections.sort(byName, (e1, e2) -> e1.name.compareTo(e2.name)); System.out.println("Sorted by name: " + byName); // Using Comparator.comparing (Java 8+) List<Employee> byAgeModern = new ArrayList<>(employees); Collections.sort(byAgeModern, Comparator.comparing(emp -> emp.age)); System.out.println("Sorted by age (modern): " + byAgeModern); } }

Searching Methods

binarySearch()

import java.util.*; public class BinarySearchExamples { public static void main(String[] args) { // Binary search on sorted list List<Integer> numbers = Arrays.asList(1, 3, 5, 7, 9, 11, 13, 15); System.out.println("List: " + numbers); int index = Collections.binarySearch(numbers, 7); System.out.println("Index of 7: " + index); index = Collections.binarySearch(numbers, 8); System.out.println("Index of 8: " + index); // Negative = not found // Binary search with custom comparator List<String> names = Arrays.asList("Alice", "Bob", "Diana", "John"); Collections.sort(names); index = Collections.binarySearch(names, "Diana"); System.out.println("Index of 'Diana': " + index); // Case-insensitive binary search List<String> mixedCase = Arrays.asList("apple", "Banana", "cherry", "Date"); Collections.sort(mixedCase, String.CASE_INSENSITIVE_ORDER); index = Collections.binarySearch(mixedCase, "BANANA", String.CASE_INSENSITIVE_ORDER); System.out.println("Index of 'BANANA' (case-insensitive): " + index); // Binary search on custom objects List<Employee> employees = Arrays.asList( new Employee("John", 30, 50000), new Employee("Alice", 25, 60000), new Employee("Bob", 35, 45000) ); Collections.sort(employees, Comparator.comparing(emp -> emp.name)); Employee searchKey = new Employee("Alice", 0, 0); index = Collections.binarySearch(employees, searchKey, Comparator.comparing(emp -> emp.name)); System.out.println("Index of Alice: " + index); } }

Shuffling and Reordering

shuffle()

import java.util.*; public class ShuffleExamples { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); System.out.println("Original: " + numbers); // Shuffle with default randomness Collections.shuffle(numbers); System.out.println("Shuffled: " + numbers); // Shuffle with specific Random object (for reproducible results) List<Integer> reproducible = new ArrayList<>(numbers); Random random = new Random(42); // Fixed seed Collections.shuffle(reproducible, random); System.out.println("Shuffled with seed: " + reproducible); // Multiple shuffles List<String> cards = Arrays.asList("A♠", "K♠", "Q♠", "J♠", "10♠"); System.out.println("\nCards original: " + cards); for (int i = 1; i <= 3; i++) { Collections.shuffle(cards); System.out.println("Shuffle " + i + ": " + cards); } } }

reverse()

import java.util.*; public class ReverseExamples { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); System.out.println("Original: " + numbers); Collections.reverse(numbers); System.out.println("Reversed: " + numbers); // Reverse a string list List<String> words = Arrays.asList("Hello", "World", "Java", "Collections"); System.out.println("\nOriginal words: " + words); Collections.reverse(words); System.out.println("Reversed words: " + words); // Reverse and then reverse back Collections.reverse(words); System.out.println("Back to original: " + words); } }

rotate()

import java.util.*; public class RotateExamples { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); System.out.println("Original: " + numbers); // Rotate right by 2 positions Collections.rotate(numbers, 2); System.out.println("Rotated right by 2: " + numbers); // Rotate left by 3 positions (negative distance) Collections.rotate(numbers, -3); System.out.println("Rotated left by 3: " + numbers); // Practical example - rotating a task list List<String> tasks = Arrays.asList("Task1", "Task2", "Task3", "Task4", "Task5"); System.out.println("\nTask list: " + tasks); // Move completed task to end Collections.rotate(tasks, -1); System.out.println("After completing first task: " + tasks); } }

swap()

import java.util.*; public class SwapExamples { public static void main(String[] args) { List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Diana"); System.out.println("Original: " + names); // Swap elements at positions 1 and 3 Collections.swap(names, 1, 3); System.out.println("After swapping 1 and 3: " + names); // Multiple swaps List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); System.out.println("\nNumbers: " + numbers); Collections.swap(numbers, 0, numbers.size() - 1); // Swap first and last System.out.println("After swapping first and last: " + numbers); // Bubble sort style swapping (educational) if (numbers.get(0) > numbers.get(1)) { Collections.swap(numbers, 0, 1); } System.out.println("After conditional swap: " + numbers); } }

Frequency and Statistics

frequency()

import java.util.*; public class FrequencyExamples { public static void main(String[] args) { List<String> words = Arrays.asList("apple", "banana", "apple", "cherry", "banana", "apple", "date"); System.out.println("Word list: " + words); int appleCount = Collections.frequency(words, "apple"); int bananaCount = Collections.frequency(words, "banana"); int orangeCount = Collections.frequency(words, "orange"); System.out.println("Frequency of 'apple': " + appleCount); System.out.println("Frequency of 'banana': " + bananaCount); System.out.println("Frequency of 'orange': " + orangeCount); // Using with custom objects List<Employee> employees = Arrays.asList( new Employee("John", 30, 50000), new Employee("Alice", 25, 60000), new Employee("John", 35, 45000), new Employee("Alice", 28, 70000) ); Employee searchEmployee = new Employee("John", 0, 0); int johnCount = Collections.frequency(employees, searchEmployee); System.out.println("\nFrequency of John: " + johnCount); // 0 - needs equals/hashCode // Better approach for custom objects long aliceCount = employees.stream() .filter(emp -> "Alice".equals(emp.name)) .count(); System.out.println("Count of Alice: " + aliceCount); } }

min() and max()

import java.util.*; public class MinMaxExamples { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9, 3, 7); System.out.println("Numbers: " + numbers); Integer min = Collections.min(numbers); Integer max = Collections.max(numbers); System.out.println("Min: " + min); System.out.println("Max: " + max); // With custom comparator List<String> words = Arrays.asList("apple", "Banana", "cherry", "Date"); String minNatural = Collections.min(words); String minCaseInsensitive = Collections.min(words, String.CASE_INSENSITIVE_ORDER); System.out.println("\nWords: " + words); System.out.println("Min (natural): " + minNatural); System.out.println("Min (case-insensitive): " + minCaseInsensitive); // With custom objects List<Employee> employees = Arrays.asList( new Employee("John", 30, 50000), new Employee("Alice", 25, 60000), new Employee("Bob", 35, 45000) ); Employee youngest = Collections.min(employees, Comparator.comparing(emp -> emp.age)); Employee highestPaid = Collections.max(employees, Comparator.comparing(emp -> emp.salary)); System.out.println("\nYoungest employee: " + youngest); System.out.println("Highest paid employee: " + highestPaid); } }

Synchronization Wrappers

Synchronized Collections

import java.util.*; public class SynchronizedCollections { public static void main(String[] args) throws InterruptedException { // Create synchronized wrappers List<String> syncList = Collections.synchronizedList(new ArrayList<>()); Set<Integer> syncSet = Collections.synchronizedSet(new HashSet<>()); Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>()); // Thread-safe operations Runnable listWriter = () -> { for (int i = 0; i < 1000; i++) { syncList.add("Item-" + i); } }; Runnable setWriter = () -> { for (int i = 0; i < 1000; i++) { syncSet.add(i); } }; // Start multiple threads Thread t1 = new Thread(listWriter); Thread t2 = new Thread(listWriter); Thread t3 = new Thread(setWriter); Thread t4 = new Thread(setWriter); t1.start(); t2.start(); t3.start(); t4.start(); t1.join(); t2.join(); t3.join(); t4.join(); System.out.println("SyncList size: " + syncList.size()); System.out.println("SyncSet size: " + syncSet.size()); // Important: When iterating, you must synchronize manually synchronized(syncList) { Iterator<String> it = syncList.iterator(); while (it.hasNext()) { // Safe iteration String item = it.next(); } } } }

Unmodifiable Collections

import java.util.*; public class UnmodifiableCollections { public static void main(String[] args) { List<String> originalList = new ArrayList<>(Arrays.asList("A", "B", "C")); Set<Integer> originalSet = new HashSet<>(Arrays.asList(1, 2, 3)); Map<String, Integer> originalMap = new HashMap<>(); originalMap.put("One", 1); originalMap.put("Two", 2); // Create unmodifiable views List<String> unmodifiableList = Collections.unmodifiableList(originalList); Set<Integer> unmodifiableSet = Collections.unmodifiableSet(originalSet); Map<String, Integer> unmodifiableMap = Collections.unmodifiableMap(originalMap); System.out.println("Unmodifiable list: " + unmodifiableList); System.out.println("Unmodifiable set: " + unmodifiableSet); System.out.println("Unmodifiable map: " + unmodifiableMap); // These operations will throw UnsupportedOperationException try { unmodifiableList.add("D"); // Throws exception } catch (UnsupportedOperationException e) { System.out.println("Cannot modify unmodifiable list"); } try { unmodifiableSet.remove(1); // Throws exception } catch (UnsupportedOperationException e) { System.out.println("Cannot modify unmodifiable set"); } // But original collections can still be modified originalList.add("D"); originalSet.add(4); originalMap.put("Three", 3); System.out.println("After modifying originals:"); System.out.println("Unmodifiable list: " + unmodifiableList); System.out.println("Unmodifiable set: " + unmodifiableSet); System.out.println("Unmodifiable map: " + unmodifiableMap); } }

Fill and Copy Operations

fill()

import java.util.*; public class FillExamples { public static void main(String[] args) { // Fill a list with same value List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E")); System.out.println("Original: " + list); Collections.fill(list, "X"); System.out.println("After fill with 'X': " + list); // Fill an array Integer[] numbers = new Integer[5]; Arrays.fill(numbers, 42); System.out.println("Filled array: " + Arrays.toString(numbers)); // Practical example - resetting values List<Boolean> flags = new ArrayList<>(Collections.nCopies(10, false)); System.out.println("Initial flags: " + flags); Collections.fill(flags, true); System.out.println("All flags true: " + flags); } }

copy()

import java.util.*; public class CopyExamples { public static void main(String[] args) { // Copy from source to destination List<String> source = Arrays.asList("A", "B", "C", "D", "E"); List<String> dest = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5")); System.out.println("Source: " + source); System.out.println("Destination before copy: " + dest); Collections.copy(dest, source); System.out.println("Destination after copy: " + dest); // What happens with different sizes List<String> smallDest = new ArrayList<>(Arrays.asList("1", "2", "3")); try { Collections.copy(smallDest, source); // Throws IndexOutOfBoundsException } catch (IndexOutOfBoundsException e) { System.out.println("Cannot copy - destination too small"); } List<String> largeDest = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5", "6", "7")); System.out.println("\nLarge destination before: " + largeDest); Collections.copy(largeDest, source); System.out.println("Large destination after: " + largeDest); } }

nCopies() and singleton Methods

nCopies()

import java.util.*; public class NCopiesExamples { public static void main(String[] args) { // Create immutable list with n copies List<String> copies = Collections.nCopies(5, "Hello"); System.out.println("nCopies result: " + copies); // The list is immutable try { copies.add("World"); // Throws UnsupportedOperationException } catch (UnsupportedOperationException e) { System.out.println("nCopies list is immutable"); } // Practical uses List<String> initialList = new ArrayList<>(Collections.nCopies(10, "")); System.out.println("Initialized list: " + initialList); // Initialize with default values List<Integer> defaultNumbers = new ArrayList<>(Collections.nCopies(8, 0)); System.out.println("Default numbers: " + defaultNumbers); } }

singleton Methods

import java.util.*; public class SingletonExamples { public static void main(String[] args) { // Create singleton collections Set<String> singletonSet = Collections.singleton("Unique"); List<Integer> singletonList = Collections.singletonList(42); Map<String, String> singletonMap = Collections.singletonMap("key", "value"); System.out.println("Singleton set: " + singletonSet); System.out.println("Singleton list: " + singletonList); System.out.println("Singleton map: " + singletonMap); // All are immutable try { singletonSet.add("Another"); // Throws exception } catch (UnsupportedOperationException e) { System.out.println("Singleton collections are immutable"); } // Practical use - removing single element List<String> names = new ArrayList<>(Arrays.asList("John", "Alice", "Bob", "Alice")); System.out.println("Before remove: " + names); names.removeAll(Collections.singleton("Alice")); System.out.println("After removing all 'Alice': " + names); } }

Checked Collections (Type Safety)

checkedCollection(), checkedList(), checkedSet(), checkedMap()

import java.util.*; public class CheckedCollections { public static void main(String[] args) { // Create type-safe collections List<String> safeList = Collections.checkedList(new ArrayList<>(), String.class); Set<Integer> safeSet = Collections.checkedSet(new HashSet<>(), Integer.class); Map<String, Integer> safeMap = Collections.checkedMap(new HashMap<>(), String.class, Integer.class); // These work fine safeList.add("Hello"); safeSet.add(42); safeMap.put("Count", 100); System.out.println("Safe collections: " + safeList + ", " + safeSet + ", " + safeMap); // This would throw ClassCastException at the point of insertion try { // safeList.add(42); // Compile error if types are known } catch (Exception e) { System.out.println("Type violation caught: " + e); } // More realistic example with raw types List rawList = new ArrayList(); List<String> checkedList = Collections.checkedList(rawList, String.class); rawList.add("Valid"); // OK try { rawList.add(42); // Throws ClassCastException immediately } catch (ClassCastException e) { System.out.println("Caught type violation: " + e.getMessage()); } } }

Empty Collections

emptyList(), emptySet(), emptyMap()

import java.util.*; public class EmptyCollections { public static void main(String[] args) { // Get immutable empty collections List<String> emptyList = Collections.emptyList(); Set<Integer> emptySet = Collections.emptySet(); Map<String, Object> emptyMap = Collections.emptyMap(); System.out.println("Empty list: " + emptyList); System.out.println("Empty set: " + emptySet); System.out.println("Empty map: " + emptyMap); // All are immutable try { emptyList.add("Something"); // Throws exception } catch (UnsupportedOperationException e) { System.out.println("Empty collections are immutable"); } // Practical use - return empty collections instead of null List<String> searchResults = searchDatabase("query"); System.out.println("Search results: " + searchResults); } // Good practice: return empty collection instead of null public static List<String> searchDatabase(String query) { if (query == null || query.trim().isEmpty()) { return Collections.emptyList(); // Better than returning null } // Actual search logic return Arrays.asList("Result1", "Result2"); } }

Disjoint and AddAll

disjoint()

import java.util.*; public class DisjointExamples { public static void main(String[] args) { List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5); List<Integer> list2 = Arrays.asList(6, 7, 8, 9, 10); List<Integer> list3 = Arrays.asList(5, 6, 7, 8, 9); System.out.println("List1: " + list1); System.out.println("List2: " + list2); System.out.println("List3: " + list3); boolean disjoint1 = Collections.disjoint(list1, list2); boolean disjoint2 = Collections.disjoint(list1, list3); System.out.println("List1 and List2 are disjoint: " + disjoint1); System.out.println("List1 and List3 are disjoint: " + disjoint2); // Practical use - checking for common elements List<String> userRoles = Arrays.asList("admin", "user", "editor"); List<String> requiredRoles = Arrays.asList("admin", "superuser"); if (!Collections.disjoint(userRoles, requiredRoles)) { System.out.println("User has at least one required role"); } else { System.out.println("User has none of the required roles"); } } }

addAll()

import java.util.*; public class AddAllExamples { public static void main(String[] args) { List<String> list = new ArrayList<>(); // Add multiple elements at once boolean changed = Collections.addAll(list, "A", "B", "C", "D", "E"); System.out.println("Collection changed: " + changed); System.out.println("List after addAll: " + list); // Add from array String[] moreElements = {"F", "G", "H"}; Collections.addAll(list, moreElements); System.out.println("After adding array: " + list); // Compared to List.addAll() List<String> anotherList = new ArrayList<>(); anotherList.addAll(Arrays.asList("X", "Y", "Z")); System.out.println("Using List.addAll(): " + anotherList); // Collections.addAll is more flexible Set<Integer> numberSet = new HashSet<>(); Collections.addAll(numberSet, 1, 2, 3, 2, 1); // Duplicates will be removed System.out.println("Number set: " + numberSet); } }

Replacement Operations

replaceAll()

import java.util.*; public class ReplaceAllExamples { public static void main(String[] args) { List<String> words = new ArrayList<>( Arrays.asList("apple", "banana", "cherry", "apple", "date") ); System.out.println("Original: " + words); // Replace all occurrences boolean replaced = Collections.replaceAll(words, "apple", "orange"); System.out.println("Replacements made: " + replaced); System.out.println("After replaceAll: " + words); // No replacements if oldValue not found replaced = Collections.replaceAll(words, "grape", "pear"); System.out.println("Replacements made: " + replaced); System.out.println("After trying to replace grape: " + words); // Case-sensitive replacement List<String> mixedCase = Arrays.asList("Apple", "apple", "APPLE", "banana"); System.out.println("\nMixed case: " + mixedCase); Collections.replaceAll(mixedCase, "apple", "orange"); System.out.println("After case-sensitive replace: " + mixedCase); } }

Performance Tips and Best Practices

import java.util.*; public class CollectionsBestPractices { public static void main(String[] args) { // 1. Use appropriate collections List<String> arrayList = new ArrayList<>(); // Random access List<String> linkedList = new LinkedList<>(); // Frequent insertions/deletions // 2. Prefer interface types List<Integer> numbers = new ArrayList<>(); Set<String> uniqueNames = new HashSet<>(); Map<String, Integer> wordCount = new HashMap<>(); // 3. Use utility methods for common operations List<String> list = Arrays.asList("A", "B", "C"); Collections.sort(list); Collections.reverse(list); Collections.shuffle(list); // 4. Use unmodifiable collections for constants final List<String> CONSTANTS = Collections.unmodifiableList( Arrays.asList("CONST1", "CONST2", "CONST3") ); // 5. Use empty collections instead of null public List<String> getResults() { return results.isEmpty() ? Collections.emptyList() : new ArrayList<>(results); } // 6. Use synchronized wrappers for thread safety List<String> threadSafeList = Collections.synchronizedList(new ArrayList<>()); // 7. Use checked collections for runtime type safety List<String> typeSafeList = Collections.checkedList(new ArrayList<>(), String.class); // 8. Use singleton collections for single elements set.removeAll(Collections.singleton("remove-me")); } }

The Collections utility class is one of the most powerful and frequently used classes in Java, providing essential algorithms and wrappers that make working with collections much easier and safer.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper