当前位置: 首页 > 知识库问答 >
问题:

哪个更好,Stream还是Iterator[关闭]

穆博简
2023-03-14

想改进这个问题吗?更新问题,以便通过编辑这篇文章用事实和引用来回答。

我在玩Java*流API,在Lagecy系统中有以下代码:

Iterator itr = configMap.entrySet().iterator();
        List<String> resultList = new ArrayList<String>();
        while(itr.hasNext()){
            Entry e = (Entry)itr.next();
            Config rc = (Config)e.getValue();

            if (rc != null && rc.getVisibleTo() != null && (rc.getVisibleTo().equalsIgnoreCase("0010") || rc.getVisibleTo().equalsIgnoreCase("0111") || rc.getVisibleTo().equalsIgnoreCase("0011"))){        
                resultList .add(rc.getName());
            }
        }

我编写了与上述代码等价的流,如下所示:

List<String> resultList = configMap.entrySet()
                   .parallelStream()
                   .map(r -> r.getValue())
                   .filter(r -> r.getVisibleTo() != null)
                   .filter(r -> {return 
                              r.getVisibleTo().equalsIgnoreCase("0010")
                           || r.getVisibleTo().equalsIgnoreCase("0111")
                           || r.getVisibleTo().equalsIgnoreCase("0011");
                        })
                   .map(r -> r.getName())
                   .collect(Collectors.toList());

无论哪种方式,我都得到了想要的结果。我的问题是,在这种情况下,哪种性能方面是更好的写作方式?如果我选择其中任何一个而不是另一个,我实际上是否获得了任何价值?地图中包含大约 1000 个值。

共有3个答案

房时铭
2023-03-14

首先,如果性能是你关心的问题,你应该根据事实来决定,所以测量,不要猜测(即使用JMH)。

对于简单的情况,迭代或经典循环往往比流更快。另一方面,流可以快得多,并且通常可以通过并行性进一步加速(其中工作负载很容易并行化)。在大多数情况下,这并不重要(以我的经验来看),因为要么数据集太小,要么使用它的代码性能不够关键。

关于可读性/可维护性,我倾向于使用流/功能方法更好地分离关注点。但是一个for-each循环也可以改进迭代代码。因此,没有简单的是/否答案,这取决于上下文。

浦修文
2023-03-14

因为您是以并行流的形式编写的,它试图多线程化并划分工作,所以考虑到您的工作有点小,您可能会看到由于管理线程的开销而导致的性能下降。这里的另一个陷阱是,由于您使用的是< code>CommonForkJoinPool(这里的默认线程池),这不是一个很好的选择,因为阻塞任务会降低整个应用程序的性能(这虽然与您的小规模工作没有太大关系,但需要记住)。

话虽如此,如果您使用单线程配置Mapig.entrySet().stream(),我会说性能差异可能会稍微慢一些,但可读性远远弥补了这一点。因此,选择变成了在稍微快一点的代码或更好的可读性之间做出的决定,这完全取决于你(但我个人会选择流)。

苗森
2023-03-14

我将稍微重写< code>sream示例:

List<String> resultList = configMap.entrySet()
        .parallelStream()
        .map(Map.Entry::getValue)
        .filter(Objects::nonNull) // value might be a null
        .filter(r ->
                ((Predicate<String>) "0010"::equals)
                        .or("0111"::equals) // null-save equivalent to  "0111".equals(value)
                        .or("0011"::equals)
                        .test(r.getVisibleTo())
        )
        .map(Config::getName)
        .collect(Collectors.toList());

并且会使用它。有关详细性能解释,请参见以下问题Java 8:Java 8的流与集合以及迭代器与流的性能

正如@4castle在下面的评论中所建议的那样,我们可以通过使用配置地图.values()而不是配置地图.entrySet()来使其更短:

List<String> resultList = configMap.values()
        .parallelStream()
        .filter(Objects::nonNull)
        .filter(r ->
                ((Predicate<String>) "0010"::equals)
                        .or("0111"::equals) // null-save equivalent to  "0111".equals(value)
                        .or("0011"::equals)
                        .test(r.getVisibleTo())
        )
        .map(Config::getName)
        .collect(Collectors.toList());
 类似资料:
  • 问题内容: 在性能方面,会更好。使用PHP来回显所有HTML输出,因此我可以将其与工作代码和变量的各种内容结合使用,或者在整个文档中定期将HTML逃逸到php。 我知道可能存在一些可读性问题,但我不必为此担心。 谢谢大家! 例子1 要么 问题答案: 这是您最容易阅读的内容。当然,每种情况都会有所不同。如果您要处理整个页面,并且其中有很大一部分没有任何PHP,那么我会脱离PHP并只编写纯HTML,而

  • 问题内容: 如果您的目标是测试MySQL列中是否存在字符串(类型为’varchar’,’text’,’blob’等),那么以下哪一项是更快/更有效/更好地使用,为什么? 或者,还有其他方法可以胜任这些方法吗? 与 问题答案: 正如kibibu在上述评论中指出的,FULLTEXT搜索绝对会更快。 但是 : 在我的测试中,它们的表现完全相同。它们都不区分大小写,并且通常会执行全表扫描,这在处理高性能M

  • 问题内容: 我知道我们可以进行相关的子查询并加入。但是哪一个更快?有黄金法则还是我必须同时衡量这两者? 问题答案: 首先,相关子查询实际上是联接的一种。关于哪一个产生最佳执行计划没有黄金法则。如果您对性能感兴趣,则需要尝试不同的表格以查看最有效的方法。或者,至少,看看执行该决定的执行计划。 通常,出于两个原因,我倾向于避免关联子查询。首先,几乎总是可以在没有相关性的情况下编写它们。其次,许多查询引

  • 问题内容: 使用哪种更好或更方便: 要么 问题答案: 您是否完全需要类型属性?如果您使用的是HTML5,则不会。否则,是的。HTML 4.01和XHTML 1.0 根据需要指定属性,而HTML5具有可选属性,默认为。HTML5现在得到了广泛的实现,因此,如果您使用HTML5doctype,则是有效且不错的选择。 至于type属性中应该包含的内容,2006年注册的MIME类型旨在替代所有主要浏览器(

  • 我有这样的表达: 以下哪些元素(