【问题标题】:Java 8 using stream, flatMap and lambdaJava 8 使用流、flatMap 和 lambda
【发布时间】:2018-06-02 09:34:20
【问题描述】:

我有这段代码,我想返回一个邮政编码列表:

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(",")));
});

【问题讨论】:

  • first: filter(entry -> recordEntry != null) 我猜这是错误的
  • 第二:为什么要使用流?
  • 第三:编译错误是什么?
  • @AniketSahrawat 缺少返回语句是他最小的问题:-)

标签: java lambda java-8 java-stream flatmap


【解决方案1】:

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

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

这就是我将如何重写您的代码:

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());

如果你觉得更舒服的话。

【讨论】:

  • 您可以将Arrays.asList(...).stream() 替换为Arrays.stream(...)Stream.of(...)
  • @shmosel true,非常感谢您的建议。
  • 如果你更喜欢方法引用,也可以.map(Entry::getContent).map(Content::getProperties).map(Properties::getPostcodes).flatMap(Pattern.compile(",")::splitAsStream)
  • @shmosel 再次非常感谢。 :)
  • 你不需要Arrays.asList(…).stream();首先使用Arrays.stream(…) 获取流。问题清单不完整。原始代码的另一个问题是 OP 经常无法确定变量是命名为entry 还是recordEntry
猜你喜欢
  • 2015-11-22
  • 1970-01-01
  • 2015-03-04
  • 1970-01-01
  • 1970-01-01
  • 2019-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多