如果说Lambda只是一些表达形式上的奇技淫巧,那么结合Java8的Stream API,我们就会发现什么才是功能强大的代码。
表达简单,功能强大。让人想的多,写的少。
流是一系列元素的集合,
但是,与集合不同的是,集合中的元素在一开始就已经在内存中了,而流中的元素是一个个取出来的
操作流的时候的感觉,特别像是在操作SQL中的集合
只要选择合适的流操作方法,然后将逻辑传递进去即可
流与集合,其实是一个时间与空间上的区分,流用时间来换取空间
就问你DBD,上述逻辑,使用SQL也就是一句话的事儿,但是如果是Java8以前,那就得写一大段代码。
接收Lambda,从流中排除某些元素
接收Lambda,将元素转化成其他形式
将流转化为其他形式
一个流被创建后,就只能遍历一次,如果想再次遍历,就得重新创建流
List<Apple> apples = MainPart01.createApples();
apples.stream()
.forEach(apple -> {
System.out.println(apple);
});
流的中间操作,其返回仍旧是一个流,可以被后续继续处理
对元素进行boolean判断,不符合要求的会从流中剔除出去
一般用方法引用作为参数更方便
剔除掉重复的元素,所谓重复,是通过元素的equals和hashCode判断的
截取流的前n的元素,后续元素丢弃
跳过指定个数的元素
将当前流中的元素映射
成另一种元素类型
之所以叫映射,而不是转化,是因为map操作不改变原先流中的元素
流的扁平化
一言以蔽之,flatmap方法让你把一个流中的每个值都换成另一个流,然后把所有的流连接 起来成为一个流
流的终端操作,是将流转化成结果
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
int sum = numbers.stream().reduce(0, Integer::sum);
int product = numbers.stream().reduce(1, (a, b) -> a * b);
Optional
所谓归约,就是将流归约为一个值
怎样用map和reduce方法数一数流中有多少个菜呢?
答案:要解决这个问题,你可以把流中每个元素都映射成数字1,
然后用reduce求和。这相当于按顺序数流中的元素个数。
int count = menu.stream()
.map(d -> 1)
.reduce(0, (a, b) -> a + b);
Collectors
类提供的工厂方法
它们主要提供了三大功能:
下面就对预定义收集器中的内容挑几个讲讲
Collectors.counting
long howManyDishes = menu.stream().collect(Collectors.counting());
这还可以写得更为直接:
long howManyDishes = menu.stream().count();
counting收集器在和其他收集器联合使用的时候特别有用,后面会谈到这一点。
在本章后面的部分,我们假定你已导入了Collectors类的所有静态工厂方法:
import static java.util.stream.Collectors.*;
这样你就可以写counting()而用不着写Collectors.counting()之类的了。
Collectors.maxBy和 Collectors.minBy
汇总
字符串连接
String shortMenu = menu.stream().map(Dish::getName).collect(joining());
分组
多级分组
Stream
int[] numbers = {2, 3, 5, 7, 11, 13};
int sum = Arrays.stream(numbers).sum()
Stream.iterate(0, n -> n + 2)
.limit(10)
.forEach(System.out::println);
按照自己的规则生成流
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println);