2021-03-24

函数式接口Lambda以及Stream流的总结

一、Lambda表达式概念

lambda表达式是JAVA8中提供的一种新的特性,它支持JAVA也能进行简单的“函数式编程”。
它是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda 是一个匿名函数,可以把 Lambda表达式 理解为是一段可以传递的代码 (将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升 ,JDK 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。

二、函数式接口

函数式接口在Java中是指:有且仅有一个抽象方法的接口。
函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。

Lambda表达式是单一抽象方法接口(函数式接口)的语法糖,如果一个接口只有一个方法需要实现,就可以使用Lambda表达式实例化这个接口

语法糖

是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部类的“语法糖”,但是二者在原理上是不同的

1.1函数式接口的定义

在这里插入图片描述

1.2自定义函数式接口

1.2.1lambda作为方法的参数

在这里插入图片描述

1.2.2lambda表达式作为方法的返回值

在这里插入图片描述

1.3常用的函数式接口

1.3.1 Supplier接口

java.util.function.Supplier 接口仅包含一个无参的方法:T get()。用来获取一个泛型参数指定类型的对 象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要 “对外提供” 一个符合泛型类型的对象数据。

在这里插入图片描述

1.3.2Consumer接口

java.util.function.Consumer 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据, 其数据类型由泛型决定。

抽象方法:accept
Consumer 接口中包含抽象方法 void accept(T t) ,意为消费一个指定泛型的数据
在这里插入图片描述

默认方法:andThen
如果一个方法的参数和返回值全都是 Consumer 类型,那么就可以实现效果:消费数据的时候,首先做一个操作, 然后再做一个操作,实现组合。而这个方法就是 Consumer 接口中的default方法 andThen 。下面是JDK的源代码:
default Consumer andThen(Consumer<? super T>after){
Objects.requireNonNull(after);
return(T t) ‐>{
accept(t);after.accept(t);
};
}
在这里插入图片描述

1.3.3Predicate接口

有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用java.util.function.Predicate接口。
抽象方法:test
Predicate接口中包含一个抽象方法:boolean test(T t)。用于条件判断的场景:
在这里插入图片描述
默认方法:and
既然是条件判断,就会存在与、或、非三种常见的逻辑关系。其中将两个Predicate条件使用“与”逻辑连接起来实现**“并且”**的效果时,可以使用default方法 and 。

在这里插入图片描述
默认方法:or
与 and 的“与”类似,默认方法 or 实现逻辑关系中的“或”。JDK源码为:

default Predicate or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) ‐> test(t) || other.test(t); }

如果希望实现逻辑“字符串包含大写H或者包含大写W”,那么代码只需要将“and”修改为“or”名称即可,其他都不变:
在这里插入图片描述

1.3.4Function接口

java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件, 后者称为后置条件。
抽象方法:apply
Function 接口中最主要的抽象方法为:R apply(T t),根据类型T的参数获取类型R的结果。 使用的场景例如:将 String 类型转换为 Integer 类型。
在这里插入图片描述
默认方法:andThen
该方法同样用于“先做什么,再做什么”的场景,和 Consumer 中的 andThen 差不多:
在这里插入图片描述

三、stream流

java8新增新特性,在我接触到java8流式处理的时候,我的第一感觉是流式处理让集合操作变得简洁了许多,通常我们需要多行代码才能完成的操作,借助于流式处理可以在一行中实现。
stream()操作将集合转换成一个流,filter()执行我们自定义的筛选处理,这里是通过lambda表达式筛选出所有偶数,最后我们通过collect()对结果进行封装处理,并通过Collectors.toList()指定其封装成为一个List集合返回。
在这里插入图片描述

1.3.1forEach

虽然方法名叫forEach,但是与for循环中的“for-each”昵称不同
void forEach(Consumer<? super T> action);
该方法接收一个Consumer接口函数,会将每一个流元素交给该函数进行处理
在这里插入图片描述

1.3.2过滤filter

java8提供的筛选操作包括:filter、distinct、limit、skip。

其定义为:
Stream filter(Predicate<? super T> predicate)

filter接受一个谓词Predicate,我们可以通过这个谓词定义筛选条件,在介绍lambda表达式时我们介绍过Predicate是一个函数式接口,其包含一个test(T t)方法,该方法返回boolean。现在我们希望从集合students中筛选出所有武汉大学的学生,那么我们可以通过filter来实现,并将筛选操作作为参数传递给filter:

在这里插入图片描述

1.3.3映射map

在这里插入图片描述
在这里插入图片描述

1.3.4count计数方法

在这里插入图片描述

1.3.5取用前几个:limit

limit方法可以对流进行截取,只取用前n个,方法签名:
Stream limit(long maxSize);
在这里插入图片描述

1.3.6跳过前几个:skip

如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流:
Stream skip(long n);
在这里插入图片描述

1.3.7组合:concat

如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concat:
static Stream concat(Stream<? extends T> a,Stream<? extends T> b)
备注:这是一个静态方法,与java.lang.String当中的concat方法是不同的
在这里插入图片描述
到这里Lambda和函数式接口以及Stream流就大致总结完了
供大家参考,别忘点赞!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值