首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >提供流生成的限制条件

提供流生成的限制条件
EN

Stack Overflow用户
提问于 2014-02-09 02:35:07
回答 4查看 4.6K关注 0票数 3

我正在写一个计算斐波那契数的代码。使用这段代码,我可以生成斐波那契数列的前n个数。

代码语言:javascript
运行
复制
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表达式来做到这一点?

EN

回答 4

Stack Overflow用户

发布于 2014-02-09 03:29:21

如果你不介意使用迭代器,你可以把它写成:

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

发布于 2014-02-12 03:38:35

我能找到的使用Stream内置功能的最佳解决方案是:

代码语言:javascript
运行
复制
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。这可以通过使语句具有条件来防止,例如

代码语言:javascript
运行
复制
.peek(x->{if(x<=1000) System.out.println(x);}).filter(x->x>1000).findFirst();

但我不喜欢对同一条件(大于或不大于1000)进行两次评估。但是,对于需要基于结果值的限制的实际任务,这两种解决方案中的一种可能足够实用。

我认为,很明显,整个结构并不是能够并行的…

票数 3
EN

Stack Overflow用户

发布于 2014-02-09 03:03:35

是的,有一种lambda方法,但不幸的是,我不认为它是在当前的Java8API中实现的。很抱歉给您介绍一种不同的语言,但我认为您需要的是类似于

代码语言:javascript
运行
复制
 takeWhile(p: (A) ⇒ Boolean): Stream[A]

来自Scala Stream API。

因为这不是在Java API中实现的,所以您必须自己完成。这个怎么样:

代码语言:javascript
运行
复制
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
}

然后你可以像这样使用它

代码语言:javascript
运行
复制
List<Long> fibNumbersUnderThousand = takeWhile(allFibNumStream, l -> l < 1000);

(假设StreamIterable的一个实例-如果不是,您可能需要调用.iterator()方法并将其包装起来)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21650155

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档