Stream Collectors.toList()
和 Stream.toList()
的区别
问题背景
在以下代码中:
java
@Test
void test() {
JSONArray nodes = new JSONArray();
String[] names = {"df1", "df2", "df3"};
for (String name : names) {
JSONObject obj = new JSONObject();
obj.put(Constants.NAME, name);
nodes.add(obj);
}
// 流式操作
List<String> dfname = nodes.stream()
.map(JSONObject.class::cast)
.map(json -> json.getString("name"))
.collect(Collectors.toList());
// 输出验证
System.out.println(dfname); // [df1, df2, df3]
boolean df1 = dfname.contains("df1");
boolean df2 = dfname.contains("df2222");
System.out.println(df1);
System.out.println(df2);
}
问题:是否可以将 .collect(Collectors.toList())
替换为 .toList()
?
以下对两者进行详细分析。
区别
1. Collectors.toList()
- 来源 :来自
java.util.stream.Collectors
。 - 特性 :
- 返回的是一个 可变的列表 ,通常是
ArrayList
。 - 允许修改列表内容,例如
add()
、remove()
等操作。 - 支持从 Java 8 开始。
- 返回的是一个 可变的列表 ,通常是
2. Stream.toList()
- 来源 :从 Java 16 引入的新方法,属于
java.util.stream.Stream
类。 - 特性 :
- 返回的是一个 不可变的列表 ,类似
List.of()
。 - 修改列表内容会抛出
UnsupportedOperationException
。 - 代码更简洁,不需要额外导入
Collectors
。
- 返回的是一个 不可变的列表 ,类似
区别详情
特性 | Collectors.toList() | Stream.toList() |
---|---|---|
返回的 List 类型 | 可变(例如 ArrayList ) |
不可变(ImmutableCollections.ListN ) |
Java 版本 | 从 Java 8 开始支持 | 从 Java 16 开始支持 |
修改性操作支持 | 支持,返回的 List 可以修改,如 add() 、remove() 等。 |
不支持,尝试修改会抛出 UnsupportedOperationException 。 |
依赖 Collectors | 是的,需要导入 java.util.stream.Collectors 。 |
否,不需要额外导入。 |
替换方式示例
在代码中,由于没有对返回的 List
进行修改,可以使用 toList()
:
java
@Test
void test() {
JSONArray nodes = new JSONArray();
String[] names = {"df1", "df2", "df3"};
for (String name : names) {
JSONObject obj = new JSONObject();
obj.put(Constants.NAME, name);
nodes.add(obj);
}
// 使用 toList()
List<String> dfname = nodes.stream()
.map(JSONObject.class::cast)
.map(json -> json.getString("name"))
.toList(); // 替换为 toList()
// 输出验证
System.out.println(dfname); // [df1, df2, df3]
boolean df1 = dfname.contains("df1");
boolean df2 = dfname.contains("df2222");
System.out.println(df1);
System.out.println(df2);
}
选择依据
- 如果需要返回一个可变列表 (可以
add()
或修改),应使用Collectors.toList()
。 - 如果不需要修改返回的列表 ,且代码运行在 Java 16 及以上,推荐使用
toList()
,代码更简洁且线程安全。
总结
两者在功能上没有差别(在逻辑正确的前提下),选择使用哪个取决于:
- Java 版本 :低于 Java 16 只能用
Collectors.toList()
。 - 可变性需求 :如果需要修改返回的
List
,选择Collectors.toList()
。
.collect(Collectors.toList());
和 .collect(toList());
本质上是等效的。两者都用于将流中的元素收集到一个 List
中。但是,它们之间的主要区别在于 方法引用的静态导入 和 代码风格:
区别分析
1. .collect(Collectors.toList());
- 是一种完整的写法,显式地使用
Collectors.toList()
方法。 - 不需要静态导入,代码的意图更明确。
- 缺点是显得稍微冗长。
2. .collect(toList());
- 需要静态导入
java.util.stream.Collectors.toList
方法。 - 静态导入后可以省略
Collectors.
,代码更简洁。 - 依赖静态导入,可能会让代码在阅读时需要结合上下文才能清楚实际方法。
示例代码
使用 Collectors.toList()
java
@Test
void testWithCollectors() {
List<String> list = Stream.of("A", "B", "C")
.collect(Collectors.toList()); // 完整写法
}
使用 toList()
(静态导入)
java
import static java.util.stream.Collectors.toList;
@Test
void testWithStaticImport() {
List<String> list = Stream.of("A", "B", "C")
.collect(toList()); // 静态导入方式
}
使用建议
-
明确性优先:
- 当团队中存在新手或对静态导入感到不熟悉时,推荐使用
Collectors.toList()
这种完整的形式。
- 当团队中存在新手或对静态导入感到不熟悉时,推荐使用
-
简洁性优先:
- 对于内部代码或约定明确的项目,可以使用静态导入
toList()
的形式。
- 对于内部代码或约定明确的项目,可以使用静态导入
总结
两者的功能和效果没有任何差异,主要区别在于代码的书写方式。
- 完整写法 :
Collectors.toList()
明确而冗长。 - 静态导入写法 :
toList()
简洁而依赖上下文。
选择具体写法时可以根据代码的风格要求、团队的熟悉程度进行选择。