将 Lambda 应用于返回另一个列表的列表的 Java 8 惯用方法?
Posted
技术标签:
【中文标题】将 Lambda 应用于返回另一个列表的列表的 Java 8 惯用方法?【英文标题】:Java 8 idiomatic way to apply a Lambda to a List returning another List? 【发布时间】:2014-11-30 01:46:34 【问题描述】:将 lambda 应用于列表中的每个项目并返回由结果组成的列表的最惯用机制是什么?
例如:
List<Integer> listA = ... imagine some initialization code here ...
List<Integer> listB = listA.apply(a -> a * a); // pseudo-code (there is no "apply")
/* listB now contains the square of every value in listA */
我检查了 API javadocs 并查看了 Apache Commons,但没有找到任何东西。
【问题讨论】:
【参考方案1】:您可以将Stream
与map
和collect
一起使用:
listB = listA.stream()
.map (a -> a*a)
.collect (Collectors.toList());
【讨论】:
【参考方案2】:要添加到@Eran 的答案,我有一个辅助方法:
public static <T, R> List<R> apply(Collection<T> coll, Function<? super T, ? extends R> mapper)
return coll.stream().map(mapper).collect(Collectors.toList());
可以用作:
List<Integer> listB = apply(listA, a -> a * a);
(注意:需要 Java 1.8 或更高版本。)
【讨论】:
这很适合作为集合的默认方法。 如果您想应用多个映射操作,这将非常低效。 @CodeConfident 您可以使用andThen
组合多个函数,然后再将它们传递给此方法。
@PeterLawrey - 同意,并且我同意您提供了问题的内容。我只是想向您的 API 客户强调这一点。
@PeterLawrey - 我认为这是 Java 也很幸运,而不是说 Kotlin,因为 apply(list, fn)
语法不利于嵌套 apply(apply(apply(list, f1), f2), f3);
。在 Kotlin 中,您可能会提供 list.apply(fn)
语法,这更有可能引发低效的调用链 list.apply(f1).apply(f2).apply(f3);
【参考方案3】:
最标准的方式是在末尾加上collect them:
List<Integer> listA = ... imagine some initialization code here ...
List<String> listB = listA.stream()
.map(a -> a.toString())
.collect(Collectors.toList());
请注意 map 函数如何引入从整数到字符串的转换,在这种情况下,返回的列表是 List<String>
类型。变换由map进行,List由collector生成。
【讨论】:
【参考方案4】:如果您不介意使用第三方库,可以使用功能强大的新集合。
// import javaslang.collection.*;
listB = listA.map(f);
这些 Java 8 集合是不可变的,可以与 Scala 和 Clojure 的集合进行比较。请阅读更多here。
顺便说一句 - for 循环也有语法糖:
// import static javaslang.API.*;
// import javaslang.collection.Stream;
Stream<R> result = For(iterable1, ..., iterableN).yield((e1, ..., eN) -> ...);
免责声明:我是 Javaslang 的创建者。
【讨论】:
以上是关于将 Lambda 应用于返回另一个列表的列表的 Java 8 惯用方法?的主要内容,如果未能解决你的问题,请参考以下文章
创建一个返回每个内部对象的 lambda(如 forEach)
C#如何使用 lambda 表达式将 iGrouping 返回到列表