Java 中的 IO 流 和 Stream API(java.util.stream) 虽然都叫 “流”,但本质是为了解决不同问题而设计的工具,核心区别体现在 “处理的数据对象” 和 “用途” 上。我们用更通俗的方式再梳理一次:
一、IO 流:“程序与外部的数据线”
核心定位:
处理 程序与外部资源之间的数据传输(比如文件、网络、键盘、屏幕等),相当于 “数据在程序内外流动的管道”。
具体特点:
-
数据来源 / 去向是 “外部”:比如从本地文件读数据(
FileInputStream)、往网络写数据(SocketOutputStream)、从键盘接收输入(System.in)、往屏幕输出内容(System.out)。 -
以 “字节” 或 “字符” 为单位传输:
- 字节流(
InputStream/OutputStream):传输原始字节(比如图片、视频、二进制文件),万能但需要手动处理编码(比如中文)。 - 字符流(
Reader/Writer):专门传输文本,自动处理字符编码(比如 UTF-8),更适合读小说、配置文件等文本内容。
- 字节流(
-
操作是 “读 / 写”,侧重 “搬运数据”:比如用
FileReader把文件里的字符 “搬” 到程序里,用FileWriter把程序里的字符串 “搬” 到文件里。 -
需要手动关闭:因为关联了外部资源(如文件句柄、网络连接),用完必须关闭,否则会导致资源泄漏(可以用 try-with-resources 自动关闭)。
示例:用 IO 流读一个文本文件
// 用字符流(FileReader)读文本文件(外部资源 → 程序)
try (FileReader reader = new FileReader("story.txt")) {
int c;
while ((c = reader.read()) != -1) { // 逐个字符读
System.out.print((char) c); // 输出到屏幕(程序 → 外部)
}
} catch (IOException e) {
e.printStackTrace();
}
二、Stream API(java.util.stream):“内存数据的加工流水线”
核心定位:
处理 程序内部内存中的数据(比如集合、数组里的数据),相当于 “对数据进行过滤、转换、计算的流水线”。
具体特点:
-
数据来源是 “内存内部”:比如对
List<Integer>中的数字过滤,对Set<String>中的字符串排序,处理的是已经加载到内存中的数据。 -
以 “元素” 为单位处理:操作的是集合 / 数组中的元素(比如一个
User对象、一个数字),而不是字节 / 字符。 -
操作是 “计算”,侧重 “数据加工”:提供了丰富的 “加工步骤”,比如:
- 过滤(
filter):只保留符合条件的元素(如年龄 > 18 的用户); - 转换(
map):把元素变成另一种形式(如把User转成用户名); - 聚合(
collect/sum):把处理结果汇总(如转成List或求和)。
- 过滤(
-
不需要关闭:因为只处理内存数据,不关联外部资源,用完自动释放,无需手动关闭。
示例:用 Stream API 处理集合
List<String> names = Arrays.asList("张三", "李四", "王五", "赵六");
// 流水线操作:过滤出长度为2的名字 → 转成大写 → 收集成新列表
List<String> result = names.stream()
.filter(name -> name.length() == 2) // 过滤
.map(String::toUpperCase) // 转换
.collect(Collectors.toList()); // 聚合
System.out.println(result); // 输出 [张三, 李四, 王五, 赵六](全是2个字,转大写)
三、一句话总结区别
- IO 流:管 “内外数据搬运”(比如文件→程序,程序→网络),是 “数据线”。
- Stream API:管 “内部数据加工”(比如集合过滤、计算),是 “流水线”。
两者除了名字都带 “流”,没有任何关联,解决的是完全不同的问题。
补充:
“流”(Stream)是编程中一个形象的比喻,其概念不仅存在于 Java 中,在其他语言(如 C、Python 等)中也有类似设计。我们可以从 “流的含义”“流的特点” 以及 “Java 中流的类型” 三个角度来理解:
一、为什么叫 “流”?
“流” 的命名源于对数据传输过程的抽象:想象水流从一个地方(源头)流向另一个地方(目的地),数据的传输过程与此类似 —— 数据从数据源(如文件、网络、内存)“流动” 到数据目的地(如程序、文件、显示器)。这种 “流动” 的特性让数据的处理变得连续、有序,就像水流一样 “源源不断” 地被处理,因此被形象地称为 “流”。
二、“流” 具备哪些特点?
无论哪种编程语言中的 “流”,都具备以下核心特点:
-
方向性:流是单向的,要么是 “输入流”(数据从外部流入程序,如
FileInputStream读取文件到程序),要么是 “输出流”(数据从程序流向外部,如FileOutputStream写数据到文件),不存在双向同时流动的流。 -
连续性:数据以字节或字符为单位,按顺序连续传输,处理时通常是 “读一个字节 / 字符,再读下一个”,无法像数组一样直接 “跳转到第 N 个位置”(某些流支持随机访问,如
RandomAccessFile,但这是特例)。 -
顺序性:数据的读取 / 写入顺序与它们在流中的存储顺序一致(先入先出),例如文件中先写的内容会被先读取。
-
资源关联性:流通常与底层资源绑定(如文件、网络连接、键盘 / 屏幕),使用完毕后需要关闭以释放资源(否则可能导致资源泄漏)。
-
可操作性:可以通过 “流的装饰”(如 Java 中的
BufferedInputStream包装FileInputStream)增强功能(如缓冲、编码转换),而不改变底层流的本质。
891

被折叠的 条评论
为什么被折叠?



