Java Stream 示例详解
简介
在 Java 8 中,Stream API 作为一个强大的新特性被引入,它为处理集合数据提供了一种更加简洁、高效和声明式的方式。Stream 可以让我们以函数式编程的风格对数据进行过滤、映射、归约等操作,极大地提升了代码的可读性和可维护性。本文将通过丰富的示例深入探讨 Java Stream 的基础概念、使用方法、常见实践以及最佳实践。
目录
- 基础概念
- 使用方法
- 创建 Stream
- 中间操作
- 终端操作
- 常见实践
- 过滤数据
- 映射数据
- 数据归约
- 最佳实践
- 小结
- 参考资料
基础概念
Stream 是 Java 8 引入的一种新的抽象概念,它代表了一组支持顺序和并行聚合操作的元素序列。与集合不同,Stream 本身并不存储数据,它只是对数据源(如集合、数组等)进行操作。Stream 的操作可以分为中间操作和终端操作:
- 中间操作:返回一个新的 Stream,允许链式调用多个中间操作。例如 filter
、map
等。
- 终端操作:执行 Stream 上的操作并返回结果,之后 Stream 就会被消耗,不能再被使用。例如 forEach
、collect
等。
使用方法
创建 Stream
-
从集合创建 ```java import java.util.Arrays; import java.util.List; import java.util.stream.Stream;
public class StreamExample { public static void main(String[] args) { List
numbers = Arrays.asList(1, 2, 3, 4, 5); Stream streamFromList = numbers.stream(); Stream parallelStreamFromList = numbers.parallelStream(); } } 2. **从数组创建**
java int[] intArray = {1, 2, 3, 4, 5}; IntStream streamFromArray = Arrays.stream(intArray);3. **使用 `Stream.of` 方法创建**
java StreamstreamFromString = Stream.of("apple", "banana", "cherry"); ```
中间操作
- 过滤(
filter
):根据条件过滤 Stream 中的元素。java List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); Stream<Integer> filteredStream = numbers.stream() .filter(number -> number % 2 == 0);
- 映射(
map
):将 Stream 中的每个元素映射为一个新的元素。java List<String> words = Arrays.asList("apple", "banana", "cherry"); Stream<Integer> lengthStream = words.stream() .map(String::length);
- 排序(
sorted
):对 Stream 中的元素进行排序。java List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2); Stream<Integer> sortedStream = numbers.stream() .sorted();
终端操作
- 遍历(
forEach
):对 Stream 中的每个元素执行给定的操作。java List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); numbers.stream() .forEach(System.out::println);
- 收集(
collect
):将 Stream 中的元素收集到一个集合中。java List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> evenNumbers = numbers.stream() .filter(number -> number % 2 == 0) .collect(Collectors.toList());
- 归约(
reduce
):将 Stream 中的元素归约为一个值。java List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); Optional<Integer> sum = numbers.stream() .reduce((a, b) -> a + b);
常见实践
过滤数据
假设我们有一个员工列表,需要过滤出年龄大于 30 岁的员工。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
class Employee {
private String name;
private int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class FilterEmployeeExample {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee("Alice", 25));
employees.add(new Employee("Bob", 35));
employees.add(new Employee("Charlie", 40));
List<Employee> filteredEmployees = employees.stream()
.filter(employee -> employee.getAge() > 30)
.collect(Collectors.toList());
filteredEmployees.forEach(System.out::println);
}
}
映射数据
将一个字符串列表中的每个字符串转换为大写形式。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class MapStringExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
List<String> upperCaseWords = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
upperCaseWords.forEach(System.out::println);
}
}
数据归约
计算一个整数列表的总和。
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class ReduceExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream()
.reduce((a, b) -> a + b);
sum.ifPresent(System.out::println);
}
}
最佳实践
- 避免不必要的中间操作:过多的中间操作可能会影响性能,尽量简化 Stream 操作链。
- 合理使用并行流:并行流可以提高处理大数据集的效率,但在某些情况下,顺序流可能更合适。需要根据具体情况进行性能测试。
- 使用
Optional
处理可能为空的结果:在使用终端操作(如reduce
)时,返回的结果可能为空,使用Optional
可以避免空指针异常。
小结
Java Stream API 为处理集合数据提供了一种强大而灵活的方式。通过理解基础概念、掌握使用方法以及遵循最佳实践,我们可以编写更加简洁、高效和可读的代码。Stream 的中间操作和终端操作组合可以满足各种数据处理需求,无论是过滤、映射还是归约数据。希望本文的示例和讲解能帮助读者更好地理解和应用 Java Stream。