【问题标题】:Java8 - Count after filter on streamJava8 - 在流上过滤后计数
【发布时间】:2018-04-24 17:17:52
【问题描述】:

我希望以前没有人问过这个问题。 在 java 8 中,我有一个字符串数组myArray 输入和一个整数maxLength。 我想计算数组中小于 maxLength 的字符串数。我想使用流来解决这个问题。

为此我想这样做:

int solution = Arrays.stream(myArray).filter(s -> s.length() <= maxLength).count();

但是我不确定这是否是正确的方法。它需要遍历第一个数组一次,然后遍历过滤后的数组进行计数。

但如果我不使用流,我可以轻松地创建一个算法,在 myArray 上循环一次。

我的问题很简单:有没有办法以与循环相同的时间性能来解决这个问题?使用流总是一个“好的”解决方案吗?

【问题讨论】:

  • 另外,如果你想要小于那么它应该是s.length() &lt; maxLength而不是s.length() &lt;= maxLength
  • @Aominè .parallel() 有帮助吗?
  • 你试过了吗?它有效吗?如果是这样,这在 codereview.stackexchange.com 上可能会更好。如果它不起作用,请告诉我们您遇到了什么错误或意外行为。
  • @azro 并行运行它可能会使情况变得更糟,因为在考虑并行之前需要考虑很多事情。
  • 不,如果您关心性能,使用流并不总是一个好的解决方案。创建流有开销。如果你的数组很小,你最好只使用一个循环。如果您正在处理一个非常大的数组,您可能应该尝试两种解决方案,看看哪个效果更好。

标签: java java-stream


【解决方案1】:

但是我不确定这是否是正确的方法。这将需要 通过第一个数组一次,然后通过过滤后的数组 数数。

您认为它将执行多次传递的假设是错误的。有一些东西调用操作融合,即可以在一次数据传递中执行多个操作;

在这种情况下,Arrays.stream(myArray) 将创建一个流对象(廉价操作和轻量级对象),filter(s -&gt; s.length() &lt;= maxLength).count(); 将合并为一次数据传递,因为管道中没有状态操作,而不是过滤所有流的元素,然后计算所有通过谓词的元素。

来自 Brian Goetz post here 的一句话:

相比之下,流管道将它们的操作融合到少数几个 尽可能地传递数据,通常是单次传递。 (有状态的 中间操作,例如排序,可以引入障碍点 这需要多次执行。)

至于:

我的问题很简单:有没有办法解决这个问题 与循环相同的时间性能?

取决于每个元素的数据量和成本。无论如何,对于少数元素,命令式 for 循环几乎总是会获胜,如果不是总是如此。

使用流总是一个“好的”解决方案吗?

不,如果您真的关心性能,那么 measuremeasuremeasure

使用流,因为它是声明性的,因为它的抽象、组合以及从并行性中受益的可能性当你知道你会从中受益时

【讨论】:

  • 来吧,选民们,我不能是唯一认为这是一个绝妙答案的人。
【解决方案2】:

您可以使用range 代替stream 并过滤输出。

int solution = IntStream.range(0, myArray.length)
                .filter(index -> myArray[index].length() <= maxLength)
                .count();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2017-04-30
    • 1970-01-01
    • 2019-11-23
    • 2019-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多