Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Reducing Streams

Header Image

Ahoy there, mateys! If ye be lookin’ to learn about stream processing in Java, then ye have come to the right place. In our previous articles, we have covered topics like creating streams, filtering streams, and mapping streams. In this article, we will dive into the exciting world of stream reduction operations.

Using Reduction Operations on Streams

As ye may know, streams are a sequence of elements that can be processed in parallel or sequentially. One of the most common operations that ye may perform on streams is reducing them to a single value. This is where reduction operations come into play.

Reduction operations take a stream of elements and reduce them to a single value. These operations are also known as terminal operations, as they produce a result that can no longer be processed further.

Reduction operations are commonly used for tasks like finding the sum, maximum, or minimum value of a stream. Java provides several reduction operations, including reduce(), collect(), and count(), among others.

Using the reduce() Operation

The reduce() operation takes a stream of elements and reduces them to a single value by applying a binary operator to each element in the stream. The binary operator takes two operands and produces a result.

Here’s an example of using the reduce() operation to find the sum of a stream of integers:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
System.out.println(sum); // Output: 15

In this example, we first create a list of integers and then create a stream from it. We then use the reduce() operation to find the sum of the integers in the stream. The reduce() operation takes an initial value of 0 and a binary operator that adds two integers together. The binary operator is applied to each element in the stream, and the result is the sum of all the integers in the stream.

Using the collect() Operation

The collect() operation is another type of reduction operation that collects the elements in a stream into a collection, such as a list, set, or map. The collect() operation takes a Collector object that specifies how to collect the elements in the stream.

Here’s an example of using the collect() operation to collect the even numbers in a stream into a list:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
System.out.println(evenNumbers); // Output: [2, 4]

In this example, we first create a list of integers and then create a stream from it. We then use the filter() operation to filter out the odd numbers in the stream. Finally, we use the collect() operation to collect the even numbers into a list.

Using the count() Operation

The count() operation is a special type of reduction operation that counts the number of elements in a stream. The count() operation returns a long value that represents the number of elements in the stream.

Here’s an example of using the count() operation to count the number of elements in a stream:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
long count = numbers.stream().count();
System.out.println(count); // Output: 5

In this example, we first create a list of integers and then create astream from it. We then use the count() operation to count the number of elements in the stream, which is 5.

Aggregate Operations on Streams

Now that we’ve covered reduction operations, let’s take a look at aggregate operations on streams. Aggregate operations are a group of stream operations that allow ye to perform complex computations on streams.

Aggregate operations include operations like min(), max(), and average(), among others. These operations can be used to find the minimum, maximum, or average value of a stream, respectively.

Using the min() and max() Operations

The min() and max() operations are used to find the minimum and maximum value of a stream, respectively. These operations take a Comparator object that is used to compare the elements in the stream.

Here’s an example of using the min() and max() operations to find the minimum and maximum values in a stream of integers:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int min = numbers.stream().min(Integer::compareTo).orElse(0);
int max = numbers.stream().max(Integer::compareTo).orElse(0);
System.out.println(min); // Output: 1
System.out.println(max); // Output: 5

In this example, we first create a list of integers and then create a stream from it. We then use the min() and max() operations to find the minimum and maximum values in the stream, respectively. The Comparator used in this example is the Integer::compareTo method reference.

Using the average() Operation

The average() operation is used to find the average value of a stream of numeric elements. This operation returns a Double value that represents the average value of the stream.

Here’s an example of using the average() operation to find the average value of a stream of integers:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
double average = numbers.stream().mapToInt(Integer::intValue).average().orElse(0.0);
System.out.println(average); // Output: 3.0

In this example, we first create a list of integers and then create a stream from it. We then use the mapToInt() operation to convert the stream of integers to a stream of int values. Finally, we use the average() operation to find the average value of the stream.

Conclusion

Ye have now learned about reduction operations and aggregate operations on streams in Java. These operations allow ye to perform complex computations on streams of elements. In our next article, we will cover collecting streams, where ye will learn how to collect the elements in a stream into a collection. Until then, keep sailing the seas of Java!

Aggregate Operations on Streams

In addition to reduction operations, Java also provides aggregate operations on streams. Aggregate operations are high-level operations that perform a sequence of operations on a stream.

Aggregate operations include operations like filter(), map(), and flatMap(). These operations are also known as intermediate operations, as they produce a new stream that can be processed further.

Using the filter() Operation

The filter() operation takes a stream of elements and filters out elements that do not satisfy a given predicate. The predicate is a boolean-valued function that takes an element and returns a boolean value.

Here’s an example of using the filter() operation to filter out the odd numbers in a stream:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
System.out.println(evenNumbers); // Output: [2, 4]

In this example, we first create a list of integers and then create a stream from it. We then use the filter() operation to filter out the odd numbers in the stream. Finally, we use the collect() operation to collect the even numbers into a list.

Using the map() Operation

The map() operation takes a stream of elements and maps each element to a new value using a given function. The function takes an element and returns a new value.

Here’s an example of using the map() operation to convert a stream of strings to uppercase:

List<String> words = Arrays.asList("hello", "world", "java");
List<String> uppercaseWords = words.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(uppercaseWords); // Output: [HELLO, WORLD, JAVA]

In this example, we first create a list of strings and then create a stream from it. We then use the map() operation to convert each string to uppercase. Finally, we use the collect() operation to collect the uppercase strings into a list.

Using the flatMap() Operation

The flatMap() operation takes a stream of elements and maps each element to a new stream using a given function. The function takes an element and returns a new stream.

Here’s an example of using the flatMap() operation to flatten a stream of lists:

List<List<Integer>> numbers = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6));
List<Integer> flattenedNumbers = numbers.stream().flatMap(Collection::stream).collect(Collectors.toList());
System.out.println(flattenedNumbers); // Output: [1, 2, 3, 4, 5, 6]

In this example, we first create a list of lists of integers and then create a stream from it. We then use the flatMap() operation to flatten the stream of lists into a single stream of integers. Finally, we use the collect() operation to collect the flattened integers into a list.

Conclusion

That’s all for this article, me hearties! In this article, we have covered reduction operations and aggregate operations on streams. Reduction operations take a stream of elements and reduce them to a single value, while aggregate operations perform a sequence of operations on a stream. By using these operations, ye can process streams of data efficiently and effectively in yer Java code. Happy stream processing!