如何使用Java 8创建无限流


69

有没有一种简单的方法可以使用创建无限流 没有外部库?

例如在Scala中:

Iterator.iterate(0)(_ + 2)

Answers:


101

是的,有一个简单的方法:

IntStream.iterate(0, i -> i + 2);

作为用例:

IntStream.iterate(0, i -> i + 2)
         .limit(100)
         .forEach(System.out::println);

打印出0到198,以2为步长递增。

通用方法是:

Stream.iterate(T seed, UnaryOperator<T> f);

后者的用法可能更不常见。


16
+1,但值得一提的是IntStream.generate可以在IntStream.iterate不适合时使用,例如斐波那契数列。
Daniel Lubarov 2014年

1
如何IntStream.iterate不适合Fibnoacci
阿西夫·穆斯塔克

@AsifMushtaq能否提供一堆斐波那契数列IntStream.iterate
Koray Tugay,

7

这是一个例子:

PrimitiveIterator.OfInt it = new PrimitiveIterator.OfInt() {
    private int value = 0;

    @Override
    public int nextInt() {
        return value++;
    }

    @Override
    public boolean hasNext() {
        return true;
    }
};

Spliterator.OfInt spliterator = Spliterators.spliteratorUnknownSize(it,
    Spliterator.DISTINCT | Spliterator.IMMUTABLE |
    Spliterator.ORDERED | Spliterator.SORTED);

IntStream stream = StreamSupport.intStream(spliterator, false);

如您所见,它有点冗长。要打印此流的前10个元素:

stream.limit(10).forEach(System.out::println);

当然,您也可以像在Scala示例中那样变换元素:

IntStream plusTwoStream = stream.map(n -> n + 2);

请注意,有内置的无限流,例如,java.util.Random.ints()它为您提供了无限的随机整数流。


2
给定您的PrimitiveIterator.OfInt it,一个简单的方法IntStream.generate(it::next)也可以。因此,它甚至根本不必是迭代器,例如IntStream.generate(new AtomicInteger()::incrementAndGet)也将提供这种自然的数字序列。
Holger 2014年

1
是的,显然我的解决方案比必要的更为冗长,并且有多种方法可以实现。
Jesper 2014年

不知道java.util.Random.ints(),+ 1
马库斯·温宁格

2

Java 8中还有另一种可能的解决方案:

AtomicInteger adder = new AtomicInteger();
IntStream stream = IntStream.generate(() -> adder.getAndAdd(2));

重要:仅当流是连续的时,数字顺序才被保留。


还值得注意的是,IntStream.iterateJava 9以来已添加了的新版本:

static IntStream iterate​(int seed,
                         IntPredicate hasNext,
                         IntUnaryOperator next);
  • 种子-初始元素;
  • hasNext-谓词,应用于元素以确定流何时必须终止;
  • next-应用于上一个元素以产生新元素的函数。

例子:

IntStream stream = IntStream.iterate(0, i -> i >= 0, i -> i + 2);

IntStream.iterate(0, i -> i < 10, i -> i + 2).forEach(System.out::println);

0

您可以通过实现流和使用者来构建自己的InfiniteStream,然后将两者组成,并且可能需要将队列排队为:

public class InfiniteStream<T> implements Consumer<T>, Stream<T> {
private final Stream<T> stream;
private final Queueing q;
...
public InfiniteStream(int length) {
    this.q = new Queueing(this.length);
    this.stream = Stream.generate(q);
    ...
}
    //implement stream methods
    //implement accept
}

在此处检查完整代码 https://gist.github.com/bassemZohdy/e5fdd56de44cea3cd8ff

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.