【问题标题】:Iterations required when chaining stream intermediate operations链接流中间操作时需要迭代
【发布时间】:2021-07-01 17:36:42
【问题描述】:

我知道 Java 中的流中间操作是惰性的,并且在调用终端操作之前不会执行。但是,我不确定链接中间操作是否会增加所需的迭代次数。因为有时我们将操作分成多个中间操作,只是为了便于阅读。

所以例如下面的两个例子做同样的事情。但在第二个例子中,两个中间操作合二为一。

myStream
     .map(s -> methodA(s))
     .map(s -> methodB(s))
     .collect(Collectors.joining());
myStream
     .map(s -> methodB(methodA(s)))
     .collect(Collectors.joining());

这两种情况所需的迭代次数不是相同吗?因为看起来,JVM 可以在单次迭代中执行它(类似于单次 for 循环),而不是为每个中间操作迭代元素。

【问题讨论】:

  • 您的意思是时间复杂度...不是性能或执行时间?显然这里的时间复杂度是一样的。
  • 时间 complexity 不会改变,可能一次你运行 N 次操作,另一次 N+N=2*N 次操作但它们仍然是 O(N)。如果您将其拆分为 100 个操作,您将运行 100*N 个操作,这仍然是 O(N)。
  • 在谈到复杂性时,O(2n)O(3n) 等无关紧要。他们都只是O(n)。它代表增长,而不是实际执行时间。
  • 即使中间操作是否惰性,也不会改变时间复杂度。所以不要把时间复杂度和性能混为一谈。它们可能会相互作用,但仍然是完全不同的东西。
  • 解决您更新的问题,两种变体都相当于一个循环。

标签: java java-stream


【解决方案1】:

我知道 Java 中的流中间操作是惰性的,并且在调用终端操作之前不会执行。但是,我不确定链接中间操作是否会增加所需的迭代次数。 ...在这两种情况下,所需的迭代次数不是相同吗?

以下内容似乎证实了您(和其他人)的结论。我使用了AtomicInteger,因为使用并行流会取消计数。在任何情况下,方法调用的总数都没有不同。但是,由于这两种方法返回不同的值,因此由于映射的顺序,总和会有所不同。在第一种情况下,MethodA 最后处理,因此它的值将被求和。在第二种情况下,MethodB 被最后处理,因此它的值将被求和。

static AtomicInteger count = new AtomicInteger(0);
Random r = new Random();
for (int i = 0; i < 10000; i++) {
    count.set(0);
    List<Integer> list = IntStream.generate(
            () -> 1)
            .limit(r.nextInt(10) + 1).boxed().toList();
    
    int sum1 = list.stream().mapToInt(s -> methodB(s)).map(s -> methodA(s))
            .sum();
    
    int save = count.get();
    
    count.set(0);
    int sum2 = list.stream().mapToInt(s -> methodB(methodA(s)))
              .sum();
    if (save != count.get()) {
        System.out.println(
                "Inconsistent counts: " + save + " " + count);
    }
}
    
public static int methodA(int v) {
    count.incrementAndGet();
    return 1;
}

    
public static int methodB(int v) {
    count.incrementAndGet();
    return 2;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 2013-04-17
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 2018-12-02
    • 1970-01-01
    相关资源
    最近更新 更多