Java 8’s Collectors Class with Practical Examples

2 min read

Java 8’s Collectors Class with Practical Examples

Java 8 introduced the java.util.stream.Collectors class, which provides a collection of utility methods for performing mutable reduction operations on elements of a stream. This feature enables developers to process and manipulate data streams in a functional and readable way. The Collectors class is a key part of the Stream API and offers various methods to collect data in different forms, such as List, Set, Map, or even custom containers.

This article will dive into the practical uses of Collectors with examples.

What is a Collector?

A Collector is an interface in the Stream API that acts as a bridge between a stream and its final result. It transforms elements of a stream into a desired data structure or performs operations like grouping, partitioning, and joining.

The Collectors utility class provides several pre-built implementations of the Collector interface to simplify common tasks.

Commonly Used Methods in Collectors Class

  1. toList(): Converts elements in the stream into a List.
  2. toSet(): Converts elements in the stream into a Set.
  3. toMap(): Converts elements in the stream into a Map.
  4. groupingBy(): Groups elements by a classifier function.
  5. partitioningBy(): Partitions elements into two groups based on a predicate.
  6. joining(): Concatenates elements into a single String.
  7. summarizingInt/Double/Long(): Generates summary statistics for numeric data.
  8. reducing(): Performs a custom reduction operation.

Example Use Cases

1. Collecting to a List

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class CollectorExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Alice");

        // Collecting names into a List
        List<String> nameList = names.stream()
                                     .collect(Collectors.toList());

        System.out.println(nameList); // Output: [Alice, Bob, Charlie, Alice]
    }
}

2. Grouping by a Property

import java.util.*;
import java.util.stream.Collectors;

class Employee {
    String name;
    String department;

    Employee(String name, String department) {
        this.name = name;
        this.department = department;
    }
}

public class CollectorExample {
    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
            new Employee("Alice", "HR"),
            new Employee("Bob", "Finance"),
            new Employee("Charlie", "HR"),
            new Employee("David", "IT")
        );

        // Group employees by department
        Map<String, List<Employee>> employeesByDept = employees.stream()
                .collect(Collectors.groupingBy(e -> e.department));

        employeesByDept.forEach((dept, empList) -> {
            System.out.println(dept + ": " + empList.stream()
                                                   .map(emp -> emp.name)
                                                   .collect(Collectors.joining(", ")));
        });
        // Output:
        // HR: Alice, Charlie
        // Finance: Bob
        // IT: David
    }
}

3. Partitioning by a Condition

public class CollectorExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);

        // Partition numbers into even and odd
        Map<Boolean, List<Integer>> partitioned = numbers.stream()
                .collect(Collectors.partitioningBy(num -> num % 2 == 0));

        System.out.println("Even Numbers: " + partitioned.get(true)); // [2, 4, 6, 8]
        System.out.println("Odd Numbers: " + partitioned.get(false)); // [1, 3, 5, 7]
    }
}

4. Summarizing Data

import java.util.IntSummaryStatistics;
import java.util.Arrays;

public class CollectorExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(3, 5, 7, 9, 11);

        // Get summary statistics
        IntSummaryStatistics stats = numbers.stream()
                .collect(Collectors.summarizingInt(num -> num));

        System.out.println("Count: " + stats.getCount());
        System.out.println("Sum: " + stats.getSum());
        System.out.println("Min: " + stats.getMin());
        System.out.println("Max: " + stats.getMax());
        System.out.println("Average: " + stats.getAverage());
    }
}

5. Custom Reduction

import java.util.Arrays;
import java.util.Optional;

public class CollectorExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // Custom reduction to calculate product
        Optional<Integer> product = numbers.stream()
                .collect(Collectors.reducing((a, b) -> a * b));

        System.out.println(product.orElse(0)); // Output: 120
    }
}

Conclusion

The Collectors class in Java 8 is a treasure trove for developers working with streams. It simplifies complex data processing tasks, turning potentially verbose code into clean and expressive one-liners. From grouping and partitioning to summarizing and custom reduction, the possibilities with Collectors are vast.

🤞 Never miss a story from us, get weekly updates to your inbox!