【问题标题】:Why is this usage of Stream::flatMap wrong?为什么 Stream::flatMap 的这种用法是错误的?
【发布时间】:2015-12-07 17:32:44
【问题描述】:

我希望能够像这样使用 Stream::flatMap

public static List<String> duplicate(String s) {

    List<String> l = new ArrayList<String>();
    l.add(s);
    l.add(s);

    return l;
}


listOfStrings.stream().flatMap(str -> duplicate(str)).collect(Collectors.toList());

但我得到以下编译器错误

Test.java:25:错误:不兼容的类型:无法推断类型变量 R listOfStrings.stream().flatMap(str -> duplicate(str)).collect(Collectors.toList());

(参数不匹配;lambda 表达式中的返回类型错误 列表无法转换为流)
其中 R,T 是类型变量: R 扩展了在方法 flatMap(Function>) 中声明的对象 T 扩展接口 Stream 中声明的 Object

在 scala 中,我可以做我认为等效的事情

scala> List(1,2,3).flatMap(duplicate(_))
res0: List[Int] = List(1, 1, 2, 2, 3, 3)

为什么在 java 中这不是 flatMap 的有效用法?

【问题讨论】:

标签: java java-8 java-stream flatmap


【解决方案1】:

flatMap 中的 lambda 表达式需要返回一个 Stream,从 flatMap 的参数可以看出,它的类型为 Function&lt;? super T, ? extends Stream&lt;? extends R&gt;&gt;

以下代码将编译并运行良好:

listOfStrings.stream()
             .flatMap(str -> duplicate(str).stream()) // note the .stream() here
             .collect(Collectors.toList());

因为 lambda 表达式 str -&gt; duplicate(str).stream() 的类型为 Function&lt;String, Stream&lt;String&gt;&gt;

【讨论】:

  • &lt;R&gt; Stream&lt;R&gt; map(Function&lt;? super T,? extends R&gt; mapper) 的返回类型相同。为什么 map 不需要 .stream() 而 flatmap 需要?
【解决方案2】:

如果您想多次复制流中的每个对象,则无需为此额外浪费内存ArrayList。有几种更短、更快的替代方案。

  • 使用Stream.generate 生成新流,然后对其进行限制:

    listOfStrings.stream()
                 .flatMap(str -> Stream.generate(() -> str).limit(2))
                 .collect(Collectors.toList());
    
  • 通过IntStream.range生成数字序列并将它们映射到同一个字符串:

    listOfStrings.stream()
                 .flatMap(str -> IntStream.range(0, 2).mapToObj(i -> str))
                 .collect(Collectors.toList());
    
  • 使用好旧的Collections.nCopies

    listOfStrings.stream()
                 .flatMap(str -> Collections.nCopies(2, str).stream())
                 .collect(Collectors.toList());
    

如果你确定你总是准确地复制两次,那么有最短的替代方案:

listOfStrings.stream()
             .flatMap(str -> Stream.of(str, str))
             .collect(Collectors.toList());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2014-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 2021-10-01
    相关资源
    最近更新 更多