Java Stream流使用案例详解
Stream流是Java 8引入的强大功能,用于以声明式方式处理集合数据,下面我将通过实际案例展示Stream流的各种用法。

基础操作案例
import java.util.*;
import java.util.stream.*;
public class StreamBasics {
public static void main(String[] args) {
// 创建一个示例数据集合
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eva", "Frank");
// 案例1:过滤出长度大于3的名字,并转换为大写
System.out.println("=== 过滤并转换 ===");
names.stream()
.filter(name -> name.length() > 3)
.map(String::toUpperCase)
.forEach(System.out::println);
// 案例2:获取前3个名字
System.out.println("\n=== 取前3个 ===");
names.stream()
.limit(3)
.forEach(System.out::println);
// 案例3:跳过前2个名字
System.out.println("\n=== 跳过前2个 ===");
names.stream()
.skip(2)
.forEach(System.out::println);
}
}
数字处理案例
import java.util.*;
import java.util.stream.*;
public class NumberStreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 案例4:过滤出偶数
System.out.println("=== 偶数 ===");
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);
// 案例5:计算所有数的和
int sum = numbers.stream()
.mapToInt(Integer::intValue)
.sum();
System.out.println("\n总和: " + sum);
// 案例6:计算平均值
OptionalDouble average = numbers.stream()
.mapToInt(Integer::intValue)
.average();
System.out.println("平均值: " + average.orElse(0));
// 案例7:找出最大值和最小值
Optional<Integer> max = numbers.stream().max(Integer::compareTo);
Optional<Integer> min = numbers.stream().min(Integer::compareTo);
System.out.println("最大值: " + max.orElse(0) + ", 最小值: " + min.orElse(0));
// 案例8:去重
List<Integer> duplicates = Arrays.asList(1, 2, 2, 3, 3, 4, 5, 5);
System.out.println("\n去重后: " +
duplicates.stream().distinct().collect(Collectors.toList()));
}
}
对象处理案例
import java.util.*;
import java.util.stream.*;
class Employee {
private String name;
private int age;
private double salary;
private String department;
public Employee(String name, int age, double salary, String department) {
this.name = name;
this.age = age;
this.salary = salary;
this.department = department;
}
// getters and setters
public String getName() { return name; }
public int getAge() { return age; }
public double getSalary() { return salary; }
public String getDepartment() { return department; }
@Override
public String toString() {
return String.format("%s (%d岁, %.2f元, %s)", name, age, salary, department);
}
}
public class ObjectStreamExample {
public static void main(String[] args) {
List<Employee> employees = Arrays.asList(
new Employee("张三", 30, 8000.0, "技术部"),
new Employee("李四", 25, 6500.0, "市场部"),
new Employee("王五", 35, 12000.0, "技术部"),
new Employee("赵六", 28, 7500.0, "财务部"),
new Employee("钱七", 40, 15000.0, "技术部"),
new Employee("孙八", 32, 9000.0, "市场部")
);
// 案例9:按部门分组
System.out.println("=== 按部门分组 ===");
Map<String, List<Employee>> byDepartment = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
byDepartment.forEach((dept, empList) -> {
System.out.println(dept + ": " + empList);
});
// 案例10:计算每个部门的平均薪资
System.out.println("\n=== 部门平均薪资 ===");
Map<String, Double> avgSalaryByDept = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.averagingDouble(Employee::getSalary)
));
avgSalaryByDept.forEach((dept, avg) ->
System.out.printf("%s: %.2f%n", dept, avg));
// 案例11:找出薪资最高的员工
System.out.println("\n=== 最高薪资员工 ===");
Optional<Employee> highestPaid = employees.stream()
.max(Comparator.comparingDouble(Employee::getSalary));
highestPaid.ifPresent(emp -> System.out.println("最高薪资: " + emp));
// 案例12:按年龄排序
System.out.println("\n=== 按年龄排序 ===");
employees.stream()
.sorted(Comparator.comparingInt(Employee::getAge))
.forEach(System.out::println);
}
}
高级操作案例
import java.util.*;
import java.util.stream.*;
public class AdvancedStreamExample {
public static void main(String[] args) {
// 案例13:flatMap - 扁平化处理
System.out.println("=== flatMap示例 ===");
List<List<String>> nestedList = Arrays.asList(
Arrays.asList("a", "b", "c"),
Arrays.asList("d", "e", "f"),
Arrays.asList("g", "h", "i")
);
List<String> flattenedList = nestedList.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println("扁平化结果: " + flattenedList);
// 案例14:reduce - 归约操作
System.out.println("\n=== reduce示例 ===");
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 求和
Optional<Integer> sum = numbers.stream()
.reduce((a, b) -> a + b);
System.out.println("求和结果: " + sum.orElse(0));
// 带初始值的求和
Integer sumWithIdentity = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println("带初始值求和: " + sumWithIdentity);
// 案例15:并行流
System.out.println("\n=== 并行流示例 ===");
long count = numbers.parallelStream()
.filter(n -> n > 2)
.count();
System.out.println("大于2的数字个数: " + count);
// 案例16:收集到特定集合
System.out.println("\n=== 收集到特定集合 ===");
List<String> words = Arrays.asList("apple", "banana", "cherry", "date");
// 收集到TreeSet(自动排序)
TreeSet<String> sortedSet = words.stream()
.collect(Collectors.toCollection(TreeSet::new));
System.out.println("TreeSet结果: " + sortedSet);
// 案例17:统计信息
System.out.println("\n=== 统计信息 ===");
IntSummaryStatistics stats = numbers.stream()
.mapToInt(Integer::intValue)
.summaryStatistics();
System.out.println("统计信息: " + stats);
System.out.println("最大值: " + stats.getMax());
System.out.println("最小值: " + stats.getMin());
System.out.println("平均值: " + stats.getAverage());
System.out.println("总数: " + stats.getCount());
// 案例18:分组并计数
System.out.println("\n=== 分组计数 ===");
List<String> items = Arrays.asList(
"apple", "banana", "apple", "orange", "banana", "apple"
);
Map<String, Long> itemCount = items.stream()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()
));
System.out.println("各元素出现次数: " + itemCount);
}
}
实际业务场景案例
import java.util.*;
import java.util.stream.*;
// 订单相关类
class Order {
private String orderId;
private String customerName;
private double amount;
private String status;
private LocalDateTime createTime;
public Order(String orderId, String customerName, double amount, String status) {
this.orderId = orderId;
this.customerName = customerName;
this.amount = amount;
this.status = status;
this.createTime = LocalDateTime.now();
}
// getters...
public String getOrderId() { return orderId; }
public String getCustomerName() { return customerName; }
public double getAmount() { return amount; }
public String getStatus() { return status; }
public LocalDateTime getCreateTime() { return createTime; }
@Override
public String toString() {
return String.format("订单[%s] %s - %.2f元 (%s)",
orderId, customerName, amount, status);
}
}
public class BusinessStreamExample {
public static void main(String[] args) {
List<Order> orders = Arrays.asList(
new Order("001", "张三", 500.0, "已完成"),
new Order("002", "李四", 1200.0, "待付款"),
new Order("003", "张三", 300.0, "已完成"),
new Order("004", "王五", 2000.0, "待发货"),
new Order("005", "张三", 800.0, "已完成"),
new Order("006", "李四", 1500.0, "已完成")
);
// 场景1:查找某个客户的所有已完成订单
System.out.println("=== 张三的已完成订单 ===");
orders.stream()
.filter(o -> "张三".equals(o.getCustomerName()))
.filter(o -> "已完成".equals(o.getStatus()))
.forEach(System.out::println);
// 场景2:计算所有已完成订单的总金额
double completedAmount = orders.stream()
.filter(o -> "已完成".equals(o.getStatus()))
.mapToDouble(Order::getAmount)
.sum();
System.out.println("\n已完成订单总金额: " + completedAmount);
// 场景3:统计每个客户的订单总金额
System.out.println("\n=== 客户订单总金额 ===");
Map<String, Double> customerTotal = orders.stream()
.collect(Collectors.groupingBy(
Order::getCustomerName,
Collectors.summingDouble(Order::getAmount)
));
customerTotal.forEach((customer, total) ->
System.out.printf("%s: %.2f元%n", customer, total));
// 场景4:找出金额最大的订单
System.out.println("\n=== 最大金额订单 ===");
Optional<Order> maxOrder = orders.stream()
.max(Comparator.comparingDouble(Order::getAmount));
maxOrder.ifPresent(order -> System.out.println("最大金额订单: " + order));
// 场景5:按状态分组并统计各状态数量
System.out.println("\n=== 各状态订单数量 ===");
Map<String, Long> statusCount = orders.stream()
.collect(Collectors.groupingBy(
Order::getStatus,
Collectors.counting()
));
statusCount.forEach((status, count) ->
System.out.printf("%s: %d个%n", status, count));
}
}
Stream流常用操作总结
| 操作 | 说明 | 示例 |
|---|---|---|
filter() |
过滤元素 | stream.filter(x -> x > 5) |
map() |
转换元素 | stream.map(String::toUpperCase) |
flatMap() |
扁平化流 | stream.flatMap(Collection::stream) |
distinct() |
去重 | stream.distinct() |
sorted() |
排序 | stream.sorted() |
limit() |
限制数量 | stream.limit(5) |
skip() |
跳过元素 | stream.skip(3) |
forEach() |
遍历 | stream.forEach(System.out::println) |
collect() |
收集结果 | stream.collect(Collectors.toList()) |
reduce() |
归约操作 | stream.reduce(0, (a,b) -> a+b) |
count() |
计数 | stream.count() |
anyMatch() |
任意匹配 | stream.anyMatch(x -> x > 0) |
allMatch() |
全部匹配 | stream.allMatch(x -> x > 0) |
noneMatch() |
无匹配 | stream.noneMatch(x -> x < 0) |
findFirst() |
找第一个 | stream.findFirst() |
findAny() |
找任意一个 | stream.findAny() |
使用建议
- 链式操作:Stream流支持链式调用,使代码更简洁易读
- 惰性求值:中间操作(如filter、map)是惰性的,只有遇到终止操作(如collect、forEach)才执行
- 并行处理:使用
parallelStream()可以利用多核CPU提高处理效率 - 避免副作用:尽量使用无状态的lambda表达式,避免在流操作中修改外部变量
- 适当使用:对于简单操作,传统循环可能更直观;复杂的数据处理则优先使用Stream流
这些案例涵盖了Stream流的大部分常用功能,通过实际代码演示了如何在Java中高效地使用Stream API处理数据集合。