Java流/forEach迭代集合时的定期操作

3
在旧版Java中,我们可以循环一个集合并在每个X项上执行某些操作-例如,将一组项目保存到数据库中:
因此,考虑到
List students = ....;

我们可以执行一些周期性的操作,例如:
for(int i = 0; i < students.size(); i++){
    methodA(students.get(i));
    methodB(students.get(i));

    if (i % 100 == 0){
        flushToDB(...);
        reportProgressToSlack(...);
        ....
    }
}

尝试使用 Streams 做类似的事情时,我们会遇到错误:

int counter = 0;
students.stream().forEach(student -> {
    methodA(student);
    methodB(student);
    counter++;
});

当然,编译器会抱怨counter必须是final或有效的final。

有没有使用Java Streams实现这样一件事情的方法呢?


请注意,您的代码中没有使用流。 - ernest_k
在当前的Java时代,您也可以循环一个集合并对每个X项执行操作。Java Stream API只是为您提供了额外的工具,但没有阻止您为每种情况使用最合适的迭代策略。由于您想要做的可能有些复杂,因此使用常规的for循环可能会更易读。 - Averroes
4个回答

1

在其他答案的基础上稍作变化,使用一个过滤器来通过每100个条目。首先通过流式传输列表索引:

IntStream.range(0, students.size()).filter(i -> {
    Student student = students.get(i);
    methodA(student);
    methodB(student);
    return i % 100 == 0;
}).forEach(...);

第二,通过流式传输和跟踪累积指数:
AtomicInteger i = new AtomicInteger();
students.stream().filter(student -> {
    methodA(student);
    methodB(student);
    return i.getAndIncrement() % 100 == 0;
}).forEach(...);


0

其他方法:

AtomicInteger counter = new AtomicInteger();
students.forEach(student -> {
    methodA(student);
    methodB(student);
    if (counter.getAndIncrement() % 100 == 0) {
        flushToDB(...);
        reportProgressToSlack(...);
    }
});

0

使用流API的for循环副本可以如下所示:

IntStream.range(0, students.size())
     .forEach(i -> {
        methodA(students.get(i));
        methodB(students.get(i));

        if (i % 100 == 0){
            flushToDB(...);
            reportProgressToSlack(...);
            ....
        }
     });

需要注意的是,上述流水线必须保持顺序。


-1

你可以尝试使用 AtomicInteger 包装器来处理这种情况:

List students = ....;
AtomicInteger counter = new AtomicInteger();
students.forEach(student -> {
    methodA(student);
    methodB(student);
    counter.getAndIncrement();
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接