【问题标题】:Should I use Stream API for simple iteration?我应该使用 Stream API 进行简单的迭代吗?
【发布时间】:2014-04-24 10:08:24
【问题描述】:

使用新的 Stream API 进行简单迭代有什么好处吗?

没有 Stream API:

 for (Map.Entry<String, String> entry : map.entrySet()) {
        doSomething(entry);
    }

使用流 API:

map.entrySet().stream().forEach((entry) -> {
        doSomething(entry);
    });

代码的长度和可读性大致相同。是否有任何重要的差异(例如在性能方面)?

【问题讨论】:

  • 如果 Streams 可以使您的代码更短并且更具可读性,则应该使用它。所以你的用例本身并不是一个很好的例子。但是,如果您要使用 map.forEach 方法本身,那么使用 lambdas 是有一定意义的,但话又说回来,此时您不再使用流。
  • 同样适用于entrySet;您可以说map.entrySet().forEach(…) 而无需流。在单个方法调用的情况下,map.entrySet().forEach(context::doSomething); 形式比 lambda 表达式更可取,因为它真的更短且更具可读性。因此,如果您有一个 现有 方法 doSomething 采用单个条目实例或两个匹配键和值的参数,那么使用 forEach(…) 是有意义的。
  • 另外,即使你这样写,第二个例子中的括号也不需要。我认为这样更具可读性...
  • 谢谢大家,我从三个 cmets 身上学到了一些东西。 Netbeans 强调了非流版本并建议进行更改。我按回车键,然后 Netbeans 生成了上面的流版本...

标签: java-8 java-stream


【解决方案1】:

Streams API 使并行性更容易实现(尽管您只会看到大型集合的好处)。如果您必须在第一个示例中实现并行性,那么代码量将会有相当大的差异(而不是在第二个示例中添加 .parallelStream())

根据Java Trail on parallelism

在应用程序中实现并行性的一个困难是使用 collections 是集合不是线程安全的,这意味着 多个线程不能在不引入的情况下操作集合 线程干扰或内存一致性错误。收藏品 框架提供了同步包装器,它添加了自动 同步到任意集合,使其成为线程安全的。 但是,同步会引入线程争用。你想要 避免线程争用,因为它会阻止线程运行 平行线。聚合操作和并行流使您能够 使用非线程安全集合实现并行性,前提是 操作时不要修改集合。笔记 并行性不会自动比执行更快 串行操作,尽管如果您有足够的数据和 处理器内核。虽然聚合操作使您能够更轻松地 实现并行性,您仍然有责任确定是否 您的应用程序适合并行性。

【讨论】:

    【解决方案2】:

    您曾询问过 Streams,但正如skiwi 的评论所指出的,如果迭代很简单并且不需要并行性或任何其他逻辑,则将 lambda 传递给 Map 上的 forEach 默认方法可能会满足要求。假设doSomething 可以重构为采用单独的键和值参数而不是Map.Entry,这可以简化为单行:

        map.forEach(MyClass::doSomething);  // if doSomething is a static method
    
        map.forEach(this::doSomething);     // if doSomething is an instance method
    

    【讨论】:

      猜你喜欢
      • 2011-05-22
      • 2014-04-27
      • 2022-06-27
      • 1970-01-01
      • 2018-02-15
      • 1970-01-01
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多