In Java 8, the Stream API was introduced, which provides a powerful and expressive way to process data in a functional programming style. Streams allow you to perform operations on collections of data with a focus on declarative code and parallelism. Here are some key points about streams in Java 8:
- Stream Creation: Streams can be created from various data sources, including collections, arrays, I/O channels, or even dynamically generated data. You can obtain a stream from a collection using the
stream()method or from an array usingArrays.stream(). - Intermediate and Terminal Operations: Streams support two types of operations: intermediate and terminal operations. Intermediate operations transform the stream and return a new stream, allowing for chaining multiple operations together. Terminal operations produce a result or a side effect, and they are typically the final operation in a stream pipeline.
- Lazy Evaluation: Streams employ lazy evaluation, which means the operations are only performed when necessary. Intermediate operations are not executed until a terminal operation is invoked, which allows for more efficient processing of large or infinite data sets.
- Functional Operations: Streams provide a rich set of functional-style operations to perform various transformations and computations on data. Some common operations include
filter,map,reduce,collect,sorted,distinct,limit, andskip. These operations can be combined and chained to create complex data processing pipelines. - Parallelism: The Stream API supports parallel execution, enabling the processing of streams in parallel on multi-core systems. Parallel streams can significantly improve the performance of certain operations, especially when dealing with large data sets. You can create a parallel stream by invoking the
parallelStream()method instead ofstream(). - Data Source Independence: Streams provide a uniform API regardless of the data source. Whether you are processing a collection, an array, or any other data source, the operations and patterns remain consistent, making it easier to work with different types of data.
Here’s a simple example that demonstrates the usage of streams in Java 8:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // Example: Filter even numbers and calculate their sum int sum = numbers.stream() .filter(n -> n % 2 == 0) .mapToInt(Integer::intValue) .sum(); System.out.println("Sum of even numbers: " + sum); // Output: 30 } } |
In this example, we create a list of integers and then create a stream from it using the stream() method. We apply a series of operations on the stream, including filter to retain only even numbers, mapToInt to convert each number to its primitive int value, and sum to calculate the sum of the resulting numbers.
The output demonstrates the sum of the even numbers in the list. This example showcases the power and simplicity of streams in Java 8 for data processing and transformation.
Here are some commonly used operations on streams in Java 8, along with examples:
- Filter: The
filteroperation allows you to selectively keep elements from a stream based on a specified condition.
|
1 2 3 4 5 |
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); List<Integer> evenNumbers = numbers.stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList()); System.out.println(evenNumbers); // Output: [2, 4, 6, 8, 10] |
- Map: The
mapoperation applies a transformation to each element of a stream, producing a new stream of transformed elements.
|
1 2 3 4 5 |
List<String> names = Arrays.asList("John", "Jane", "Adam", "Eve"); List<Integer> nameLengths = names.stream() .map(String::length) .collect(Collectors.toList()); System.out.println(nameLengths); // Output: [4, 4, 4, 3] |
- Reduce: The
reduceoperation combines the elements of a stream into a single result by repeatedly applying a binary operation.
|
1 2 3 4 |
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); int sum = numbers.stream() .reduce(0, Integer::sum); System.out.println(sum); // Output: 15 |
- Collect: The
collectoperation accumulates the elements of a stream into a mutable result container, such as a List or Set.
|
1 2 3 4 |
List<String> names = Arrays.asList("John", "Jane", "Adam", "Eve"); Set<String> uniqueNames = names.stream() .collect(Collectors.toSet()); System.out.println(uniqueNames); // Output: [John, Jane, Adam, Eve] |
- Distinct: The
distinctoperation returns a stream with unique elements, eliminating duplicates.
|
1 2 3 4 5 |
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5); List<Integer> distinctNumbers = numbers.stream() .distinct() .collect(Collectors.toList()); System.out.println(distinctNumbers); // Output: [1, 2, 3, 4, 5] |
- Sort: The
sortedoperation sorts the elements of a stream in natural order or based on a specified comparator.
|
1 2 3 4 5 |
List<String> names = Arrays.asList("John", "Jane", "Adam", "Eve"); List<String> sortedNames = names.stream() .sorted() .collect(Collectors.toList()); System.out.println(sortedNames); // Output: [Adam, Eve, Jane, John] |
- Limit: The
limitoperation returns a stream consisting of the firstnelements from the original stream.
|
1 2 3 4 5 |
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> limitedNumbers = numbers.stream() .limit(3) .collect(Collectors.toList()); System.out.println(limitedNumbers); // Output: [1, 2, 3] |
- Skip: The
skipoperation discards the firstnelements from a stream and returns the remaining elements.
|
1 2 3 4 5 |
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> skippedNumbers = numbers.stream() .skip(2) .collect(Collectors.toList()); System.out.println(skippedNumbers); // Output |
These are just a few examples of the operations available on streams in Java 8. Streams provide a rich set of operations that can be combined and chained together to perform powerful data transformations and computations in a concise and expressive manner.
