Java8 Stream API 实战案例——让集合操作更优雅

📅 2026/6/16 12:50:15
Java8 Stream API 实战案例——让集合操作更优雅
Java8 引入的 Stream API 是 Java 发展史上最重要的更新之一。它让集合操作从怎么做变成了做什么代码更简洁、更易读。一、Stream 是什么传统方式操作集合需要写大量 for 循环和 if 判断// 传统方式筛选出年龄大于18的用户名ListStringnamesnewArrayList();for(Useruser:userList){if(user.getAge()18){names.add(user.getName());}}用 Stream 一行搞定// Stream 方式ListStringnamesuserList.stream().filter(u-u.getAge()18).map(User::getName).collect(Collectors.toList());二、创建 Stream// 从集合创建ListStringlistArrays.asList(a,b,c);StreamStringstream1list.stream();// 从数组创建String[]arr{a,b,c};StreamStringstream2Arrays.stream(arr);// 从值创建StreamStringstream3Stream.of(a,b,c);三、常用中间操作中间操作返回的是一个新的 Stream可以链式调用。1. filter——筛选// 筛选成绩大于等于60分的学生ListStudentpassListstudents.stream().filter(s-s.getScore()60).collect(Collectors.toList());2. map——转换// 提取所有学生姓名ListStringnamesstudents.stream().map(Student::getName).collect(Collectors.toList());// 对象转字符串ListStringinfoListstudents.stream().map(s-s.getName() - s.getScore()).collect(Collectors.toList());3. distinct——去重// 获取所有不重复的班级ListStringclassesstudents.stream().map(Student::getClassName).distinct().collect(Collectors.toList());4. sorted——排序// 按成绩降序排序ListStudentsortedstudents.stream().sorted(Comparator.comparingInt(Student::getScore).reversed()).collect(Collectors.toList());// 先按班级、再按成绩排序ListStudentsorted2students.stream().sorted(Comparator.comparing(Student::getClassName).thenComparingInt(Student::getScore)).collect(Collectors.toList());5. limit / skip——分页// 跳过前10条取10条第二页ListStudentpage2students.stream().skip(10).limit(10).collect(Collectors.toList());四、常用终止操作终止操作才是真正执行计算的时候。1. forEach——遍历students.stream().filter(s-s.getScore()60).forEach(s-System.out.println(s.getName()不及格));2. count——计数longcountstudents.stream().filter(s-s.getScore()90).count();System.out.println(优秀学生人数: count);3. anyMatch / allMatch / noneMatch——匹配// 是否有不及格的学生booleanhasFailstudents.stream().anyMatch(s-s.getScore()60);// 是否全部及格booleanallPassstudents.stream().allMatch(s-s.getScore()60);// 是否没有不及格的booleannoFailstudents.stream().noneMatch(s-s.getScore()60);4. findFirst / findAny——查找// 获取第一个成绩大于90的学生OptionalStudenttopstudents.stream().filter(s-s.getScore()90).findFirst();top.ifPresent(s-System.out.println(s.getName()));五、collect——收集最常用// 1. 转为 ListListStringliststream.collect(Collectors.toList());// 2. 转为 Set自动去重SetStringsetstream.collect(Collectors.toSet());// 3. 转为 MapMapString,Integermapstudents.stream().collect(Collectors.toMap(Student::getName,// keyStudent::getScore,// value(a,b)-a// key 冲突时保留第一个));// 4. 分组统计MapString,ListStudentgroupstudents.stream().collect(Collectors.groupingBy(Student::getClassName));// 5. 分组后计数MapString,LongcountByClassstudents.stream().collect(Collectors.groupingBy(Student::getClassName,Collectors.counting()));// 6. 分组后求平均值MapString,DoubleavgByClassstudents.stream().collect(Collectors.groupingBy(Student::getClassName,Collectors.averagingInt(Student::getScore)));// 7. 拼接字符串Stringnamesstudents.stream().map(Student::getName).collect(Collectors.joining(, ));// 输出: 张三, 李四, 王五六、实战学生成绩统计DataAllArgsConstructorclassStudent{privateStringname;privateStringclassName;privateintscore;}publicclassStreamExample{publicstaticvoidmain(String[]args){ListStudentstudentsArrays.asList(newStudent(张三,大数据2301,88),newStudent(李四,大数据2301,92),newStudent(王五,大数据2302,76),newStudent(赵六,大数据2302,45),newStudent(孙七,软件2301,63));// 1. 各班级平均分System.out.println( 各班平均分 );students.stream().collect(Collectors.groupingBy(Student::getClassName,Collectors.averagingInt(Student::getScore))).forEach((c,avg)-System.out.println(c: avg));// 2. 不及格名单System.out.println(\n 不及格学生 );students.stream().filter(s-s.getScore()60).forEach(s-System.out.println(s.getName(): s.getScore()));// 3. 各班最高分System.out.println(\n 各班最高分 );students.stream().collect(Collectors.groupingBy(Student::getClassName,Collectors.maxBy(Comparator.comparingInt(Student::getScore)))).forEach((c,s)-System.out.println(c: s.get().getName()(s.get().getScore())));// 4. 按成绩排名System.out.println(\n 成绩排名 );students.stream().sorted(Comparator.comparingInt(Student::getScore).reversed()).forEach(s-System.out.println(s.getName(): s.getScore()));// 5. 成绩分布统计System.out.println(\n 成绩分布 );students.stream().collect(Collectors.groupingBy(s-{if(s.getScore()90)return优秀;if(s.getScore()80)return良好;if(s.getScore()70)return中等;if(s.getScore()60)return及格;return不及格;},Collectors.counting())).forEach((level,count)-System.out.println(level: count人));}}七、并行流——利用多核提升性能数据量大时可以用parallelStream()自动并行处理// 并行流数据量小的时候不要用反而更慢ListStringnamesstudents.parallelStream().filter(s-s.getScore()60).map(Student::getName).collect(Collectors.toList());数据量普通流并行流100条0.1ms0.3ms1万条5ms3ms100万条500ms80ms建议数据量超过 10 万条再考虑并行流。八、踩坑提醒1. Stream 只能使用一次StreamStringstreamlist.stream();stream.forEach(System.out::println);stream.filter(s-s.startsWith(A));// 报错stream 已关闭2. 不要在 forEach 中修改外部变量// 错误ListStringresultnewArrayList();list.stream().forEach(s-result.add(s));// 线程不安全// 正确ListStringresultlist.stream().collect(Collectors.toList());3. Optional 判空// 正确用法OptionalStudentoptstudents.stream().filter(s-s.getScore()90).findFirst();opt.ifPresent(s-System.out.println(s.getName()));// 不要直接用 get()Studentsopt.get();// 没有值时会抛异常总结Stream API 是现代 Java 开发的必备技能。掌握它之后你会发现自己写 for 循环的次数越来越少。记住一个原则传统 for 循环 告诉计算机怎么做 → Stream 告诉计算机要什么如果对你有帮助欢迎点赞、评论、关注【张老师技术栈】持续分享 Java/Python/爬虫 实战干货。