2014-02-08 38 views
2

我正在编写一个计算斐波纳契数字的代码。通过这段代码,我可以生成前n个斐波那契数列。提供流生成的限制条件

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的方法。在斐波纳契数达到某个值后,我想停止Stream的生成。

我的意思是如果我想列出所有小于1000的斐波那契数,那么我不能使用limit,因为我不知道可能有多少斐波那契数。

有没有办法使用lambda表达式来做到这一点?

回答

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); 
     } 
    }); 
+0

啊我真的不能叫'System.exit' :-( –

+0

我不喜欢我使用System.exit方式(0);在这里,但它确实完成了工作 –

+0

好吧,我们组合了一个极限,我们知道它已经结束了,只是控制了打印的数量,我不知道其他方式来设置结束到一个威胁(新的java8) –

2

是的,有一个lambda方式,但不幸的是,我不认为这是当前Java 8 Stream API中实现。 对不起你指向一个不同的语言,但你要什么,我认为是一样的东西

takeWhile(p: (A) ⇒ Boolean): Stream[A] 

从斯卡拉流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); 

(假设StreamIterable一个实例 - 如果没有,你可能需要调用.iterator()方法和换行高达)

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); 
} 
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(); 

但我不喜欢评估相同的条件(大于千或不是两次)。但是,也许这两种解决方案中的一种可能对于需要基于结果值的限制的现实生活任务而言足够实用。

我认为,很明显,整个结构不平行能力......