В Java 8 представлен класс Stream, который напоминает Scala Stream, мощный используя ленивую конструкцию, с помощью которой можно сделать что-то вроде этого очень кратко:
def from(n: Int): Stream[Int] = n #:: from(n+1)
def sieve(s: Stream[Int]): Stream[Int] = {
s.head #:: sieve(s.tail filter (_ % s.head != 0))
}
val primes = sieve(from(2))
primes takeWhile(_ < 1000) print // prints all primes less than 1000
Я задавался вопросом, возможно ли это сделать в Java 8, поэтому я написал что-то вроде этого:
IntStream from(int n) {
return IntStream.iterate(n, m -> m + 1);
}
IntStream sieve(IntStream s) {
int head = s.findFirst().getAsInt();
return IntStream.concat(IntStream.of(head), sieve(s.skip(1).filter(n -> n % head != 0)));
}
IntStream primes = sieve(from(2));
Довольно просто, но он создает java.lang.IllegalStateException: stream has already been operated upon or closed
, потому что findFirst()
и skip()
являются терминальными операциями на Stream
, которые могут выполняться только один раз.
Мне не нужно использовать поток дважды, потому что все, что мне нужно, это первое число в потоке, а остальное - как другой поток, т.е. эквивалент Scala Stream.head
и Stream.tail
. Есть ли способ в Java 8 Stream
, который я могу использовать для достижения этого?
Спасибо.