Java 8:计算lambda迭代的首选方法? [英] Java 8: Preferred way to count iterations of a lambda?

查看:439
本文介绍了Java 8:计算lambda迭代的首选方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常遇到同样的问题。我需要计算一个lambda的运行,以便在lambda之外使用。例如:

I face the same problem often. I need to count the runs of a lambda for use outside the lambda. E.g.:

myStream.stream().filter(...).forEach(item->{ ... ; runCount++);
System.out.println("The lambda ran "+runCount+"times");

问题是runCount需要是final,所以它不能是int。它不能是一个整数,因为那是不可变的。我可以使它成为类级变量(即一个字段),但我只需要在这段代码中。
我知道有各种各样的方法,我只是好奇你最喜欢的解决方案是什么?您是否使用AtomicInteger或数组引用或其他方式?

The issue is that runCount needs to be final, so it cannot be an int. It cannot be an Integer because that's immutable. I could make it class level variable (i.e. a field) but I'll only need it in this block of code. I know there are various ways, I'm just curious what is your preferred solution for this? Do you use an AtomicInteger or an array reference or some other way?

推荐答案

为了讨论,让我重新格式化你的例子:

Let me reformat your example a bit for the sake of discussion:

long runCount = 0L;
myStream.stream()
    .filter(...)
    .forEach(item -> { 
        foo();
        bar();
        runCount++; // doesn't work
    });
System.out.println("The lambda ran " + runCount + " times");

如果真的需要从lambda中增加一个计数器,这样做的典型方法是使计数器为 AtomicInteger AtomicLong ,然后调用其中一个增量方法。

If you really need to increment a counter from within a lambda, the typical way to do so is to make the counter an AtomicInteger or AtomicLong and then call one of the increment methods on it.

您可以使用单元素 int long 数组,但如果流并行运行则会出现竞争条件。

You could use a single-element int or long array, but that would have race conditions if the stream is run in parallel.

但请注意,流以 forEach ,表示没有返回值。您可以将 forEach 更改为 peek ,它会传递项目,然后计算它们:

But notice that the stream ends in forEach, which means that there is no return value. You could change the forEach to a peek, which passes the items through, and then count them:

long runCount = myStream.stream()
    .filter(...)
    .peek(item -> { 
        foo();
        bar();
    })
    .count();
System.out.println("The lambda ran " + runCount + " times");

这有点好,但仍有点奇怪。原因是 forEach peek 只能通过副作用完成他们的工作。 Java 8的新兴功能风格是避免副作用。我们通过将计数器的增量提取到流上的 count 操作中做了一点。其他典型的副作用是将项目添加到集合中。通常这些可以通过使用收集器来替换。但是在不知道你想要做什么实际工作的情况下,我无法提出更具体的建议。

This is somewhat better, but still a bit odd. The reason is that forEach and peek can only do their work via side effects. The emerging functional style of Java 8 is to avoid side effects. We did a little of that by extracting the increment of the counter into a count operation on the stream. Other typical side effects are adding items to collections. Usually these can be replaced via use of collectors. But without knowing what actual work you're trying to do, I can't suggest anything more specific.

这篇关于Java 8:计算lambda迭代的首选方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆