Java 8-流思想

Bober02:

我最近开始玩Java 8,之前在Haskell / Scala中做过零碎的工作。我正在尝试使用诸如map或的Java中的高阶函数forEach,并且努力了解将一切推向Stream意识形态的动机我知道它提供了很好的通用抽象,应该是懒惰的,但让我们考虑一个非常简单的通用示例:

list.map(x -> do_sth(x));

非常常见的成语,期望它返回List<T>现在,在Java 8中,我需要执行以下操作:

list.stream().map(x -> doSth(x)).collect(Collectors.toList())

现在,据我所知,在调用collect之前,流将不会应用地图,因此在后台将有一个遍历collection的过程。我也看不出是为什么地图,列表如常见的使用情况map.toList()list.groupBy()将不会被添加到相应的接口?我在这里是否缺少基本的设计决策?

斯图尔特·马克斯(Stuart Marks):

少数新方法已直接添加到各种集合中,这些集合急切地对这些集合执行变异操作。例如,要在列表的每个元素上运行函数,将原始元素替换为返回值,请使用List.replaceAll(UnaryOperator)这样其他例子是Collection.removeIf(Predicate)List.sort()Map.replaceAll(BiFunction)

相比之下,Stream中添加了许多新方法,例如过滤器,映射,跳过,限制,排序,区分等。这些方法大多数都是惰性的,它们不会改变源,而是将元素传递到下游。我们确实考虑过将这些直接添加到collections类中。此时出现了几个问题。我们如何区分急切的,变异的操作和懒惰的流生成操作?重载非常困难,因为它们的返回类型不同,因此它们必须具有不同的名称。如何将此类操作链接在一起?急切的操作将不得不生成集合来存储中间结果,这可能是非常昂贵的。生成的collection API会混杂着急切,突变和惰性的非突变方法。

第二个考虑因素是与添加默认方法的潜在不兼容性。向接口添加默认方法的最大风险是与该接口实现上的现有方法发生名称冲突。如果具有相同名称和参数(通常没有参数)的方法具有不同的返回类型,则这是不可避免的不兼容性。因此,我们一直不太愿意添加大量默认方法。

由于这些原因,我们决定将延迟的,不变的方法全部保留在流API中,以牺牲需要额外的方法调用stream()和collect()在集合和流之间架桥的代价为代价。对于一些常见的情况,我们添加了急切的,直接将集合的调用突变的方法,例如我上面列出的那些。

参见lambdafaq.org进行进一步的讨论。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章