Java Collections Aggregate Operations

In this tutorial, we will explore aggregate operations in Java Collections using the Stream API. These operations include filtering, mapping, reducing, and collecting data from collections in a concise and efficient manner. We will use the latest Java version to ensure modern practices and features.

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Step-by-Step Guide
    1. Create a List of Custom Objects
    2. Filtering
    3. Mapping
    4. Reducing
    5. Collecting
  4. Complete Code Example
  5. Conclusion

Introduction

Aggregate operations in Java Collections allow for functional-style operations on streams of elements. Using the Stream API, we can perform operations like filtering, mapping, reducing, and collecting data in a declarative manner. This tutorial provides a step-by-step guide to understanding and using these operations.

Prerequisites

Before we start, ensure you have the following:

  • Java Development Kit (JDK) installed (latest version preferred)
  • An Integrated Development Environment (IDE) such as IntelliJ IDEA or Eclipse

Step-by-Step Guide

Step 1: Create a List of Custom Objects

First, let's create a custom object named Person with attributes name and age, and then create a list of Person objects with names.

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

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + '}';
    }
}

public class AggregateOperationsExample {
    public static void main(String[] args) {
        // Create a list of Person objects
        List<Person> people = new ArrayList<>();
        people.add(new Person("Ravi", 25));
        people.add(new Person("Sita", 30));
        people.add(new Person("Arjun", 22));
        people.add(new Person("Lakshmi", 20));
        people.add(new Person("Rahul", 25));
    }
}

Step 2: Filtering

Filtering allows us to select elements from a stream based on a given predicate. For example, let's filter out people older than 25.

import java.util.stream.Collectors;

public class AggregateOperationsExample {
    public static void main(String[] args) {
        // Create a list of Person objects
        List<Person> people = new ArrayList<>();
        people.add(new Person("Ravi", 25));
        people.add(new Person("Sita", 30));
        people.add(new Person("Arjun", 22));
        people.add(new Person("Lakshmi", 20));
        people.add(new Person("Rahul", 25));

        // Filter people older than 25
        List<Person> filteredPeople = people.stream()
            .filter(person -> person.getAge() > 25)
            .collect(Collectors.toList());

        System.out.println("Filtered People: " + filteredPeople);
    }
}

Step 3: Mapping

Mapping allows us to transform elements in a stream. Let's extract the names of all people in the list.

public class AggregateOperationsExample {
    public static void main(String[] args) {
        // Create a list of Person objects
        List<Person> people = new ArrayList<>();
        people.add(new Person("Ravi", 25));
        people.add(new Person("Sita", 30));
        people.add(new Person("Arjun", 22));
        people.add(new Person("Lakshmi", 20));
        people.add(new Person("Rahul", 25));

        // Extract names of all people
        List<String> names = people.stream()
            .map(Person::getName)
            .collect(Collectors.toList());

        System.out.println("Names: " + names);
    }
}

Step 4: Reducing

Reducing is a terminal operation that combines elements of a stream into a single result. Let's find the sum of the ages of all people.

public class AggregateOperationsExample {
    public static void main(String[] args) {
        // Create a list of Person objects
        List<Person> people = new ArrayList<>();
        people.add(new Person("Ravi", 25));
        people.add(new Person("Sita", 30));
        people.add(new Person("Arjun", 22));
        people.add(new Person("Lakshmi", 20));
        people.add(new Person("Rahul", 25));

        // Sum of ages of all people
        int totalAge = people.stream()
            .map(Person::getAge)
            .reduce(0, Integer::sum);

        System.out.println("Total Age: " + totalAge);
    }
}

Step 5: Collecting

Collecting is a terminal operation that transforms the elements of a stream into a different form, such as a list, set, or map. Let's group people by age.

import java.util.Map;
import java.util.stream.Collectors;

public class AggregateOperationsExample {
    public static void main(String[] args) {
        // Create a list of Person objects
        List<Person> people = new ArrayList<>();
        people.add(new Person("Ravi", 25));
        people.add(new Person("Sita", 30));
        people.add(new Person("Arjun", 22));
        people.add(new Person("Lakshmi", 20));
        people.add(new Person("Rahul", 25));

        // Group people by age
        Map<Integer, List<Person>> peopleByAge = people.stream()
            .collect(Collectors.groupingBy(Person::getAge));

        System.out.println("People grouped by age: " + peopleByAge);
    }
}

Complete Code Example

Here's the complete code example for aggregate operations in Java Collections using the Stream API:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + '}';
    }
}

public class AggregateOperationsExample {
    public static void main(String[] args) {
        // Create a list of Person objects
        List<Person> people = new ArrayList<>();
        people.add(new Person("Ravi", 25));
        people.add(new Person("Sita", 30));
        people.add(new Person("Arjun", 22));
        people.add(new Person("Lakshmi", 20));
        people.add(new Person("Rahul", 25));

        // Filter people older than 25
        List<Person> filteredPeople = people.stream()
            .filter(person -> person.getAge() > 25)
            .collect(Collectors.toList());
        System.out.println("Filtered People: " + filteredPeople);

        // Extract names of all people
        List<String> names = people.stream()
            .map(Person::getName)
            .collect(Collectors.toList());
        System.out.println("Names: " + names);

        // Sum of ages of all people
        int totalAge = people.stream()
            .map(Person::getAge)
            .reduce(0, Integer::sum);
        System.out.println("Total Age: " + totalAge);

        // Group people by age
        Map<Integer, List<Person>> peopleByAge = people.stream()
            .collect(Collectors.groupingBy(Person::getAge));
        System.out.println("People grouped by age: " + peopleByAge);
    }
}

Conclusion

In this tutorial, we demonstrated how to use aggregate operations in Java Collections using the Stream API. We covered filtering, mapping, reducing, and collecting data from collections, showcasing the power and flexibility of the Stream API. Following this guide, developers can effectively perform aggregate operations on Java Collections in their applications.

Comments