news 2026/6/26 8:13:31

Java的Stream流

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java的Stream流

目录

1.什么是Stream

Stream的特点

2.Stream流vs传统集合操作

3.创建Stream流

4.Stream常用方法

4.1中间方法

过滤操作

排序操作

限制和跳过元素

去重操作

映射操作

流合并

关键点总结

4.2 终结方法

1.foreach

2.count统计个数

3.max/min 最大/最小值

4.3 收集方法


Stream是Java 8引入的一套新的API,用于处理集合数据的函数式编程风格操作。它让集合操作变得更简洁、高效,并支持并行处理

1.什么是Stream

Stream是一种高级迭代器,用于对数据源进行函数式操作。

Stream的特点

1. 不存储数据:Stream本身不存储数据,数据来自数据源

2. 函数式操作:支持lambda表达式和函数式编程

3. 延迟执行:中间操作都是延迟执行的

4. 可消费性:Stream只能被消费一次

2.Stream流vs传统集合操作

现在有一个装有String的列表["Tom", "Jerry", "Alice"],我要把Alice全部大写并且放到新的列表当中去,应该怎么办?

传统方式:

// 传统集合操作 List<String> names = Arrays.asList("Tom", "Jerry", "Alice"); List<String> result = new ArrayList<>(); for (String name : names) { if (name.startsWith("A")) { result.add(name.toUpperCase()); } }

Stream流操作:

// Stream操作 List<String> result1 = names.stream() .filter(name -> name.startsWith("A")) .map(String::toUpperCase) .collect(Collectors.toList());

结果都是一样的[ALICE]

3.创建Stream流

详情看代码:

//1.获取集合的stream流 List<String> list = new ArrayList<>(); Stream<String> stream1 = list.stream(); //2.获取Map的stream流 Map<String,String> map=new HashMap<>(); //获取键流 Stream<String> stream2 = map.keySet().stream(); //获取值流 Stream<String> stream3 = map.values().stream(); //获取键值对流 Stream<Map.Entry<String, String>> stream4 = map.entrySet().stream(); //3.获取数组的stream流 Integer[] arr={1,2,3,4,5,6,7,8,9}; Stream<Integer> stream5 = Arrays.stream(arr); Stream<Integer> stream6 = Stream.of(arr);

4.Stream常用方法

4.1中间方法

中间方法的意思是,调用完它们之后,返回的是一个新的流,可以进行用中间方法对其进行操作,所以它支持链式编辑。

package com.qbcy; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; public class Demo2 { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("张无忌"); list.add("周芷若"); list.add("赵敏"); list.add("张强"); list.add("张三丰"); list.add("张翠山"); //1.过滤方法 list.stream().filter(s -> s.startsWith("张")&&s.length()==3) .forEach(s -> System.out.println(s)); //2.排序方法 List<Double> list1 = new ArrayList<>(); list1.add(1.2); list1.add(4.3); list1.add(4.3); list1.add(4.3); list1.add(3.2); list1.add(2.1); list1.stream().sorted().forEach(s -> System.out.print(s+" ")); System.out.println(); //降序排列 list1.stream().sorted((s1,s2)->Double.compare(s2,s1)).forEach(s -> System.out.print(s+" ")); System.out.println(); //获取降序排列后的前两个元素 limit list1.stream().sorted((s1,s2)->Double.compare(s2,s1)).limit(2).forEach(s -> System.out.print(s+" ")); System.out.println(); //跳过前两个元素 skip list1.stream().sorted((s1,s2)->Double.compare(s2,s1)).skip(2).forEach(s -> System.out.print(s+" ")); System.out.println(); //去重 distinct //如果希望能去重,则需要重写hashCode和equals方法 list1.stream().distinct().forEach(s -> System.out.print(s+" ")); System.out.println(); //映射方法:把流上面的元素拿出来变成新的元素再放到新流中 list1.stream().map(s -> "加10后:"+(s+10)).forEach(System.out::println); //合并流,把两个流接起来 Stream<Object> res=Stream.concat(list.stream(),list1.stream()); System.out.println("-----------合并后的流-----------"); res.forEach(System.out::println); } }

过滤操作

使用filter方法筛选出以"张"开头且长度为3的字符串:

list.stream().filter(s -> s.startsWith("张")&&s.length()==3) .forEach(s -> System.out.println(s));

排序操作

Double类型列表进行升序和降序排列:

// 升序 list1.stream().sorted().forEach(s -> System.out.print(s+" ")); // 降序 list1.stream().sorted((s1,s2)->Double.compare(s2,s1)).forEach(s -> System.out.print(s+" "));

限制和跳过元素

使用limit获取前两个元素,skip跳过前两个元素:

// 获取前两个 list1.stream().sorted((s1,s2)->Double.compare(s2,s1)).limit(2).forEach(s -> System.out.print(s+" ")); // 跳过前两个 list1.stream().sorted((s1,s2)->Double.compare(s2,s1)).skip(2).forEach(s -> System.out.print(s+" "));

去重操作

使用distinct去除重复元素:

list1.stream().distinct().forEach(s -> System.out.print(s+" "));

映射操作

通过map将每个元素转换为新格式:

list1.stream().map(s -> "加10后:"+(s+10)).forEach(System.out::println);

流合并

使用Stream.concat合并两个流:

Stream<Object> res=Stream.concat(list.stream(),list1.stream()); res.forEach(System.out::println);

关键点总结

  • filter用于条件筛选
  • sorted支持自然排序和自定义比较器
  • limitskip控制元素数量
  • distinct依赖equalshashCode实现去重
  • map实现元素转换
  • Stream.concat可合并多个流

4.2 终结方法

一旦调用终结方法,这个流就不能再使用了

首先创建Teacher类

package com.qbcy; /** * 创建Teacher类 */ public class Teacher { private String name; private int age; private String sex; public Teacher() { } public Teacher(String name, int age, String sex) { this.name = name; this.age = age; this.sex = sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "Teacher [name=" + name + ", age=" + age + ", sex=" + sex + "]"; } }

1.foreach

package com.qbcy; import java.util.ArrayList; import java.util.List; /** * 终结方法 */ public class Demo3 { public static void main(String[] args) { List<Teacher> list = new ArrayList<>(); list.add(new Teacher("张三", 18, "男")); list.add(new Teacher("张三丰", 50, "男")); list.add(new Teacher("张无忌", 20, "男")); list.add(new Teacher("周芷若", 18, "女")); list.add(new Teacher("赵敏", 16, "女")); list.add(new Teacher("张翠山", 40, "男")); //forEach 遍历过滤后的数据 list.stream().filter(t->t.getAge()>30).forEach(System.out::println); } }

这里把年龄大于30的教师过滤出来,使用forEach遍历输出:

2.count统计个数

Long tCount=list.stream().filter(t->t.getAge()>30).count(); System.out.println("30岁以上的教师数量为:"+tCount);

3.max/min 最大/最小值

//max 返回最大值 放到了 Optional 容器里面 ,这个容器里面能记住值value Optional<Teacher> res=list.stream().max((t1, t2)->Double.compare(t1.getAge(),t2.getAge())); Teacher maxAgeTeacher= res.get(); System.out.println("最大年龄的教师为:"+maxAgeTeacher); System.out.println("-------------------------------"); //min 返回最小值 放到了 Optional 容器里面 ,这个容器里面能记住值value Optional<Teacher> res1=list.stream().min((t1, t2)->Double.compare(t1.getAge(),t2.getAge())); Teacher minAgeTeacher= res1.get(); System.out.println("最小年龄的教师为:"+minAgeTeacher); System.out.println("-------------------------------");

4.3 收集方法

package com.qbcy; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; public class Demo1 { //获取Stream流 public static void main(String[] args) { //1.获取集合的stream流 List<String> list = new ArrayList<>(); //赋值 list.add("张三"); list.add("李四"); list.add("王五"); //过滤 Stream<String> streamList=list.stream().filter(s->s.startsWith("张")); List<String> resList= streamList.collect(Collectors.toList()); System.out.println(resList); System.out.println("--------------------------------------------------"); //2.获取Map的stream流 Map<String,String> map=new HashMap<>(); //赋值 map.put("1","张三"); map.put("2","张三"); map.put("3","张三"); map.put("4","张三"); //获取键流 Stream<String> streamKeys = map.keySet().stream(); List<String> resKeys= streamKeys.collect(Collectors.toList()); System.out.println(resKeys); System.out.println("--------------------------------------------------"); //获取值流 Stream<String> stream3 = map.values().stream(); List<String> resValues= stream3.collect(Collectors.toList()); System.out.println(resValues); System.out.println("--------------------------------------------------"); //获取键值对流 Stream<Map.Entry<String, String>> stream4 = map.entrySet().stream(); List<Map.Entry<String, String>> resEntry= stream4.collect(Collectors.toList()); Map<String, String> resMap= resEntry.stream().collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue)); System.out.println(resMap); System.out.println(resEntry); System.out.println("--------------------------------------------------"); //3.获取数组的stream流 Integer[] arr={1,2,3,4,5,6,7,8,9}; Stream<Integer> stream5 = Arrays.stream(arr); Stream<Integer> stream6 = Stream.of(arr); List<Integer> resArr= stream5.collect(Collectors.toList()); System.out.println(resArr); System.out.println("--------------------------------------------------"); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/25 14:14:55

4.2 X-Ray 视角透视 Agent:用 Langfuse 追踪、调试与优化你的 AI 应用

X-Ray 视角透视 Agent:用 Langfuse 追踪、调试与优化你的 AI 应用 导语:在上一章,我们建立了评估体系的“理论大厦”。但理论需要工具来落地。如果说开发 AI 应用像是在造一架精密的飞机,那么没有追踪和可观测性工具,就相当于在没有仪表盘和黑匣子的情况下“盲飞”。这无疑…

作者头像 李华
网站建设 2026/6/25 15:34:58

4.5 AI 世界的“防火墙”:从零构建 LLM 攻击实时检测系统

4.5 AI 世界的“防火墙”:从零构建 LLM 攻击实时检测系统 导语:我们已经构建了功能强大、可观测、可评估的 AI Agent。但我们是否忽略了一个致命的“阿喀琉斯之踵”——安全?当你的 Agent 能够调用 API、访问数据库、甚至执行代码时,它就从一个信息处理器,变成了一个拥有“…

作者头像 李华
网站建设 2026/6/26 5:18:41

【dz-1003】基于太阳能供电的园林远程监控系统

摘要 随着园林管理现代化进程的加快&#xff0c;精准把控园林土壤及环境状况对提升植物成活率、降低养护成本具有重要意义。传统的园林管理模式依赖人工巡检&#xff0c;不仅存在响应滞后、劳动强度大的问题&#xff0c;还因人为判断差异导致管理标准不统一&#xff0c;难以满…

作者头像 李华
网站建设 2026/6/25 12:45:55

4.4 线上vs离线:使用 Langfuse 实现智能体的全方位无死角评估

线上vs离线:使用 Langfuse 实现智能体的全方位无死角评估 导语:我们已经学会了用 Langfuse 收集 AI 应用的“痕迹”(Traces)。现在,是时候从这些痕迹中“断案”了——也就是进行评估。评估是连接“可观测性”和“持续优化”的桥梁。在本章中,我们将深入 Langfuse 的核心评…

作者头像 李华
网站建设 2026/6/25 3:38:08

allure报告中附件无法显示问题排查

如果 allure.attach 附加的图片无法查看&#xff0c;可能的原因和排查方法如下&#xff1a;一、图片数据格式错误原因 附加的图片数据不是有效的图片格式&#xff08;如 PNG、JPG&#xff09;。 数据可能是损坏的或被错误编码&#xff08;如二进制数据未被正确处理&#xff09;…

作者头像 李华
网站建设 2026/6/25 9:02:26

微模块机房在中小企业的应用前景:从“奢侈品”到“新基建标配”

在很长一段时间里&#xff0c;微模块机房&#xff08;Micro Modular Data Center, MMDC&#xff09;被视为大型金融、电信或互联网企业的专属方案——高集成、高可靠、高成本。然而&#xff0c;随着产品形态下沉、交付模式创新以及中小企业数字化需求的爆发&#xff0c;微模块正…

作者头像 李华