news 2026/7/27 16:14:08

300. Java Stream API - 收集 Stream 元素到集合或数组(Java Stream 收集器详解)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
300. Java Stream API - 收集 Stream 元素到集合或数组(Java Stream 收集器详解)

300. Java Stream API - 收集 Stream 元素到集合或数组(Java Stream 收集器详解)

Java 的 Stream API 提供了多种方式来将流中的元素收集到集合中,比如 List、Set、数组等。你在上一节已经见识过其中的一两个例子,本节我们来深入挖掘各种实用模式及其适用场景。


🧭 在选择收集方式前,你应先思考几个关键问题:

  • 🔒 是否需要一个不可变(unmodifiable)的集合?
  • 🧺 是否需要一个具体的集合类型(如ArrayListLinkedList或自定义实现)?
  • 📏 是否能预估元素数量?(这将影响性能优化)
  • 🧩 是否需要与第三方库的集合实现兼容?

这些因素会影响你最终的收集方式选择。接下来我们逐一介绍各种场景下的典型收集方式。


🚀 1. 收集到可变ArrayList(默认方式)

这是最常用也最简单的方式:

Stream<String>strings=Stream.of("one","two","three","four");List<String>result=strings.filter(s->s.length()==3).map(String::toUpperCase).collect(Collectors.toList());System.out.println("result = "+result);

🧾 输出:

result=[ONE,TWO]

📌 特点:

  • 返回一个普通的ArrayList
  • 简洁 ✅,可变 ✅,性能中等 ⚠️(当元素数量大时,可能触发内部数组扩容)

🎯 2. 自定义集合类型或预设容量(toCollection

当你:

  • 想使用其他集合类型(如LinkedList
  • 或者你知道将要收集多少元素(可优化容量)

可使用Collectors.toCollection(...)

Stream<Integer>ints=IntStream.range(0,10_000).boxed();List<String>result=ints.map(String::valueOf).collect(Collectors.toCollection(()->newArrayList<>(10_000)));System.out.println("# result size = "+result.size());

🧠 好处:

  • 避免ArrayList多次扩容
  • 可替换为LinkedList::newCopyOnWriteArrayList::new等工厂方法

🔒 3. 收集为不可变 List(Java 10+)

✅ 使用Collectors.toUnmodifiableList()

Stream<String>strings=Stream.of("one","two","three","four");List<String>result=strings.filter(s->s.length()==3).map(String::toUpperCase).collect(Collectors.toUnmodifiableList());System.out.println("result = "+result);

📌 输出:

result=[ONE,TWO]

⚠️ 尝试修改result.add(...)会抛出UnsupportedOperationException


🚀 4. 更高效的不可变 List(Java 16+)

✅ 使用新方法.toList()

Stream<String>strings=Stream.of("one","two","three","four");List<String>result=strings.filter(s->s.length()==3).map(String::toUpperCase).toList();System.out.println("result = "+result);

📌 输出:

result=[ONE,TWO]

⚙️ 为什么更高效?

  • .collect(Collectors.toUnmodifiableList())的底层实现是:
    1. 收集到一个ArrayList
    2. 再封装为不可变集合(多了一步)
  • .toList()则更聪明:如果能预估流的长度,它会一次性分配数组空间,避免扩容与拷贝JDK 16优化)

🔢 5. 收集到数组(使用toArray

❌ 简单版(类型擦除):

Object[]result=Stream.of("a","b","c").toArray();
  • 不推荐!返回Object[],类型丢失。

✅ 推荐写法(保留数组类型):

String[]result=Stream.of("one","two","three","four").filter(s->s.length()==3).map(String::toUpperCase).toArray(String[]::new);System.out.println(Arrays.toString(result));

📌 输出:

[ONE,TWO]

🧠 背后的语法糖:

String[]::new==size->newString[size]

📝 各种收集方式总结对比表

模式返回类型可变性Java 版本适用场景说明
collect(Collectors.toList())ArrayList✅ 可变Java 8+默认收集方式,简单好用
collect(toCollection(...))任意集合类型✅ 可变Java 8+自定义集合或设置初始容量
collect(toUnmodifiableList())ImmutableList❌ 不可变Java 10+需要只读集合,防止误修改
stream.toList()ImmutableList❌ 不可变Java 16+更高效的不可变收集,推荐
toArray(String[]::new)数组✅ 可变Java 8+需要收集成固定类型数组
toArray()Object[]✅ 可变Java 8+不推荐,类型擦除
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/16 23:15:45

Glyph推理界面打不开?网页推理模式使用问题解答

Glyph推理界面打不开&#xff1f;网页推理模式使用问题解答 1. Glyph-视觉推理&#xff1a;让长文本处理更高效 你有没有遇到过这样的情况&#xff1a;想要让大模型读一篇超长文档&#xff0c;结果发现上下文长度不够&#xff0c;要么截断内容&#xff0c;要么直接报错&#…

作者头像 李华
网站建设 2026/7/15 5:43:01

GPT-OSS模型微调准备:数据格式与环境配置

GPT-OSS模型微调准备&#xff1a;数据格式与环境配置 你是否也在寻找一个高效、开源且支持本地部署的大语言模型&#xff1f;最近&#xff0c;OpenAI推出的GPT-OSS系列模型引起了广泛关注。特别是gpt-oss-20b-WEBUI这一版本&#xff0c;不仅具备强大的生成能力&#xff0c;还集…

作者头像 李华
网站建设 2026/7/25 4:08:53

如何利用标签抗体系统实现重组蛋白的高效检测与纯化?

一、为何在重组蛋白研究中需要引入标签系统&#xff1f;随着分子生物学与蛋白质组学的发展&#xff0c;对特定蛋白的功能研究日益深入。然而&#xff0c;直接研究内源性蛋白常面临表达量低、难以特异性识别与分离等挑战。为此&#xff0c;重组DNA技术应运而生&#xff0c;允许研…

作者头像 李华
网站建设 2026/7/25 12:33:32

【Matplotlib中文显示救星】:资深工程师亲授4种稳定解决方案

第一章&#xff1a;Matplotlib中文显示乱码问题的根源剖析 在使用 Matplotlib 进行数据可视化时&#xff0c;许多开发者在绘制包含中文标签或标题的图表时&#xff0c;常遇到中文显示为方框或问号的乱码现象。这一问题并非 Matplotlib 本身的缺陷&#xff0c;而是与其字体支持机…

作者头像 李华
网站建设 2026/7/24 18:17:28

aiohttp并发1000请求时崩溃?99%的人都忽略的5个关键细节

第一章&#xff1a;aiohttp并发1000请求时崩溃&#xff1f;99%的人都忽略的5个关键细节 在使用 aiohttp 进行高并发网络请求时&#xff0c;开发者常遇到程序在发起约 1000 个并发请求后崩溃或响应缓慢的问题。这通常并非 aiohttp 本身性能不足&#xff0c;而是忽略了底层异步机…

作者头像 李华