我正在编写一个代码来计算斐波纳契数。使用此代码,我可以生成前n个Fibonacci序列。
Stream.generate(new Supplier<Long>() {
private long n1 = 1;
private long n2 = 2;
@Override
public Long get() {
long fibonacci = n1;
long n3 = n2 + n1;
n1 = n2;
n2 = n3;
return fibonacci;
}
}).limit(50).forEach(System.out::println);
方法limit
返回Stream
,其中包含传递给此方法的元素数。我希望在Fibonacci数达到某个值后停止生成Stream
。
我的意思是,如果我想列出小于1000的所有Fibonacci数字,那么我就不能使用limit
,因为我不知道可能有多少斐波纳契数。
有没有办法用lambda表达式做到这一点?
答案 0 :(得分:3)
如果您不介意使用迭代器,可以将其写为:
static LongUnaryOperator factorial = x -> x == 0 ? 1
: x * factorial.applyAsLong(x - 1);
public static void main(String[] args) {
LongStream ls = LongStream.iterate(0, i -> i + 1).map(factorial);
OfLong it = ls.iterator();
long next = 0;
while ((next = it.nextLong()) <= 1000) System.out.println(next);
}
答案 1 :(得分:3)
使用我能找到的Stream
内置功能的最佳解决方案是:
LongStream.generate(new LongSupplier() {
private long n1 = 1, n2 = 2;
public long getAsLong() {
long fibonacci = n1;
long n3 = n2 + n1;
n1 = n2;
n2 = n3;
return fibonacci;
}
}).peek(System.out::println).filter(x->x>1000).findFirst();
它的缺点是处理第一项>=1000
。这可以通过使语句成为条件来防止,例如
.peek(x->{if(x<=1000) System.out.println(x);}).filter(x->x>1000).findFirst();
但我不喜欢两次评估相同的条件(大于千或不大)。但是,这两种解决方案中的一种可能对于实际任务而言足够实用,其中需要基于结果值的限制。
我认为,显然整个构造不具备并行能力......
答案 2 :(得分:2)
是的,有一种lambda方式,但遗憾的是,我不认为它是在当前的Java 8 Stream
API中实现的。
很抱歉给您指的是另一种语言,但我认为您想要的是
takeWhile(p: (A) ⇒ Boolean): Stream[A]
来自Scala Stream API的。
由于这不是在Java API中实现的,因此您必须自己完成。 这个怎么样:
public static List<T> takeWhile(Iterable<T> elements, Predicate<T> predicate) {
Iterator<T> iter = elements.iterator();
List<T> result = new LinkedList<T>();
while(iter.hasNext()) {
T next = iter.next();
if (predicate.apply(next)) {
result.add(next);
} else {
return result; // Found first one not matching: abort
}
}
return result; // Found end of the elements
}
然后你可以像
一样使用它List<Long> fibNumbersUnderThousand = takeWhile(allFibNumStream, l -> l < 1000);
(假设Stream
是Iterable
的实例 - 如果没有,您可能需要调用.iterator()
方法并将其包装起来)
答案 3 :(得分:1)
脏的第一个版本
Stream.generate(new Supplier<Long>() {
private long n1 = 1;
private long n2 = 2;
@Override
public Long get() {
long fibonacci = n1;
long n3 = n2 + n1;
n1 = n2;
n2 = n3;
return fibonacci;
}
}).limit(50).forEach(x -> {
if (x < 1000) {
System.out.println(x);
}
});