java8 新特性
注:此为复习笔记,查缺补漏,并非全部知识点讲解。
Lambda表达式
-
lambda表达式允许把函数作为一个方法的参数。使得代码结构更加紧凑。
- 通过函数描述符能描述lambda表达式的参数。如:
int example(Apple a1, Apple a2)
就可以表示为(Apple, Apple)->int
。 - 传递行为正是Lambda的拿手好戏。
- 通过函数描述符能描述lambda表达式的参数。如:
-
lambda主要用来定义行内执行的方法类型接口。
-
lambda表达式支持三种使用方式。
- 直接使用,定义一个方法后,使用变量名.方法名的方式调用。
- 通过将接口类型定义在方法参数中,在方法实现中调用该接口中的方法,在将实现接口方法的变量名传入该方法作为参数。
- 同2中在方法参数中定义接口类型,但是在调用时不传入变量名,而是直接写一个lambda表达式。
public class Note { interface Calculation{ //接口中只能有一个抽象方法,接口默认方法不算抽象,重写了Object类的也不算抽象(任何类中都有实现)。 int cal(int a, int b); } public static void main(String[] args) { // 方式1 Calculation add = (a,b) -> a+b; int r1 = add.cal(10, 20); System.out.println(r1); // 方式2 Note note = new Note(); Calculation subtraction = (int a, int b) -> {return a-b;}; int r2 = note.cal(10, 20, subtraction); System.out.println(r2); // 方式3 Note note2 = new Note(); int r3 = note2.cal(10, 20, (m,n)->m*n); //变量名既与接口中方法定义的无关,也与调用的方法参数中写的无关,只是个形参 System.out.println(r3); } public int cal(int x, int y, Calculation calculation){ return calculation.cal(x, y); } }
-
lambda表达式只能引用标记了final的外层局部变量。也即是表达式内部不能修改外部的值。
默认方法
- 默认方法也就是接口可以去实现方法,而不需要是实现类去实现。
- 好处:之前为了修改接口的功能,所有实现类都要去修改。使用默认方法后,只改接口就好。
- 原因:引进默认方法是为了不与之前发布的代码形成冲突。有新特性需要接口增加方法,但是会与已发布的代码冲突,没法实现新的接口方法。所以引入了接口默认方法,直接在接口中实现即可,不需要修改原有代码。
- 使用方法:加上
default
关键字,对于实现的多接口相同的默认方法,可以自己重写一个,或者使用super调用具体的某一个(接口.super.方法();
) - 接口还可以声明静态接口方法。
函数式接口
- 简单来说,只有一个抽象方法的接口就是函数式接口。接口默认方法不算抽象,重写了Object类的也不算抽象(任何类中都有实现)。
- Java中提供了一些函数式接口:Comparatot、Runnalble、ActionListener、Callable、PrivilegedAction…
方法引用
-
方法引用通过方法名来指向一个方法。
-
采用方法引用的方式是为了简化lambda表达式的写法。
-
lambda表达式可用方法引用代替的场景可以简要概括为:lambda表达式的主体仅包含一个表达式,且该表达式仅调用了一个已经存在的方法。方法引用所使用方法的入参和返回值与lambda表达式实现的函数式接口的入参和返回值一致,也即是函数描述符要一致。
-
方法引用有四种不同的方式:
调用方式 使用方式 使用场景 1. 静态方法引用 ClassName :: staticMethodName lambda表达式主体仅调用了某个类的静态方法 2. 构造器引用 ClassName :: new lambda表达式仅调用了某个类的构造函数返回实例 3. 类的任意对象的实例方法引用 ClassName :: instanceMethodName lambda表达式第一个入参为调用者,后续参数与实例方法参数一致,也即是接口中的方法比实例方法多一个参数为调用者 4. 特定对象的实例方法引用 object :: instanceMethodName lambda表达式仅调用了某个对象的某个实例方法
Stream
- 能够让程序员以声明的方式处理数据源(集合、数组等)。核心观点是将数据源看作流(Stream),在管道(Pipeline)中传输和运算,支持包含筛选、排序、聚合等,到达终点时便得到最终结果。
- 支持并行操作,且不用写多线程代码。
- foreach(Cunsumer<? super T> action) 函数的参数是Cumsumer消费者类型(一种能够对传入数据进行处理,没有返回值的接口)。功能是变量数组中的每一个元素
- map(Function mapper) 函数的参数是函数式接口对象,功能是将流中所有元素用Function计算后返回一个新的流(类型有可能改变)
- filter(Predicate<? super T> predicate) 函数的参数也是个函数式接口
- reduce(BinaryOperator<T> accumulator) 参数是一个累加器,返回一个Optional对象。
- collect(Collector collector) 参数是一个工具类,提供了很多归约的静态方法,如toList()、toSet()等。能将Stream流转换成List、Set。