# Using Collectors for Aggregating and Reducing Collection Elements

When working with collections in Java, it is often necessary to aggregate or reduce the elements within the collection. This is where collectors come into play. Collectors provide a way to perform various operations on the elements of a collection and produce a result. In this article, we will explore how to use collectors effectively for aggregating and reducing collection elements.

## What are Collectors?

Collectors are a utility class provided by the Java Stream API that is used to perform mutable reduction operations on a stream of elements. They allow us to collect elements from a stream into various data structures or perform reductions on them.

## Aggregating Elements with Collectors

Aggregating elements involves combining the elements within a collection into a single value. Java collectors provide several methods for aggregating elements based on different criteria. Let's explore a few commonly used aggregating collectors:

### Summing Elements

If you have a collection of numerical elements and want to calculate their sum, you can use the `summingInt`, `summingLong`, or `summingDouble` collectors. These collectors sum the values of a given property for all elements in the collection.

Here's an example:

``````List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.collect(Collectors.summingInt(Integer::intValue));
System.out.println("Sum: " + sum);``````

Output: `Sum: 15`

### Averaging Elements

To find the average of a collection of numerical elements, you can use the `averagingInt`, `averagingLong`, or `averagingDouble` collectors. These collectors calculate the average of a given property for all elements in the collection.

Here's an example:

``````List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
double average = numbers.stream()
.collect(Collectors.averagingInt(Integer::intValue));
System.out.println("Average: " + average);``````

Output: `Average: 3.0`

### Getting Minimum and Maximum Elements

If you want to find the minimum or maximum element in a collection based on a certain property, you can use the `minBy` and `maxBy` collectors. These collectors return the minimum or maximum element of a given property from all elements in the collection.

Here's an example:

``````List<String> names = Arrays.asList("John", "Emily", "Michael", "Sarah");
Optional<String> minName = names.stream()
.collect(Collectors.minBy(Comparator.naturalOrder()));
System.out.println("Minimum Name: " + minName.orElse("None"));

Optional<String> maxName = names.stream()
.collect(Collectors.maxBy(Comparator.naturalOrder()));
System.out.println("Maximum Name: " + maxName.orElse("None"));``````

Output: ```Minimum Name: Emily Maximum Name: Sarah```

## Reducing Elements with Collectors

Reducing elements involves performing a reduction operation on the elements of a collection, resulting in a single value. Java collectors provide the `reducing` collector that allows you to perform custom reduction operations. Let's see an example:

Suppose we have a collection of employees, and we want to find the total salary of all employees using the reducing collector:

``````List<Employee> employees = // collection of employees

BigDecimal totalSalary = employees.stream()
.map(Employee::getSalary)
Output: `Total Salary: \$10000.00`
In the above example, we start with an initial value of `BigDecimal.ZERO` and use the addition function `BigDecimal::add` to accumulate the salaries of all employees into a single sum.