一文学会Java8新特性—Java Stream 流(java数据处理工具)使用指南|代码实战参考

张开发
2026/4/10 14:20:21 15 分钟阅读

分享文章

一文学会Java8新特性—Java Stream 流(java数据处理工具)使用指南|代码实战参考
关于Java Stream 流使用指南 一文学会Stream流用法Java Stream 流使用指南一、Stream 基础概念二、Stream 三大操作步骤1. 创建流2. 中间操作惰性求值3. 终端操作触发执行三、方法引用详解1. 类::实例方法2. 实例::方法3. 类::静态方法4. 构造方法引用四、Collectors 常用收集器五、实战案例基于以前的业务代码案例1批量提取 ID 去重案例2构建查询映射表案例3关联数据组装 VO案例4动态查询条件构建六、性能优化建议✅ 推荐做法❌ 避免做法七、最后提供大家几个注意事项八、速查表Java Stream 流使用指南一、Stream 基础概念Stream 是 Java 8 引入的数据处理工具用于对集合进行函数式操作支持链式调用代码简洁且可读性强。二、Stream 三大操作步骤1. 创建流// 从集合创建ListAppappListnewArrayList();StreamAppstreamappList.stream();// 从 Set 创建SetLonguserIdsnewHashSet();StreamLongsetStreamuserIds.stream();2. 中间操作惰性求值// map: 转换元素appList.stream().map(App::getUserId)// App - Long.map(user-user.getName());// User - String// filter: 过滤元素appList.stream().filter(app-app.getPriority()5).filter(app-HTML.equals(app.getCodeGenType()));// distinct: 去重appList.stream().map(App::getUserId).distinct();// sorted: 排序appList.stream().sorted(Comparator.comparing(App::getPriority).reversed());// limit/skip: 分页appList.stream().skip(10).limit(20);3. 终端操作触发执行// collect: 收集结果ListAppVOlistappList.stream().map(this::getAppVO).collect(Collectors.toList());SetLongsetappList.stream().map(App::getUserId).collect(Collectors.toSet());MapLong,UserVOmapuserList.stream().collect(Collectors.toMap(User::getId,userService::getUserVO));// forEach: 遍历appList.stream().forEach(System.out::println);// count: 计数longcountappList.stream().count();// findFirst/findAny: 查找OptionalAppfirstappList.stream().findFirst();// anyMatch/allMatch/noneMatch: 匹配booleanhasHighPriorityappList.stream().anyMatch(app-app.getPriority()8);上面关于User::getId - 类的方法引用和 userService::getUserVO - 实例的方法引用区别三、方法引用详解1. 类::实例方法// 等价于: user - user.getId()User::getId// 使用场景调用流元素自身的方法MapLong,StringmapuserList.stream().collect(Collectors.toMap(User::getId,User::getName));2. 实例::方法// 等价于: user - userService.getUserVO(user)userService::getUserVO// 使用场景调用某个对象的方法流元素作为参数MapLong,UserVOmapuserList.stream().collect(Collectors.toMap(User::getId,userService::getUserVO));3. 类::静态方法// 等价于: str - Integer.parseInt(str)Integer::parseIntListIntegernumbersstrings.stream().map(Integer::parseInt).collect(Collectors.toList());4. 构造方法引用// 等价于: () - new ArrayList()ArrayList::newListApplistappStream.collect(Collectors.toCollection(ArrayList::new));四、Collectors 常用收集器// 转 List.collect(Collectors.toList())// 转 Set去重.collect(Collectors.toSet())// 转 Map.collect(Collectors.toMap(User::getId,// keyuserService::getUserVO// value))// 分组.collect(Collectors.groupingBy(App::getCodeGenType))// 拼接字符串.collect(Collectors.joining(, ))// 统计.collect(Collectors.summarizingInt(App::getPriority))五、实战案例基于以前的业务代码案例1批量提取 ID 去重// 从应用列表中提取所有用户ID并去重SetLonguserIdsappList.stream().map(App::getUserId).collect(Collectors.toSet());案例2构建查询映射表// 批量查询用户并转为 Map避免 N1 问题MapLong,UserVOuserVOMapuserService.listByIds(userIds).stream().collect(Collectors.toMap(User::getId,userService::getUserVO));案例3关联数据组装 VO// 将 Entity 列表转为 VO 列表并关联用户信息ListAppVOappVOListappList.stream().map(app-{AppVOappVOgetAppVO(app);UserVOuserVOuserVOMap.get(app.getUserId());appVO.setUser(userVO);returnappVO;}).collect(Collectors.toList());案例4动态查询条件构建// 结合 QueryWrapper 进行条件过滤returnQueryWrapper.create().eq(id,id).like(appName,appName).eq(appType,appType).orderBy(sortField,ascend.equals(sortOrder));六、性能优化建议✅ 推荐做法// 1. 批量查询替代 N1 问题SetLonguserIdsappList.stream().map(App::getUserId).collect(Collectors.toSet());MapLong,UserVOuserMapuserService.listByIds(userIds).stream().collect(Collectors.toMap(User::getId,userService::getUserVO));// 2. 大集合使用 parallelStream谨慎使用largeList.parallelStream().filter(item-item.getPriority()5).collect(Collectors.toList());// 3. 提前过滤减少后续计算量appList.stream().filter(app-app.getPriority()5)// 先过滤.map(this::getAppVO)// 后转换.collect(Collectors.toList());❌ 避免做法// 1. 在循环中查询数据库N1 问题for(Appapp:appList){UseruseruserService.getById(app.getUserId());// 每次查库}// 2. 重复创建 StreamappList.stream().filter(...).collect(toList());appList.stream().map(...).collect(toList());// 3. 在不必要时使用 parallelStream小数据量反而更慢smallList.parallelStream().map(...).collect(toList());七、最后提供大家几个注意事项Stream 只能消费一次使用后需重新创建中间操作是惰性的只有终端操作才会触发执行避免在 Stream 中修改外部状态线程安全问题方法引用比 Lambda 更简洁优先使用方法引用注意空指针使用前做好 null 检查八、速查表操作类型常用方法说明转换map,flatMap元素转换/扁平化过滤filter,distinct条件过滤/去重排序sorted自然排序/自定义排序截断limit,skip限制数量/跳过匹配anyMatch,allMatch任意/全部匹配查找findFirst,findAny查找第一个/任意一个收集collect,toArray收集结果归约reduce,count归约/计数最后我个人觉得stream特性在集合数据处理、批量转换、过滤筛选、统计分析等 场景实用性很强 为java开发者在数据处理方面带来了极大效率提升。

更多文章