注意:该文章总结于某站---三更草堂视频,文章仅用于自己学习总结
1. 概述
1.1 为什么学?
- 目前主流技术,大部分公司在使用,更好的阅读企业中的代码。
- 大数量数据下处理集合效率高。
- 代码可读性高。
- 消除多级嵌套。
1.2 函数式编程思想
1.2.1 概念
面向对象需要关注的是用什么对象完成什么事情。而函数式编程思想就类似于我们数学中的函数。它主要关注的是对数据进行了什么操作。
1.2.2 优点
- 代码简洁,开发快速
- 接近自然语言,易于理解
- 易于并发编程
2. Lambda表达式
2.1 概述
Lambda是JDK8中的一个语法糖。他可以对某些匿名内部类的写法进行简化。他是函数式编程思想的重要体现。让我们不用关注是什么对象。而是更关注我们对数据进行了什么操作。
2.2 核心原则
可推导可省略
2.3 基本格式
(参数列表)-> {代码}
例子:
2.4 省略规则
- 参数类型可以省略
- 方法体只有一句代码时大括号return和唯一一句代码的分号可以省略
- 方法只有一个参数时小括号可以省略
- 以上这些规则记不住也可以选择不省略
3. Stream流
3.1 概述
Java8的Stream使用的是函数式编程模式,如同它的名字一样,他可以被用来对集合或者数组进行链状流式的操作。可以更方便的让我们对集合或数组操作。
3.2 常用操作
3.2.1 创建流
3.2.2 中间操作
3.2.2.1 filter
可以对流中的元素进行条件过滤,复核过滤条件的才能继续留在流中
3.2.2.2 map
可以对流中的数据进行计算或者数据类型转换
3.2.2.3 distinct
可以去除流中重复的元素
3.2.2.4 sorted
可以对流中的元素进行排序
3.2.2.5 limit
可以设置流的最大长度,超出的部分将被抛弃
3.2.2.6 skip
跳过流中前n个元素,返回剩下的元素
3.2.2.7 flatMap
map只能把一个对象来做为流中的元素。而flatMap可以把一个对象转换成多个对象做为流中的元素。
3.2.3 终结操作
3.2.3.1 forEach
对流中的元素进行遍历操作,我们通过传入的参数去指定对遍历到的元素进行什么具体操作。
3.2.3.2 count
可以用来获取当前流中元素个数
3.2.3.3 max&min
可以用来获取流中的最值
3.2.3.4 collect
把当前流转换成一个集合
3.2.3.5 查找与匹配
anyMatch
可以用来判断是否有任意复核匹配条件的元素,结果为boolean类型
allMatch
可以用来判断是否都符合匹配条件,结果为boolean类型。如果都符合结果为true,否则结果为false。
noneMatch
可以判断流中的元素是否都不符合匹配条件。如果都不符合结果为true,否则结果为false
findAny
获取流中任意一个元素,该方法没有办法保证获取的元素一定是第一个。
findFirst
获取流中第一个元素。
3.2.3.6 reduce归并
对流中的数据按照你制定的计算方式计算出一个结果。
reduce的作用是把stream中的元素给组合起来,我们可以传入一个初始值,他会按照我们的计算方式一次拿流中的元素和在初始化值的基础上进行计算,计算结果再和后面的元素计算。
reduce一个参数:将第一个元素设置为初始值。
3.3 注意事项
- 惰性求职(如果没有终结操作,中间操作是不会得到执行的)
- 流是一次性的(一旦一个流对象经过终结操作后。这个流就不能再被使用)
- 不会影响原数据(我们在流中多数据做很多处理。但是正常情况下是不会影响原来集合中的元素的。这往往也是我们所期待的)
4. Optional
4.1 概述
我们在编写代码的时候出现最多的就是空指针异常。所有很多情况下我们需要做各种非空判断。
尤其是对象中的属性还是一个对象的情况下。这种判断会更多。
而过多的判断语句会让我们代码显得臃肿。
所有在JDK8中引入Optional,养成使用Optional习惯后你可以写出更优雅的代码来避免空指针。
并且很多函数式编程相关的API中也使用到了Optional,如果不会使用Optional也会对函数式编程学习造成影响。
4.2 使用
4.2.1 创建对象
Optional就好像是包装类,可以把我们具体数据封装Optional对象内部。然后我们去使用Optional中封装好的方法操作封装进去的数据可以非常优雅的避免空指针异常。
我们一般使用Optional的静态方法ofNullable来把数据封装成一个Optional对象。无论传入的参数是否为null都不会出现问题。
Author author = getAuthor();
Optional<Author> authorOptional = Optional.ofNullable(author);
你可能会觉得加一行代码来封装数据比较麻烦。但是如果改造下getAuthor方法,让其返回值就是封装好的Optional的话,我们在使用就会方便很多。
而且实际开发中我们的数据多是从数据库获取。Mybatis从3.5之后已经支持Optional。我们可以直接把dao方法返回值定义为Optional类型,Mybatis就会自己把数据封装为Optional对象返回。
如果你确定一个对象不为空的则可以使用Optional的静态方法of来把数据封装成Optional对象
Author author = new Author();
Optional<Author> authorOptional = Optional.of(author);
注意:如果使用of的时候传入的参数必须不为null。(为null会出现空指针异常,也可以使用of之前进行非空判断)。
4.2.2 安全消费值
我们获取到一个Optional对象后肯定需要对其中的数据进行使用。这个时候我们可以使用其ifPresent方法来消费其中的值
这个方法会判断其内封装的数据是否为空,不为空时才会执行具体消费代码,避免空指针异常。
Optional<Author> authorOptional = Optional.ofNullable(getAuthor());
authorOptional.ifPresent(author -> System.out.println(author.getName()));
4.2.3 获取值
如果我们想获取值自己进行处理可以使用get方法获取,但是不推荐。因为Optional内部的数据为空的时候未出现异常。
4.2.4 安全获取值
4.2.5 过滤
4.2.6 判断
4.2.7 数据转换
5. 函数式接口
5.1 概述
6. 方法引用
语法规则
类名或者对象名::方法名