Java Stream API实战,告别for循环

Java 8引入的Stream API让集合操作变得优雅又高效。但很多人还在用传统的for循环,或者只用了stream().collect()这一招。

今天把Stream API的常用操作从基础到高级过一遍。

基础操作

java 复制代码
List<String> names = Arrays.asList("张三", "李四", "王五", "赵六", "张三丰");

// 过滤
names.stream()
    .filter(name -> name.length() <= 2)
    .collect(Collectors.toList());
// ["张三", "李四", "王五", "赵六"]

// 转换
names.stream()
    .map(String::length)
    .collect(Collectors.toList());
// [2, 2, 2, 2, 3]

// 排序
names.stream()
    .sorted()
    .collect(Collectors.toList());

// 去重
Stream.of(1, 1, 2, 3, 3)
    .distinct()
    .collect(Collectors.toList());
// [1, 2, 3]

// 截取
IntStream.range(0, 100)
    .limit(5)
    .collect(Collectors.toList());
// [0, 1, 2, 3, 4]

// 跳过
IntStream.range(0, 10)
    .skip(5)
    .collect(Collectors.toList());
// [5, 6, 7, 8, 9]

聚合操作

java 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 求和
int sum = numbers.stream().mapToInt(Integer::intValue).sum();

// 最大/最小
Optional<Integer> max = numbers.stream().max(Integer::compareTo);
Optional<Integer> min = numbers.stream().min(Integer::compareTo);

// 计数
long count = numbers.stream().count();

// 平均
OptionalDouble avg = numbers.stream().mapToInt(Integer::intValue).average();

收集器(Collectors)

java 复制代码
List<User> users = ...;

// 转Map
Map<Long, User> userMap = users.stream()
    .collect(Collectors.toMap(User::getId, u -> u));

// 按key分组
Map<String, List<User>> groupByCity = users.stream()
    .collect(Collectors.groupingBy(User::getCity));

// 分组并计数
Map<String, Long> countByCity = users.stream()
    .collect(Collectors.groupingBy(User::getCity, Collectors.counting()));

// 拼接字符串
String names = users.stream()
    .map(User::getName)
    .collect(Collectors.joining(", "));
// "张三, 李四, 王五"

// 分区(满足条件/不满足条件)
Map<Boolean, List<User>> partition = users.stream()
    .collect(Collectors.partitioningBy(u -> u.getAge() >= 18));

实战案例

案例一:复杂数据转换

java 复制代码
// 原始数据:订单列表
List<Order> orders = ...;

// 需求:找出已支付订单中,金额最高的前5个用户的名字
List<String> result = orders.stream()
    .filter(o -> "PAID".equals(o.getStatus()))
    .sorted(Comparator.comparing(Order::getAmount).reversed())
    .limit(5)
    .map(Order::getUserName)
    .collect(Collectors.toList());

案例二:扁平化(flatMap)

java 复制代码
// 每个用户有多个地址
List<User> users = ...;

// 获取所有用户的地址(扁平化)
List<Address> allAddresses = users.stream()
    .flatMap(user -> user.getAddresses().stream())
    .collect(Collectors.toList());

// 对比:不用flatMap
List<Address> allAddresses = new ArrayList<>();
for (User user : users) {
    allAddresses.addAll(user.getAddresses());
}

案例三:并行流

java 复制代码
// 数据量大时用并行流
long count = IntStream.range(0, 1_000_000)
    .parallel()  // 开启并行
    .filter(n -> n % 2 == 0)
    .count();

// 注意:并行流不是所有场景都快
// 数据量小、操作简单、有状态操作时可能更慢

Stream vs for循环

对比 Stream for循环
可读性 链式调用,语义清晰 需要自己组织逻辑
并行化 .parallel()一行搞定 需要手写多线程
性能 大数据量并行时有优势 小数据量略快
调试 不太方便 断点调试容易
副作用 不鼓励 随意

建议:简单操作用Stream,复杂逻辑或需要调试时用for循环。


Stream API让Java的集合操作从"怎么做"变成了"做什么",代码更声明式、更易读。

建议把常用操作记下来,写代码时先想"能不能用Stream"。

相关推荐
AI你一生一世16 小时前
不止于时序存储:DolphinDB 如何成为 AI 时代的工业智能底座
java·人工智能·struts·时序数据库·工业智能·dolphindb·ai基础设施
云-缩影16 小时前
拆解 AI 图像生成应用的后端架构:ECS、OSS 和大模型 API 怎么配合
java·spring boot·后端
瑞克-桑切斯17 小时前
7、MySQL 慢查询排查与优化实战指南
java·服务器·数据库
海的透彻21 小时前
dockerfile如何快速构建容器(java服务)
java·开发语言
code2cat21 小时前
Java工具篇之Gradle:用任务图组织构建与交付
java·开发语言·单元测试·gradle
后台模板学习1 天前
大模型 Prompt 工程在电商订单系统中的踩坑记录
java·python·prompt
w_zero_one1 天前
算法--构造
java·数据结构·算法
SL_staff1 天前
制造业订单交付崩盘?用四层协同框架重建交付可信度(技术实践)
java·产品·全栈
SL_staff1 天前
打破风控迭代死循环:用决策编排重构业务与技术协作链路
java·产品·全栈
Mikko71 天前
Redis 连接数满了服务端有错误信息吗?连接数不增加却命令超时?6.2 实测连接池、超时与大 key 怎么判定
java·spring boot·redis·后端