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"。

相关推荐
用户3721574261351 小时前
Java 高效管理 Excel 批注:添加、读取、修改和删除
java
C语言小火车1 小时前
C++ 为什么越来越依赖标准库?
java·开发语言·c++
西索斯coding2 小时前
在 中接入 教程:p配置、m填写、扩展思考参数一篇就够(2)
java·前端·javascript·ai
隐退山林2 小时前
JWT令牌技术
java·开发语言·java-ee
w_zero_one2 小时前
动态规划(三)
java·算法·动态规划
木棉软糖2 小时前
JDBC 读 ResultSet 读到一半,报 stream closed
java·mysql·spring
狂奔的sherry2 小时前
JRuby 多线程反引号偶发 127:GC 提前释放了 posix_spawn 的 argv
java·linux·ruby·gc·jruby
咖啡八杯2 小时前
异常体系设计:三类策略(i18n code、message、受检异常)
java·架构·代码规范
Spatial3Ddddd2 小时前
2026空间三维重建服务商横向对比
java·服务器·人工智能