概念

面向对象思想关注用什么对象完成什么事情。而函数式编程思想就类似数学中的函数。它关注的是对数据进行了说明操作。(类似把具体的操作代码通过参数的形式传递进去)

好处

为了看懂公司大佬写的代码。
大数据量下处理集合效率高
代码可读性高
减少嵌套

Lambda表达式

Lambda是JDK8中的语法糖,它可以对某些匿名内部类的写法进行简化。它是函数式编程思想的一个重要体现。让我们不用关注是什么对象,而是更关注我们对数据进行了什么操作。写Lambda记得看底层源码。
关注的是参数列表和具体的逻辑代码体

省略规则:

参数类型可以省略
方法体中只有一句代码时大括号return和唯一一句代码的分号可以省略
方法只有一个参数时小括号可以省略

Steam流

流不会影响原数据(我们在流中可以处理很多数据,但是正常情况下是不会影响到原来集合中的元素的。)

流代码分为三步:

1.创建流
2.中间操作
map()方法中的第一个泛型不能改(第一个类型就是对象的元素,已经是定义好的,不能修改不然会报错),但是第二个泛型是可以修改的(可以修改为想要的数据类型),简单理解为就是把流当中的元素转换为另外一种元素类型然后再放到流中。
mapToInt() 高级用法…..还有mapTOLong()等等,针对基本数据类型进行优化。
流中的distinct()是依赖Object中的equals方法来判断是否为相同对象的。所以使用distinct方法需要重写equals方法;
limit()用法(截取个元素)
skip()用法(跳过第
个元素)
流中的sorted()是需要对象去实现是Comparable接口,不然会抛出ClassCastException异常。实现有两种方式,一种是在操作的对象中实现,第二种是通过匿名内部类的方式去实现。
flatMap()可以把一个对象转换为多个对象放到流中。
3.终结操作
流必须要要有终结操作,否则无法执行。流被终结以后无法再次使用。
forEach() 对流中的元素进行遍历操作。
count() 返回此流中元素的计数。
max() min() 获取流中的最值。
collect() 是将流中的元素转为一个集合。
anyMatch() 根据逻辑判断返回布尔值。
allMatch() 可以用来判断是否都符合逻辑判断条件,返回布尔值。
noneMatch() 可以用来判断是否都卢符合逻辑判断条件,返回布尔值。
findAny() 查找流中的任意一元素该方法无法保证获取的元素一定是流中的第一个元素。
ifPresent() 如果Optional对象不为null则继续往下执行。为null就不继续往下执行。
findFirst()获取流中的第一个元素。
reduce()传入一个参数,循环流中元素进行操作(可以对传入的参数进行比较等操作),并返回一个传入参数类型的数据。reduce两个参数的重载形式内部的计算方式如下:

T result = identity;
for(T element : this stream){
result = accumlator..apply(result,element);
}
return result;

Optional

养成使用Optional的习惯可以写出更加优雅的代码来避免空指针异常。
实际开发过程中很多数据是通过数据库来获取的,Mybatis从3.5版本以后也支持Optional了。可以直接把dao方法的返回值类型定义为Optional类型,Mybatis会自己把数据封装为Optional对象返回。封装的过程也不需要我们自己去操作。
很多函数式编程相关的API都用了Optional。
Optional.ofNullable() 将对象封装为Optional对象。无论传入的参数是否为null都不会出现问题。(建议使用 )
Optional.of() 传入的参数必须不能为null。(不建议使用)
Optional.empty() 返回一个空的Optional对象。
Optional.ifPresent() 该方法会判断其内部封装的数据是否为空,不为空的时候才能执行具体的消费代码。
Optional.isPresent() 该方法会判断其内部封装的数据是否为空,为空返回false,不为空返回true.
Optional.filter() 在方法中进行逻辑判断,如果满足会返回Optional对象;不满足则返回null.
Optional.map() 将对象中的值转为Optional>对象.

如果想要安全的获取Optional对象中的值,不推荐使用get()方法。推荐使用以下几种方法。
Optional.orElseGet() 如果Optional中的值为null,可以自定义返回一个对象。
Optional.orElseThrow() 如果Optional中的值为null,可以手动抛出异常。

函数式接口

JDK的函数式接口中都加上了
@FunctionalInterface注解进行标识,无论是否加上该注解只要接口中只有一个抽象方法,都是函数式接口。
JDK自带的常用函数式接口
Comparator 消费接口
Function 计算转换接口
Predicate 判断接口
Supplier 生产型接口
函数式接口中的默认方法

方法引用

方法引用的基本格式
类名或对象名::方法名
写完Lambda表达式以后,发现方法体只有一行代码,并且方法调用时候使用Idea快捷键能够转换成方法引用即可。

高级玩法

  1. **map() **方法中的第一个泛型不能改(第一个类型就是对象的元素,已经是定义好的,不能修改不然会报错),但是第二个泛型是可以修改的(可以修改为想要的数据类型),简单理解为就是把流当中的元素转换为另外一种元素类型然后再放到流中。
  2. **mapToInt() **高级用法.....还有mapTOLong()等等,针对基本数据类型进行优化。

并行流

当流中有大量元素,可以使用并行流提高操作效率。其实并行流就是把任务分配给多个线程去完成。如果使用Stream的话,只需要修改一个方法的调用就可以使用并行流来提高效率
Stream.parallel()方法