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()简洁而依赖上下文。
选择具体写法时可以根据代码的风格要求、团队的熟悉程度进行选择。
