Java 8 使用流、flatMap 和 lambda
Java 8 using stream, flatMap and lambda
我有这段代码,我想 return 邮政编码列表:
List<String> postcodes = new ArrayList<>();
List<Entry> entries = x.getEntry(); //getEntry() returns a list of Entry class
for (Entry entry : entries) {
if (entry != null) {
Properties properties = entry.getContent().getProperties();
postcodes.addAll(Arrays.asList(properties.getPostcodes().split(",")));
}
}
return postcodes;
这是我尝试使用 stream() 方法和以下链接方法的尝试:
...some other block of code
List<Entry> entries = x.getEntry.stream()
.filter(entry -> recordEntry != null)
.flatMap(entry -> {
Properties properties = recordEntry.getContent().getProperties();
postCodes.addAll(Arrays.asList(properties.getPostcodes().split(",")));
});
您的代码有几个问题,即:
postCodes.addAll
是一个 副作用 因此你应该避免这样做,否则当代码并行执行时你会收到 n确定性 结果。
flatMap
需要一个流,而不是布尔值;这是您的代码当前尝试传递给 flatMap
. 的内容
flatMap
在这种情况下使用一个函数,该函数也使用一个值和 return 返回一个值,考虑到您已经决定使用 lambda 语句块,那么您必须包含一个 return lambda 语句块中的语句将值指定为 return。在您的代码中情况并非如此。
- 流管道由终端操作驱动,这些操作将流转换为非流值,您的代码当前根本不会执行,因为您刚刚设置了成分,但实际上并未从流中请求结果。
- 您的查询的接收者类型应该是
List<String>
而不是 List<Entry>
因为在您当前的代码中调用 Arrays.asList(properties.getPostcodes().split(","))
return 是一个 List<String>
然后通过调用 addAll
. 添加到累加器
- 感谢 Holger 指出,您总是无法决定变量是命名为
entry
还是 recordEntry
。
这就是我重写您的代码的方式:
List<String> entries = x.getEntry.stream()
.filter(Objects::nonNull)
.map(Entry::getContent)
.map(Content::getProperties)
.map(Properties::getPostcodes)
.flatMap(Pattern.compile(",")::splitAsStream)
.collect(Collectors.toList());
如果认为合适,您可能希望使用 Collectors.toCollection
指定列表的特定实现 returned。
编辑:
通过 shmosel 的一些好的建议,我们实际上可以在整个流管道中使用方法引用,从而实现更好的代码意图并且更容易遵循。
或者您可以继续以下方法:
List<String> entries = x.getEntry.stream()
.filter(e -> e != null)
.flatMap(e -> Arrays.asList(
e.getContent().getProperties().getPostcodes().split(",")).stream()
)
.collect(Collectors.toList());
如果你觉得更舒服。
我有这段代码,我想 return 邮政编码列表:
List<String> postcodes = new ArrayList<>();
List<Entry> entries = x.getEntry(); //getEntry() returns a list of Entry class
for (Entry entry : entries) {
if (entry != null) {
Properties properties = entry.getContent().getProperties();
postcodes.addAll(Arrays.asList(properties.getPostcodes().split(",")));
}
}
return postcodes;
这是我尝试使用 stream() 方法和以下链接方法的尝试:
...some other block of code
List<Entry> entries = x.getEntry.stream()
.filter(entry -> recordEntry != null)
.flatMap(entry -> {
Properties properties = recordEntry.getContent().getProperties();
postCodes.addAll(Arrays.asList(properties.getPostcodes().split(",")));
});
您的代码有几个问题,即:
postCodes.addAll
是一个 副作用 因此你应该避免这样做,否则当代码并行执行时你会收到 n确定性 结果。flatMap
需要一个流,而不是布尔值;这是您的代码当前尝试传递给flatMap
. 的内容
flatMap
在这种情况下使用一个函数,该函数也使用一个值和 return 返回一个值,考虑到您已经决定使用 lambda 语句块,那么您必须包含一个 return lambda 语句块中的语句将值指定为 return。在您的代码中情况并非如此。- 流管道由终端操作驱动,这些操作将流转换为非流值,您的代码当前根本不会执行,因为您刚刚设置了成分,但实际上并未从流中请求结果。
- 您的查询的接收者类型应该是
List<String>
而不是List<Entry>
因为在您当前的代码中调用Arrays.asList(properties.getPostcodes().split(","))
return 是一个List<String>
然后通过调用addAll
. 添加到累加器
- 感谢 Holger 指出,您总是无法决定变量是命名为
entry
还是recordEntry
。
这就是我重写您的代码的方式:
List<String> entries = x.getEntry.stream()
.filter(Objects::nonNull)
.map(Entry::getContent)
.map(Content::getProperties)
.map(Properties::getPostcodes)
.flatMap(Pattern.compile(",")::splitAsStream)
.collect(Collectors.toList());
如果认为合适,您可能希望使用 Collectors.toCollection
指定列表的特定实现 returned。
编辑:
通过 shmosel 的一些好的建议,我们实际上可以在整个流管道中使用方法引用,从而实现更好的代码意图并且更容易遵循。
或者您可以继续以下方法:
List<String> entries = x.getEntry.stream()
.filter(e -> e != null)
.flatMap(e -> Arrays.asList(
e.getContent().getProperties().getPostcodes().split(",")).stream()
)
.collect(Collectors.toList());
如果你觉得更舒服。