java8闪亮新特性函数式编程-lambda表达式及stream流操作。废话不多说,关键在应用。
一、引入流
1、背景:集合高频使用,API虽丰富,但步骤略繁琐
2、流优势:
1)声明性方式处理数据集合,直达目的,说明想要完成什么,而非利用循环if如何实现一个操作。
2)可组合操作,流水线调用(filter、sorted、map、collect)灵活应对多变需求;行为参数化,根据菜品type、价格、热量筛选即可,而不用复制粘贴代码
3)可并行
3、流组成(input--操作处理--output)
public class Stream1Difine {
/**
* 1、源:menu (集合、数组或IO资源)
* 2、数据处理操作(filter、map、reduce、find、match、sort等;类似于数据库的操作
* 3、元素序列 threeHighCaloricDishNames (计算结果,仍为集合)
* 重要2特点
* 1、流水线 (执行filter、map、reduce等操作返回值为stream-中间操作;执行count、collect返回集合-终端操作)
* 2、内部迭代 VS 外部迭代(集合)
*/
@Test
public void test(){
List<Dish> menu = Arrays.asList(
new Dish("pork", false, 800, Dish.Type.MEAT),
new Dish("beef", false, 700, Dish.Type.MEAT),
new Dish("chicken", false, 400, Dish.Type.MEAT),
new Dish("french fries", true, 530, Dish.Type.OTHER),
new Dish("rice", true, 350, Dish.Type.OTHER),
new Dish("season fruit", true, 120, Dish.Type.OTHER) ,
new Dish("pizza", true, 550, Dish.Type.OTHER),
new Dish("prawns", false, 300, Dish.Type.FISH),
new Dish("salmon", false, 450, Dish.Type.FISH) );
List<String> threeHighCaloricDishNames =
menu.stream() //从menu源中获得流
.filter(d -> d.getCalories() > 300) //操作 链路流水线相连
.map(Dish::getName) //操作
.limit(3) //操作
.collect(toList()); //终端操作 将stream转化成另一种形式,开始执行中间操作,返回元素序列
System.out.println(threeHighCaloricDishNames);
}
}
其中操作分为中间操作和终端操作。中间操作后返回流,n个中间操作形成流水线,直至终端操作被调用;终端操作将流转为集合输出。常用的中间操作有:filter、map、limit、sorted、distinct,利用流延迟、短路(limit、matchAny、findAny)特性,可根据需求选择调用恰当API,提高系统性能;常用的终端操作有:forEach、count、collect
二、流与集合
集合:如同DVD光盘,所有数据先load到容器中(内存数据结构,先装满,在开始操作);通过外部迭代for循环获取元素。
流:视频流,需要时才会计算出需要的值(需求驱动,实时制造);只能被消费一次,处理完后(执行终端操作后,关闭流),从数据源再获得新的流重新操作;内部循环获取元素。
public class Stream2Collection {
//只能消费1次
@Test
public void test(){
List<String> title = Arrays.asList("Java8", "In", "Action");
Stream<String> s = title.stream();
s.forEach(System.out::println);
s.forEach(System.out::println);//IllegalStateException: stream has alre