Java Streams - 如何在每第n个项目中执行中间函数 [英] Java Streams — How to perform an intermediate function every nth item

查看:88
本文介绍了Java Streams - 如何在每第n个项目中执行中间函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一个Stream上的操作,使我能够每隔n项执行一次非终端(和/或终端)操作。虽然我使用素数流,例如,流可以很容易地生成网络请求,用户操作或其他一些冷数据或实时Feed。



由此:

 持续时间start = Duration.ofNanos(System.nanoTime()); 

IntStream.iterate(2,n - > n + 1)
.filter(Findprimes :: isPrime)
.limit(1_000_1000 * 10)
。的forEach(的System.out ::的println);

System.out.println(持续时间:+ Duration.ofNanos(System.nanoTime())。minus(start));

对于这样的流函数:

  IntStream.iterate(2,n  - > n + 1)
.filter(Findprimes :: isPrime)
.limit(1_000_1000 * 10)
.peekEvery(10,System.out :: println)
.forEach(it - > {});


解决方案

创建一个帮助方法来包装 peek() consumer:

  public static IntConsumer every(int count,IntConsumer consumer){ 
if(count< = 0)
抛出新的IllegalArgumentException(Count必须> 1:Got+ count);
返回新的IntConsumer(){
private int i;
@Override
public void accept(int value){
if(++ this.i == count){
consumer.accept(value);
this.i = 0;
}
}
};
}

您现在几乎可以按照自己的意愿使用它:

  IntStream.rangeClosed(1,20)
.peek(every(5,System.out :: println))
。计数();

输出



< pre class =lang-none prettyprint-override> 5
10
15
20

辅助方法可以放在实用程序类中并静态导入,类似于 收集器 类只是静态辅助方法。



如@ user140547所述 comment ,此代码不是线程安全的,因此不能与并行流一起使用。此外,输出顺序会混乱,所以无论如何将它与并行流一起使用并没有多大意义。


I am looking for an operation on a Stream that enables me to perform a non-terminal (and/or terminal) operation every nth item. Although I use a stream of primes for example, the stream could just as easily be web-requests, user actions, or some other cold data or live feed being produced.

From this:

    Duration start = Duration.ofNanos(System.nanoTime());

    IntStream.iterate(2, n -> n + 1)
            .filter(Findprimes::isPrime)
            .limit(1_000_1000 * 10)
            .forEach(System.out::println);

    System.out.println("Duration: " + Duration.ofNanos(System.nanoTime()).minus(start));

To a stream function like this:

    IntStream.iterate(2, n -> n + 1)
            .filter(Findprimes::isPrime)
            .limit(1_000_1000 * 10)
            .peekEvery(10, System.out::println)
            .forEach( it -> {});

解决方案

Create a helper method to wrap the peek() consumer:

public static IntConsumer every(int count, IntConsumer consumer) {
    if (count <= 0)
        throw new IllegalArgumentException("Count must be >1: Got " + count);
    return new IntConsumer() {
        private int i;
        @Override
        public void accept(int value) {
            if (++this.i == count) {
                consumer.accept(value);
                this.i = 0;
            }
        }
    };
}

You can now use it almost exactly like you wanted:

IntStream.rangeClosed(1, 20)
         .peek(every(5, System.out::println))
         .count();

Output

5
10
15
20

The helper method can be put in a utility class and statically imported, similar to how the Collectors class is nothing but static helper methods.

As noted by @user140547 in a comment, this code is not thread-safe, so it cannot be used with parallel streams. Besides, the output order would be messed up, so it doesn't really make sense to use it with parallel streams anyway.

这篇关于Java Streams - 如何在每第n个项目中执行中间函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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