lambda表达式由来已久,Scala中lambda的使用是家常便饭,而在java8中,也引进了lambda及stream的使用。
1. lambda
什么是lambda表达式?
Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。 ——百度百科
我理解,lambda匿名函数就是能够像操作对象一样操作函数这个实体,即可以定义 Function f = (…)
而这个Fcuntion
类型,在java种,有四种大类型。
- java.util.function.Function
标准的函数,方法:
- R apply(T t) – 执行该函数(传入参数t)主要。
- Function<V, R> compose(Function<? super V, ? extends T> before) – 先执行传入的before函数,再将before函数的结果传入本函数执行。
- Function<T, V> andThen(Function<? super R, ? extends V> after) – 与compose相反,先执行自身,再将返回值作为参数传入after函数执行。
Function<Integer,Integer> increment = a->a+1;
System.out.println(increment.apply(1));
- java.util.function.Consumer
消费类函数,顾名思义用于消费,接收参数进行消费而没有返回值。
- void accept(T t) – 执行本函数,函数接收参数t。
- andThen – 与上方Function.andThen形似,只不过参数是Consumer,不再重复。
Consumer<Integer> printer = (b) -> System.out.println(b);
printer.accept(2);
- java.util.function.Supplier
供给类函数,与Consumer相反,它不接收参数,只返回结果。可以理解为一个工厂。
- T get() – 返回一个Object。
Supplier<Integer> factory = ()->3;
System.out.println(factory.get());
- java.util.function.Predicate
Predicate可能比较难理解,直接翻译是谓语
的意思,但是翻译为判断条件
也许更好理解。在之后与stream的结合使用种,Predicate的场景将会展现出来。
- boolean test(T t) – 传入参数,返回boolean,主要
- Predicate and(Predicate<? super T> other) – 传入一个Predicate,与当前函数做&&操作。
- Predicate negate() – 对当前函数的结果取反。
- Predicate or(Predicate<? super T> other) – 传入一个Predicate,与当前函数做 || 操作。
Predicate<Integer> isGreaterThanOne = (a) -> a>1;
Predicate<Integer> isLessThanThree = (a) -> a<3;
System.out.println(isGreaterThanOne.and(isLessThanThree).test(2));
2. stream
stream与四大function配合使用才是lambda的精髓。
java中的stream一般是Collection的实现类可以使用的,可以通过 collection.stream()得到。而stream的操作中,又分为两种:中间操作/终止操作。
当一个collection进行中间操作时,实际上时不会发生任何数据计算的,一个中间操作还会继续将Stream对象返回。只有执行终止操作才会真正进行打通
整个流程,完整的执行中间操作与终止操作。
- 中间操作:
filter() -> 使用Predicate进行过滤
map() -> 使用Function进行转换,得到一个自定义数据结构
flatMap() -> 将多个collection压平
distinct() -> hasCode去重
sorted() -> 排序
peek() -> 类似map,区别是使用Consumer
limit() -> 限制获取/计算的行数
skip() -> 跳过多少行 - 终止操作:
forEach() -> 使用Comsumer遍历处理每一个元素
forEachOrdered() -> 顺序的forEach
toArray() -> 转为Arr
reduce() -> 对stream中的数据进行累加计算(不一定是加法)
collect() -> 收集器,很灵活,可以收集为各种集合。
min() -> 取最小值
max()-> 取最大值
count() -> 计数
anyMatch() -> 只要匹配一条,传入Predicate
allMatch() -> 类似上面的,匹配全部元素
noneMatch() -> 类似上面的,所有元素都不匹配
findFirst() -> 获取流中第一个元素,得到一个Optional对象
findAny() -> 任意获取一个元素,得到一个Optional对象
举个例子
- 以最常用的map举个例子:
// TO 将Integer的list转化为String
List<Integer> raw = Lists.newArrayList(1,2,3);
// 定义转换函数
Function<Integer,String> map = integer->integer+"";
// 进行转换
List<String> strs= raw.stream().map(map ).collect(Collectors.toList());
- 再举个filter的例子,大家可以感受一下Predicate与stream结合的强大:
// TODO 找到list中,是1或大于2的,并且不是3的所有元素
List<Integer> raw = Lists.newArrayList(1,2,3,4);
Predicate<Integer> isOne = a->a.equals(1);
Predicate<Integer> greaterThanTwo = a->a.equals(2);
Predicate<Integer> isThree = a->a.equals(3);
List<Integer> result = raw.stream().filter(isOne.or(greaterThanTwo).and(isThree.negate())).collect(Collectors.toList());