Java IntStream 或 LongStream 按值限制而不是按元素数量限制

Java IntStream or LongStream limit by value and not by count of elements

我想迭代/生成无限的 IntStream 或 LongStream 并通过提供的最大值限制它们,而不是通过操作 limit(long n) 可能的元素数量来限制它们,例如获取第一个20个正偶数:

List<Integer> evens = IntStream.iterate(0, i -> i + 2)
                               .limit(20)
                               .boxed()
                               .collect(Collectors.toList());

我需要的是用最大值限制流。例如,如果我需要 1000

以下的 2 的所有幂
List<Integer> evens = IntStream.iterate(1, i -> i * 2)  //1, 2, 4, 8, 16, 32...
                               .limit(<here some how use the value 1000>)
                               .boxed()
                               .collect(Collectors.toList());

或斐波那契数列

List<Long> fibs = Stream.iterate(new long[]{1,1}, f -> new long[]{f[1], f[0] + f[1]})  //1,1,2,3,5,8,13,21...
                        .mapToLong(f -> f[1])
                        .limit(i -> i < 1000) //I know this doesn't work as limit expects a long value
                        .boxed()
                        .collect(Collectors.toList()); 

过滤器不起作用并导致 OutOfMemoryError

List<Integer> evens = IntStream.iterate(1, i -> i * 2)  //1, 2, 4, 8, 16, 32...
                               .filter(i -> i <= 1000)
                               .boxed()
                               .collect(Collectors.toList());

我有很多不同的UnaryOperators,我想用它们来生成不同的数字序列(不仅是我上面给出的简单例子,比如i -> i * 2,我可以在其中以某种方式计算出可能的数字给定范围内的元素)。

问题:如何将流限制为元素计数的给定最大值?

在Java9+中,使用takeWhile(i -> i <= value).

您正在寻找takeWhile

List<Integer> evens = IntStream.iterate(1, i -> i * 2)  //1, 2, 4, 8, 16, 32...
                               .takeWhile(i -> i <= 1000)
                               .boxed()
                               .collect(Collectors.toList());

在您展示的所有案例中,您都没有使用允许条件的 iterate()'s 方法。所以如果有人还没有达到Java9,可以这样做:

  • 获取不超过 20 的偶数。
List<Integer> evens = IntStream.iterate(0, i->i<=20, i->i+2)
    .boxed()
    .collect(Collectors.toList());

System.out.println(evens);
  • 获取小于 100 的斐波那契数列
List<Long> fibs = Stream.iterate(new long[]{1,1}, f->f[1] < 100,f -> new long[] 
               {f[1], f[0] + f[1]})
     .mapToLong(f -> f[1])
     .boxed()
     .collect(Collectors.toList());

System.out.println(fibs);
  • 求 2 的 128 次方。
List<Integer> powersOfTwo = IntStream.iterate(1, i-> i <= 128, i -> i * 2)  //1, 2, 4, 8, 16, 32...
        .boxed()
        .collect(Collectors.toList());
    
System.out.println(powersOfTwo);

版画

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
[1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
[1, 2, 4, 8, 16, 32, 64, 128]