探索 Java 8 中的 Stream API
Java 8 引入了 Stream API,极大地简化了对集合(如 List、Set)的操作。Stream 提供了一种声明式的方式来处理数据,允许我们使用类似 SQL 的操作来操作集合。本文将详细介绍 Java 中的 Stream API,包括创建 Stream、常用操作符、终止操作以及实际使用示例。
1. 什么是 Stream?
Stream 是一个用于处理数据序列的抽象概念。它不存储数据,而是从数据源(如集合、数组等)按需生成数据。Stream 提供了一套丰富的操作符,可以链式调用,以一种声明式的方式处理数据。
2. 创建 Stream
Stream 可以从多种数据源创建,最常见的是从集合和数组创建。
java
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamExample {
public static void main(String[] args) {
// 从集合创建 Stream
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> streamFromList = list.stream();
// 从数组创建 Stream
String[] array = {"x", "y", "z"};
Stream<String> streamFromArray = Arrays.stream(array);
// 使用 Stream.of 创建 Stream
Stream<String> streamOf = Stream.of("1", "2", "3");
}
}
3. 中间操作
中间操作用于转换 Stream,返回一个新的 Stream。这些操作是惰性的,只有在终止操作执行时才会实际处理数据。常见的中间操作有 filter
、map
、sorted
、distinct
、limit
和 skip
。
示例:
java
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class IntermediateOperations {
public static void main(String[] args) {
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());
// 将每个数平方
List<Integer> squares = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
// 排序
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
// 去重
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println("Even numbers: " + evenNumbers);
System.out.println("Squares: " + squares);
System.out.println("Sorted numbers: " + sortedNumbers);
System.out.println("Distinct numbers: " + distinctNumbers);
}
}
4. 终止操作
终止操作用于触发 Stream 的处理,并生成一个结果。常见的终止操作有 forEach
、collect
、reduce
、count
、findFirst
、findAny
和 allMatch
等。
示例:
java
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class TerminalOperations {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// forEach 打印每个元素
numbers.stream()
.forEach(System.out::println);
// collect 收集结果为 List
List<Integer> collectedNumbers = numbers.stream()
.collect(Collectors.toList());
// reduce 求和
Optional<Integer> sum = numbers.stream()
.reduce((a, b) -> a + b);
// count 统计数量
long count = numbers.stream()
.count();
// findFirst 找到第一个元素
Optional<Integer> first = numbers.stream()
.findFirst();
// allMatch 判断是否所有元素都大于 0
boolean allGreaterThanZero = numbers.stream()
.allMatch(n -> n > 0);
System.out.println("Collected numbers: " + collectedNumbers);
sum.ifPresent(s -> System.out.println("Sum: " + s));
System.out.println("Count: " + count);
first.ifPresent(f -> System.out.println("First: " + f));
System.out.println("All greater than zero: " + allGreaterThanZero);
}
}
5. 实际示例
假设我们有一个 Employee
类,并希望通过 Stream API 处理一组员工数据。
java
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
class Employee {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
@Override
public String toString() {
return name + ": " + salary;
}
}
public class EmployeeExample {
public static void main(String[] args) {
List<Employee> employees = Arrays.asList(
new Employee("Alice", 70000),
new Employee("Bob", 80000),
new Employee("Charlie", 90000),
new Employee("David", 60000)
);
// 找到薪水最高的员工
Optional<Employee> highestPaidEmployee = employees.stream()
.max(Comparator.comparingDouble(Employee::getSalary));
highestPaidEmployee.ifPresent(emp -> System.out.println("Highest Paid Employee: " + emp));
// 找到所有薪水大于 65000 的员工
List<Employee> highEarners = employees.stream()
.filter(e -> e.getSalary() > 65000)
.collect(Collectors.toList());
System.out.println("High earners: " + highEarners);
// 计算所有员工的总薪水
double totalSalary = employees.stream()
.mapToDouble(Employee::getSalary)
.sum();
System.out.println("Total salary: " + totalSalary);
}
}
6. 总结
Stream API 是 Java 8 引入的强大工具,提供了一种声明式、链式调用的方式来处理数据。通过了解中间操作和终止操作,你可以高效地处理数据流,简化代码,提高可读性和可维护性。希望本文能帮助你更好地理解和使用 Java 中的 Stream API。