Stream 使用方式解释
代码背景
以下代码片段通过 Java 的 stream
流处理方式从 JSONArray
中提取所有元素的 Constants.NAME
属性,并将结果收集到一个列表中:
@Testvoid 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(node -> (String) ((JSONObject) node).get(Constants.NAME)).collect(Collectors.toList());// 输出验证System.out.println(dfname); // [df1, df2, df3]}
功能解释
-
通过流对数组中的每个元素进行处理:
- 调用了
nodes.stream()
将JSONArray
转换为一个流(Stream
)。
- 调用了
-
映射操作:
- 使用
map
方法对流中的每个元素应用转换操作,将JSONObject
的NAME
属性提取为String
。 (String) ((JSONObject) node).get(Constants.NAME)
将每个node
(原始是JSONObject
)中的Constants.NAME
对应的值提取出来并转换为String
。
- 使用
-
收集为列表:
- 使用
Collectors.toList()
将流的结果收集到一个新的List
中。
- 使用
问题说明
- 在代码中,
JSONArray
是阿里巴巴的 JSON 库(fastjson
)。 nodes
是一个JSONArray
,其stream()
方法是从父类继承的。- 每个
node
实际上是一个JSONObject
。
代码逻辑可以正常工作,但需要注意以下几点:
优化建议
-
增强代码可读性:
可以让代码更清晰:List<String> dfname = nodes.stream().map(node -> (String) ((JSONObject) node).get(Constants.NAME)).collect(Collectors.toList());
-
避免类型转换警告:
如果编译时出现类型转换警告,可以通过以下方式避免:List<String> dfname = nodes.stream().map(JSONObject.class::cast).map(json -> json.getString(Constants.NAME)).collect(Collectors.toList());
JSONObject.class::cast
将每个元素转换为JSONObject
,确保类型安全。json.getString(Constants.NAME)
是fastjson
提供的更简洁的获取字符串的方法,替代(String) json.get(...)
。
测试示例
@Testvoid 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);}
输出
[df1, df2, df3]
true
false
.collect(Collectors.toList());
和 .collect(toList());
的区别
.collect(Collectors.toList());
和 .collect(toList());
本质上是等效的。两者都用于将流中的元素收集到一个 List
中。但是,它们之间的主要区别在于 方法引用的静态导入 和 代码风格:
区别分析
1. .collect(Collectors.toList());
- 是一种完整的写法,显式地使用
Collectors.toList()
方法。 - 不需要静态导入,代码的意图更明确。
- 缺点是显得稍微冗长。
2. .collect(toList());
- 需要静态导入
java.util.stream.Collectors.toList
方法。 - 静态导入后可以省略
Collectors.
,代码更简洁。 - 依赖静态导入,可能会让代码在阅读时需要结合上下文才能清楚实际方法。
示例代码
使用 Collectors.toList()
@Test
void testWithCollectors() {List<String> list = Stream.of("A", "B", "C").collect(Collectors.toList()); // 完整写法
}
使用 toList()
(静态导入)
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()
简洁而依赖上下文。
选择具体写法时可以根据代码的风格要求、团队的熟悉程度进行选择。