ZetCode

Java Collections.min Method

Last modified: April 20, 2025

The Collections.min method is a utility method from Java's java.util.Collections class. It returns the minimum element of a given collection according to natural ordering. The collection must implement the Comparable interface.

There are two overloaded versions of this method. One uses natural ordering, while the other accepts a Comparator for custom ordering. Both throw exceptions if the collection is empty.

Collections.min Method Overview

The min method scans the entire collection to find the smallest element. For natural ordering, elements must implement Comparable. The method throws NoSuchElementException if the collection is empty.

The version with a Comparator allows custom ordering logic. This is useful when elements don't implement Comparable or when you need different ordering than natural. Both methods have linear time complexity.

Basic Usage with Numbers

This example demonstrates the simplest usage of Collections.min with a list of numbers. Numbers implement Comparable, so they can be compared naturally. The example shows finding the minimum in a list.

MinWithNumbers.java
package com.zetcode;

import java.util.Collections;
import java.util.List;

public class MinWithNumbers {

    public static void main(String[] args) {

        List<Integer> numbers = List.of(34, 12, 56, 7, 23, 89);

        Integer min = Collections.min(numbers);

        System.out.println("Numbers: " + numbers);
        System.out.println("Minimum number: " + min);
    }
}

This code creates a list of integers and finds the smallest one using Collections.min. The natural ordering of integers is used, so 7 is correctly identified as the minimum. The output shows both the original list and the found minimum.

The example demonstrates the most straightforward case where elements implement Comparable and natural ordering is sufficient.

Finding Minimum String

Strings also implement Comparable, allowing natural ordering based on lexicographical comparison. This example finds the alphabetically first string in a collection. The comparison is case-sensitive.

MinWithStrings.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MinWithStrings {

    public static void main(String[] args) {
        
        List<String> words = new ArrayList<>();
        words.add("zebra");
        words.add("apple");
        words.add("banana");
        words.add("cherry");
        
        String minWord = Collections.min(words);
        
        System.out.println("Words: " + words);
        System.out.println("First word alphabetically: " + minWord);
    }
}

The code creates a list of strings and finds the lexicographically smallest one. "apple" is returned as it comes first in dictionary order. String comparison is based on Unicode values of characters.

Note that uppercase letters have lower Unicode values than lowercase. For case-insensitive comparison, we would need a custom Comparator.

Using Custom Comparator

This example shows how to use Collections.min with a custom Comparator. We find the shortest string in a list by comparing string lengths. The comparator defines the ordering logic.

MinWithComparator.java
package com.zetcode;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class MinWithComparator {

    public static void main(String[] args) {
        
        List<String> words = Arrays.asList(
            "elephant", "cat", "giraffe", "dog", "hippopotamus");
        
        // Comparator comparing by string length
        Comparator<String> byLength = Comparator.comparingInt(String::length);
        
        String shortest = Collections.min(words, byLength);
        
        System.out.println("Words: " + words);
        System.out.println("Shortest word: " + shortest);
    }
}

Here we use a Comparator that compares strings by their length. The min method uses this comparator to find the shortest string. "cat" and "dog" are both shortest, but "cat" appears first in the list.

This demonstrates how to customize the comparison logic when natural ordering isn't appropriate. The comparator can implement any comparison rules needed.

Finding Minimum Custom Object

For custom objects, we can either implement Comparable or provide a Comparator. This example shows both approaches with a simple Person class. We find the youngest person.

MinWithCustomObjects.java
package com.zetcode;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Person implements Comparable<Person> {
    String name;
    int age;
    
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public int compareTo(Person other) {
        return Integer.compare(this.age, other.age);
    }
    
    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

public class MinWithCustomObjects {

    public static void main(String[] args) {
        
        List<Person> people = Arrays.asList(
            new Person("Alice", 25),
            new Person("Bob", 20),
            new Person("Charlie", 30)
        );
        
        // Using natural ordering (Comparable)
        Person youngestNatural = Collections.min(people);
        System.out.println("Youngest (natural): " + youngestNatural);
        
        // Using custom Comparator
        Person youngestComparator = Collections.min(people, 
            Comparator.comparingInt(p -> p.age));
        System.out.println("Youngest (comparator): " + youngestComparator);
    }
}

The Person class implements Comparable based on age, enabling natural ordering. We demonstrate finding the youngest person using both natural ordering and a custom comparator. Both approaches yield the same result in this case.

This example shows how to work with custom objects when using Collections.min. The choice between Comparable and Comparator depends on design requirements.

Handling Empty Collection

Collections.min throws NoSuchElementException when called on an empty collection. This example demonstrates proper error handling to prevent crashes when collections might be empty.

MinWithEmptyCollection.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;

public class MinWithEmptyCollection {

    public static void main(String[] args) {
        
        List<Integer> numbers = new ArrayList<>();
        
        try {
            Integer min = Collections.min(numbers);
            System.out.println("Minimum: " + min);
        } catch (NoSuchElementException e) {
            System.out.println("Cannot find minimum in empty collection");
            System.out.println("Error: " + e.getMessage());
        }
        
        // Safe alternative with Optional
        numbers.add(42); // Add an element
        numbers.stream().min(Integer::compareTo)
            .ifPresentOrElse(
                min -> System.out.println("Minimum: " + min),
                () -> System.out.println("Collection is empty")
            );
    }
}

The example first attempts to find the minimum in an empty list, which throws an exception. We catch and handle this gracefully. Then we show a modern alternative using Stream and Optional that avoids exceptions.

Proper error handling is crucial when working with Collections.min as empty collections are common in real-world applications. The stream approach provides a more functional alternative.

Performance Considerations

Collections.min has O(n) time complexity as it must examine each element. For large collections, this might be a concern. This example compares performance with alternative approaches.

MinPerformance.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;

public class MinPerformance {

    public static void main(String[] args) {
        
        // Create large list of random numbers
        List<Integer> numbers = new ArrayList<>();
        Random random = new Random();
        IntStream.range(0, 1_000_000)
            .forEach(i -> numbers.add(random.nextInt()));
        
        // Time Collections.min
        long start = System.nanoTime();
        Integer min1 = Collections.min(numbers);
        long duration = System.nanoTime() - start;
        System.out.printf("Collections.min took %d ns%n", duration);
        
        // Time parallel stream min
        start = System.nanoTime();
        Integer min2 = numbers.parallelStream().min(Integer::compareTo).get();
        duration = System.nanoTime() - start;
        System.out.printf("Parallel stream min took %d ns%n", duration);
        
        // Verify same results
        System.out.println("Same result: " + min1.equals(min2));
    }
}

This code creates a large list of random numbers and compares the performance of Collections.min versus a parallel stream approach. The actual timings will vary, but the parallel stream might be faster for very large collections on multi-core systems.

The example demonstrates that while Collections.min is simple and effective, alternatives exist for performance-critical scenarios. Always measure performance in your specific context.

Case-Insensitive String Minimum

This final example shows how to find the minimum string ignoring case. We use a case-insensitive comparator to modify the natural ordering of strings. This is a common real-world requirement.

MinCaseInsensitive.java
package com.zetcode;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class MinCaseInsensitive {

    public static void main(String[] args) {
        
        List<String> words = Arrays.asList(
            "Zebra", "apple", "Banana", "cherry", "Date");
        
        // Case-sensitive (natural ordering)
        String minSensitive = Collections.min(words);
        System.out.println("Case-sensitive minimum: " + minSensitive);
        
        // Case-insensitive
        String minInsensitive = Collections.min(words, 
            String.CASE_INSENSITIVE_ORDER);
        System.out.println("Case-insensitive minimum: " + minInsensitive);
    }
}

The example first shows case-sensitive comparison where "Banana" is considered the minimum due to uppercase letters having lower Unicode values. Then we use String.CASE_INSENSITIVE_ORDER to find "apple" as the minimum.

This demonstrates how to leverage built-in comparators for common use cases. The case-insensitive comparator provides a clean solution without needing to write custom comparison logic.

Source

Java Collections.min Documentation

In this article, we've explored the Java Collections.min method in depth. We've covered basic usage with numbers and strings, custom comparators, performance considerations, and error handling. This method is a powerful tool for finding minimum elements in collections.

Author

My name is Jan Bodnar, and I am a dedicated programmer with many years of experience in the field. I began writing programming articles in 2007 and have since authored over 1,400 articles and eight e-books. With more than eight years of teaching experience, I am committed to sharing my knowledge and helping others master programming concepts.

List all Java tutorials.