当前位置: 首页 > news >正文

Stream API三巨头:filter、map、collect

我们来深入剖析 Stream API 中最核心、最常用的“三巨头”:filtermapcollect。理解了它们,你就掌握了 Stream 大半的精髓。


1. filter() - 过滤器

是什么?

filter 是一个中间操作。它就像一个大筛子或一个过滤器,用于从流中筛选出满足特定条件的元素

怎么工作?
  • 参数:它接受一个 Predicate<? super T> 函数式接口作为参数。
    • Predicate 是一个“断言函数”,它接收一个参数,返回一个 boolean 值(truefalse)。
  • 逻辑:流中的每一个元素都会被传递给 Predicatetest 方法。
    • 如果 test 方法返回 true,该元素会被保留并传递到下一个操作。
    • 如果返回 false,该元素会被过滤掉。
  • 返回值:返回一个新的 Stream<T>,包含所有被保留的元素。
代码示例
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Anna", "Edward");// 过滤出所有以字母 "A" 开头的名字
List<String> namesStartingWithA = names.stream().filter(name -> name.startsWith("A")) // Predicate: 输入name,返回boolean.collect(Collectors.toList());System.out.println(namesStartingWithA); // 输出: [Alice, Anna]// 过滤出长度大于 3 的名字
List<String> longNames = names.stream().filter(name -> name.length() > 3).collect(Collectors.toList());System.out.println(longNames); // 输出: [Alice, Charlie, David, Anna, Edward]

2. map() - 映射/转换器

是什么?

map 是一个中间操作。它就像一个加工机床,用于将流中的每个元素转换成另一个形式。它是一对一的映射,原元素会被新元素替换。

怎么工作?
  • 参数:它接受一个 Function<? super T, ? extends R> 函数式接口作为参数。
    • Function 是一个“转换函数”,它接收一个参数(类型 T),返回一个结果(类型 R)。
  • 逻辑:流中的每一个元素都会被传递给 Functionapply 方法,并将该方法的返回值(可以是任何类型)组成一个新的流。
  • 返回值:返回一个 Stream<R>,流的元素类型可能已经从 T 改变为了 R
代码示例
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 1. 将每个字符串映射为它的长度(将 String 转换为 Integer)
List<Integer> nameLengths = names.stream().map(name -> name.length()) // Function: 输入String,返回Integer.collect(Collectors.toList());
System.out.println(nameLengths); // 输出: [5, 3, 7]// 2. 将每个字符串转换为大写
List<String> upperCaseNames = names.stream().map(String::toUpperCase) // 使用方法引用,等价于 .map(s -> s.toUpperCase()).collect(Collectors.toList());
System.out.println(upperCaseNames); // 输出: [ALICE, BOB, CHARLIE]// 更复杂的例子:从对象中提取特定字段
class Person {private String name;private int age;// 省略构造方法和getter/setter
}
List<Person> people = Arrays.asList(new Person("Alice", 25),new Person("Bob", 30)
);// 将 Person 流映射为 String 流(只包含名字)
List<String> onlyNames = people.stream().map(person -> person.getName()) // 输入Person,输出String.collect(Collectors.toList());
System.out.println(onlyNames); // 输出: [Alice, Bob]// 将 Person 流映射为 Integer 流(只包含年龄)
List<Integer> onlyAges = people.stream().map(Person::getAge) // 使用方法引用.collect(Collectors.toList());
System.out.println(onlyAges); // 输出: [25, 30]

3. collect() - 收集器/终结者

是什么?

collect 是一个终结操作。它是流水线的终点站,用于将流中的元素聚合、汇总到一个容器中(如 List, Set, Map)或生成一个值。它会触发整个流的实际执行。

怎么工作?
  • 参数:它接受一个 Collector<? super T, A, R> 接口的参数。
    • 幸运的是,我们很少自己实现这个接口,而是使用 Collectors 工具类提供的各种静态工厂方法。
  • 逻辑:它根据传入的 Collector 策略,对流中的元素进行可变缩减(mutable reduction),将元素累积到一个结果容器中。
  • 返回值:返回一个类型为 R 的结果,通常是一个集合或一个值。
常用 Collectors 方法示例
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Anna", "Bob");// 1. 收集到 List (最常用)
List<String> list = names.stream().filter(name -> name.length() > 3).collect(Collectors.toList()); // 返回 ArrayList// 2. 收集到 Set (自动去重)
Set<String> set = names.stream().collect(Collectors.toSet()); // 返回 HashSet, 输出: [Alice, Bob, Charlie, David, Anna] (只有一个Bob)// 3. 收集到指定的集合类型,例如 TreeSet
TreeSet<String> treeSet = names.stream().collect(Collectors.toCollection(TreeSet::new)); // 可以指定集合的具体实现// 4. 连接字符串:将所有元素用分隔符连接起来
String joined = names.stream().collect(Collectors.joining(", ")); // 参数是分隔符
System.out.println(joined); // 输出: Alice, Bob, Charlie, David, Anna, Bob// 5. 分组:按条件分组,返回一个 Map
// 按名字的首字母分组
Map<Character, List<String>> groupByFirstLetter = names.stream().collect(Collectors.groupingBy(name -> name.charAt(0)));
System.out.println(groupByFirstLetter);
// 输出: {A=[Alice, Anna], B=[Bob, Bob], C=[Charlie], D=[David]}// 6. 分区:是分组的一种特例,按true/false分区(满足条件和不满足条件的)
// 将名字分为长度大于3和不超过3的两部分
Map<Boolean, List<String>> partitioned = names.stream().collect(Collectors.partitioningBy(name -> name.length() > 3));
System.out.println(partitioned);
// 输出: {false=[Bob, Bob], true=[Alice, Charlie, David, Anna]}

组合使用:威力无穷

真正的威力在于将它们组合成一条声明式的流水线。

任务:有一个名字列表,要求:

  1. 过滤掉长度小于等于3的。
  2. 将所有名字转换为大写。
  3. 按字母顺序排序。
  4. 收集到一个新的 ArrayList 中。
List<String> names = Arrays.asList("Chris", "Alice", "Bob", "David", "Eve");List<String> processedNames = names.stream()         // 获取流.filter(name -> name.length() > 3)          // 1. 过滤.map(String::toUpperCase)                   // 2. 转换.sorted()                                   // 3. 排序.collect(Collectors.toList());              // 4. 收集System.out.println(processedNames); // 输出: [ALICE, CHRIS, DAVID]

总结对比

方法类型目的参数返回值
filter中间操作筛选元素Predicate<T> (返回boolean)Stream<T>
map中间操作转换元素Function<T, R> (T->R)Stream<R>
collect终结操作收集元素到容器Collector<? super T, A, R>R (通常是一个集合)

记住这个流程:获取流 -> 过滤(filter) -> 转换(map) -> 收集(collect)。这个模式可以解决你日常开发中绝大部分的数据处理需求。多练习,你就会越来越习惯这种声明式的优雅编程风格。


文章转载自:

http://pTH2m633.srcth.cn
http://2OihAUwh.srcth.cn
http://aRoJGomE.srcth.cn
http://StJzRQOU.srcth.cn
http://k2oup7qN.srcth.cn
http://Iu2rD1aJ.srcth.cn
http://p1UGXP1V.srcth.cn
http://AJX4yubs.srcth.cn
http://FhNHgcc2.srcth.cn
http://77geue05.srcth.cn
http://WtshHPIh.srcth.cn
http://a9YXmEuk.srcth.cn
http://gtw44hjs.srcth.cn
http://hyciHnRR.srcth.cn
http://JpuWgK43.srcth.cn
http://dkXAHwO2.srcth.cn
http://QpGwyckW.srcth.cn
http://8rV70sAX.srcth.cn
http://f9XlYWTB.srcth.cn
http://dcz9YMth.srcth.cn
http://Xd5EQZEl.srcth.cn
http://DGivSMQT.srcth.cn
http://1TLJ1thE.srcth.cn
http://8r3bBWdK.srcth.cn
http://1i8SQkwT.srcth.cn
http://3ssUeBZf.srcth.cn
http://olMp4m7X.srcth.cn
http://hbhtqOf0.srcth.cn
http://1ZZ98ZcR.srcth.cn
http://b4rdi2SZ.srcth.cn
http://www.dtcms.com/a/372276.html

相关文章:

  • NAS可以干啥?好玩吗?
  • GDAL 在 Python 中的开发起步
  • RK3568编译linux内核遇到问题总结
  • React学习教程,从入门到精通, React 样式语法知识点与案例详解(13)
  • BiFormer注意力机制YOLOV8
  • 【算法】字符串专题
  • 谓语动词选择指南
  • JavaScript常见算法题分类
  • python---多态
  • 中兴B860AV3.2-M/B860AV3.1-M2-内存大小区分参考指南
  • 【开题答辩全过程】以 校园二手货物交易平台为例,包含答辩的问题和答案
  • 【PyTorch】图像多分类部署
  • 阿里云上启动enclave 并与宿主机通信
  • Python 多任务编程:进程、线程与协程全面解析
  • Wan系列模型解析--VACE
  • 关于学习的一些感悟
  • 如何在Python中使用正则表达式替换特定格式的文本?
  • 【正则表达式】 正则表达式断言(Assertion)是什么?
  • GD32入门到实战39--SRAM
  • [RootersCTF2019]I_<3_Flask
  • 多功能台灯设计与实现(论文+源码)
  • SpringBoot+RustFS实现高效文件存储解决方案
  • Docker04-镜像源切换
  • Python 2025:量化金融与智能交易的新纪元
  • 基于 WeKnora 构建企业级 RAG 知识库:Windows 部署与实践全解析
  • 【Android】View 的基础知识
  • FastDFS V6双IP特性及配置
  • Spring Boot常用注解-详细解析+示例
  • 使用 Doxygen 生成 C++ 与 Python 项目文档
  • 【面试题】Transformer基础原理与数学模型