Java 8使用stream,flatMap和lambda

问题描述 投票:2回答:1

我有这段代码,我想返回一个postCodes列表:

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(",")));
});
java lambda java-8 java-stream flatmap
1个回答
5
投票

你的代码有几个问题,即:

  1. postCodes.addAll是副作用,因此你应该避免这样做,否则当代码并行执行时,你会收到不确定的结果。
  2. flatMap期待一个流,而不是布尔值;这是您的代码目前尝试传递给flatMap的内容。
  3. 在这种情况下,flatMap使用一个也消耗一个值并返回一个值的函数,并且考虑到你决定使用一个lambda语句块,那么你必须在lambda语句块中包含一个return语句,指定要返回的值。在您的代码中不是这种情况。
  4. 流管道由终端操作驱动,终端操作是将流转换为非流值的操作,而您的代码当前根本不会执行,因为您只是设置了成分但实际上没有从流中请求结果。
  5. 您的查询的接收器类型应该是List<String>而不是List<Entry>,因为在您当前的代码中,对Arrays.asList(properties.getPostcodes().split(","))的调用返回一个List<String>,然后您将调用addAll添加到累加器中。
  6. 感谢Holger指出它,你经常无法确定变量是否被命名为entryrecordEntry

这就是说我是如何重写你的代码的:

List<String> entries = x.getEntry.stream()
        .filter(Objects::nonNull)
        .map(Entry::getContent)
        .map(Content::getProperties)
        .map(Properties::getPostcodes‌)
        .flatMap(Pattern.co‌mpile(",")::splitAsS‌tream)
        .collect(Collectors.toList());

如果认为合适,您可能希望使用Collectors.toCollection指定返回列表的特定实现。

编辑:

通过shmosel的一些好建议,我们实际上可以在整个流管道中使用方法引用,从而实现更好的代码意图,并且更容易遵循。

或者你可以继续这种方法:

List<String> entries = x.getEntry.stream()
       .filter(e -> e != null)
       .flatMap(e -> Arrays.asList(
         e.getContent().getProperties().getPostcodes().split(",")).stream()
       )
       .collect(Collectors.toList());

如果它对你来说更舒服

© www.soinside.com 2019 - 2024. All rights reserved.