StreamAPI offers two static methods to generate Stream using functions,i.e. Stream.iterate() & Stream.generate() ,which both can create so-called Unlimited Streams:unlike these from Collection with limited and fixed size ,those streams area limited with infinite size. But ,obviously ,we’d better use limit(n) to limit the size,just to avoid creating literally Unlimited ones.
1、iterate()
先来个小题目:打印出最小的十个偶数,你咋写的?
再怎么说,总有个计数器的吧,这种实现多麻烦。
// 写法1
int count = 0;
for (int i = 0;i < Integer.MAX_VALUE; i = i + 2) {
if (count++ >=10) {
return;
}
System.out.println(i);
}
假如用java8 的 无限流,只要三行搞定
// 写法2
Stream.iterate(0, i -> i + 2)
.limit(10)
.forEach(System.out::println);
我们观察一下Stream.iterate的API 说明
要求传递一个seed ,然后一个单目函数,返回一个无限有序的流,流元素是由单目函数不断对前面元素迭代计算得到的。
我们来做个经典裴波那契数列的例子:如果不用java8 ,写个递归可以搞定,可仔细想想,递归这种思路不也就是 后一个元素对前面相邻元素的迭代运算吗?(TODO)
我们来换个思路:我们的目标是下面的数列,其特点是从第三项开始,每一项都是前面相邻两个元素的和:
0,1,1,2,3,5,8,13…
再来介绍下裴波那契元组数列:
(0,1) ,(1,1),(1, 2),(2,3),(3,5),(5,8),(8,13)…
也就是:(0,1) ,(1,0+1),(1, 1+1),(2, 2+ 1),(3, 3+ 2),(5,5+3),(8,8+5)…
仔细看,每个元组只取第一个元素的话不就是裴波那契数列嘛!
下面,我们首先来对元组数列建模,我们用一个数组表示一个元组,然后将(0, 1)元组作为seed(种子值),?? 表示必传的一个 UnaryOperator。
Stream.iterate(new int[] {0, 1}, ??)
.limit(20)
.forEach(System.out::println);
这里的UnaryOperator写法可就考验小伙伴对 函数的抽象能力了!
思考一下: 本质上就是每个元素都是元组(数组),元组第一个元素是前一个元组的后一个元素,元组的第二个元素是前一个元组两元素之和嘛!(你自己在纸上比划比划)
Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
.limit(20)
.forEach(t -> System.out.println(t[0] + " ," + t[1]));
这样我们就得到了元组的无限流,不过我们只取了20个。
假如我们希望得到裴波那契数列,取这个流每个元组的第一个元素就可以了:
Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
.limit(20)
.map(t -> t[0])
.forEach(System.out::println);
题外话:其实取每个元组的第二个元素也能得到从1 开始的裴波那契数列!
2、generate()