9.4 Iterating with Java 8 Streams
Java Collections Framework: Iterating with Java 8 Streams
Overview of Java 8 Streams
Streams in Java 8 introduced a new, functional-style approach to processing collections of objects. A stream represents a sequence of elements that supports various methods to perform computations on data, such as filtering, mapping, and reducing, without modifying the underlying data source.
Key Features of Streams
- Functional Operations: Supports filter, map, reduce, and more.
- Lazy Evaluation: Operations on streams are only executed when necessary.
- Parallel Processing: Enables parallelism to improve performance.
Creating Streams
Streams can be created from a variety of sources, such as collections, arrays, or even custom data sources.
Example: Creating a Stream from a List
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Creating a stream from a List
Stream<String> stream = names.stream();
// Iterating through the stream
stream.forEach(System.out::println); // Output: Alice, Bob, Charlie
}
}
In this example, we create a Stream from a List and use forEach to print each element.
Common Stream Operations
1. Filtering
The filter method allows you to exclude elements that don’t match a given condition.
import java.util.Arrays;
import java.util.List;
public class FilterExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// Filter even numbers
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println); // Output: 2, 4, 6
}
}
In this example, filter is used to keep only even numbers in the stream.
2. Mapping
The map function is used to transform each element in a stream.
import java.util.Arrays;
import java.util.List;
public class MapExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Convert each name to uppercase
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println); // Output: ALICE, BOB, CHARLIE
}
}
Here, map is applied to each element, converting names to uppercase.
3. Reducing
The reduce method combines elements of a stream into a single result, often using an accumulator function.
import java.util.Arrays;
import java.util.List;
public class ReduceExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Sum of all numbers
int sum = numbers.stream()
.reduce(0, Integer::sum);
System.out.println("Sum: " + sum); // Output: Sum: 15
}
}
In this example, reduce accumulates all integers in the list to compute their sum.
Parallel Streams
Parallel streams divide tasks across multiple threads, improving performance for large datasets.
Example: Using Parallel Stream
import java.util.Arrays;
import java.util.List;
public class ParallelStreamExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Edward");
// Process stream in parallel
names.parallelStream()
.forEach(System.out::println); // Output order may vary due to parallel processing
}
}
Here, parallelStream enables concurrent processing of the stream’s elements.
Summary
- Streams allow functional-style operations on collections, enabling clean and concise code.
- Filtering, mapping, and reducing are common stream operations for data processing.
- Parallel streams provide an easy way to leverage multi-core processors.
Streams in Java 8 are a powerful tool for handling data in a functional and efficient manner, especially when working with collections.