淅奇妈的笔记干货来啦~
一、环境配置支撑:java 11 JDK,Lambok插件,以IDEA为例,确保Annotation Processors中Enable annotaion processing勾选,Lambok plugin中各项勾选。
二、概念及特点:
概念:函数编程强调结果而不是执行过程,利用若干简单的执行单元使得计算结果不断逐层运算。每一次计算都使用上一次计算的结果,函数使用可以更简单处理和更专注于代码逻辑。
特点:a)使用函数不会改变入参函数值; b)函数参数可以多个,返回值也可以是一个函数;
例子1:
.skip(1)跳过一个元素,.peek打印出每个元素,.collection最后收集成一个新的集合。
orderList.stream()
.skip(1)
.peek(name->log.debug("order:{}",order.getOrderId()))
.collection(Collectors.toList());
例子2:
取除了玩具类的,价格前三的订单编码,并输出:
.filter过滤玩具类,.sorted价格倒序,.limit(3)限制前三,.map(Order::getOderId)取订单编码,.distinct去重,.forEach循环遍历打印输出
order->{...}是Lamda表达式的写法,->左边是参数列表,右边是函数体
Order::getOderId方法引用,class::method
orderList stream()
.filter(order->{"玩具".equals(b.getOrderTypeName)})
.sorted((order1,order2)->order2.getPrice().compareTo(order1.getPrice()))
.limit(3)
.map(Order::getOderId)
.distinct()
.forEach(System.out::println);
三、语法:
Lamda表达式,方法引用 class::method:
1、静态方法引用
//调用订单类B中的静态查询方法,Combine中会对数据进行去重
//Combine combine = (a,b)->OrderB.findOrder(a,b);
Combine combine = (a,b)->OrderB::findOrder;
2、参数方法引用
//BinFuntion是一个函数式接口,支持输入两个参数,返回一个参数
//BiFunction<String.String,Interger> param = (a,b)->a.indexOf(b);
BiFunction<String,String,Interger> param = String::indexOf;
3、实例方法引用
/*构建流使用.builder().build();
Supplier是一个函数式接口,提供者,其接口方法get();*/
Order order = Order.builder().orderTypeName("玩具").build();
//Supplier<String> supplier = ()->order.getOrderTypeName();
Supplier<String> supplier = order::getOrderTypeName;
4、构造器引用
//Supplier<Order> supplier = ()->new Order();
Supplier<Order> supplier = Order::new;
四、函数式接口
有且仅有一个为实现的非静态方法的接口叫做“函数式接口”。以下是jdk提供的一些接口
Function函数,Function<入参类型,出参类型>
//Function表示一个函数,Function<入参类型,出参类型>
Function<Long,Long> num = (value)->value + 3 //此步还没有真正修改值
Long resultNum = num.apply((long)8);//真正赋值
Predicate函数,只取一个值作为参数,并返回true或false
Predicate<Object> predicate = (value)->null != value;
UnaryOperator函数,入参和出参类型相同
UnaryOperator<Order> unaryOperator = (order)=>{
order.setName("玩具");
return order;
}
BinaryOperator函数,两个入参返回一个值得操作
BinaryOperator<Long> num = (a,b)->a+b;
Supplier函数,提供商、提供值
Supplier<Interger> supplier = ()=>(int)(Math.random()*1000D);
Consumer函数,一个入参但不返回任何值
Consumer<Interger> consumer = (value)->log.debug("{}",value);
注:函数之间可以组合,例如and/or/compose/andthen等
Function<Interger,Interger> a = (value)->value*value; Function<Interger,Interger> b = (value)->2*value; //组合执行,先执行b,再执行a Function<Interger,Interger> aAndB = a.compose(b)
五、流创建
第一种方式:Arrays.stream
//创建流,arrayList数组转换成流
Array.stream(arrayList)
.peek(order=>log.debug("order:{}",order))//打印
.collect(Collectors.toList())//重新装入新集合
//比较两组集合的长度
assertEquals(arrayList.size(),newList.size());
第二种方式:Collection.stream
/*
底层实现:StreamSupport.stream(spliterator(),false);
代码实现: val itr = orderList.iterator(); -- 将list集合放入迭代器,利用迭代器生成流
Spliterator<Order> spliterator.spliteratorUnknownSize(itr,Spliterator.NONNULL);
Stream<Order> orderStream = StreamSupport.stream(spliteratorfalse);
val list = orderStream.peek(order->log.debug("order:{}",order))
.collect(Collectors.toList());
*/
//创建流
val list = orderList.stream()
.speek(order->log.debug("order:{}",order))
.collect(Collectors.toList());
第三种方式:Stream.of
//括号中可以任意数组下标的元素组成集合,也可以直接给整个数组集合或者重新实例一个新的
val list = Stream.of(arrayList[0],arrayList[1],arrayList[3])
.speek(order->log.dubug("order:{}",order))
.collect(Collectors.List());
第四种方式:Stream.iterate【迭代器】
val list = Stream.iterate(0,n->n+1)
.limit(10)
.speek(order->log.dubug("order:{}",order))
.collect(Collectors.toList());
第五种方式:Stream.generate【可以理解成工厂方法】,以随机数为例
val list = Stream.generate{()->Math.random()}
.limit(10)
.speek(order->log.debug("order:{}",order))
.collect(Collectors.toList());
第六种方式:IntStream【整型流】
val list = IntStream(0,5)//(0,5)左闭右开,左边包含右边不包含
.boxed()//boxed转换成对象,Stream<Interger>
.peek(i->log.debug("num:{}",i))
.collect(Collectors.toList());
第七中方式:Stream.builder()
Stream.Builder<Order> sb = Stream.builder();
val list = sb.add(arrayOfOrders[0])
.add(arrayOfOrders[1])
.add(arrayOfOrders[2])
.build()
.skip(1)//第1个元素不要
.peek(order->log.debug("order:{}",order.getOrderId))
.collect(Collectors.toList());
六、常用基本操作符
1、中间操作符:filter,map【可多个使用,做值的变换】,peek,findAny【返回任意一个】,findFirst
2、终端操作符:forEach,anyMatch【任何匹配】,noneMatch【任何不匹配】,count,min,max
例:findFirst
//查玩具订单中价格最高的一个
val first:Optional<Order> = orderList.stream()
.filter(order->order.getOrderName().equals("玩具"))
.sorted((order1,order2)->order2.getPrice().comparaTo(order1.getPrice()))
.findFirst()
asserTrue(first.ispresent());//.ispresent()判断是否有值
例:forEach
/*
//原写法
for(Order order: orders){
order.setOrderState("1"));
}
assertTrue(orderList.get(1).isEnabled());
*/
aList.stream().forEach(order->order.setOrderState("1"));
例:anyMatch
//查找编码满足10023开头的订单
//val existed:Object = orderList.stream()
// .filter(order->order.getOrderId().startsWith("10023")).count()>0
predicate<Order> orderAnyMaths = order->order.getOrderId().startsWith("10023");
val existed:Object = orderList.stream()
.anyMath(orderAnyMaths);
/*
.anyMath(...)等同于.filter(...).count()>0,
但.anyMath相比.filter(...).count()>0具有短路的优势
*/
例:max
Optional<Order> priceMax = orderList.stream()
.max(Comparator.comparing(Order::getPrice()));
assertTrue(priceMax.ispersent());