文章目录
-
- 1. lambda表达式
-
- 1.1 什么是lambda表达式?
- 1.2 lambda表达式的重要特征?
- 1.3 lambda表达式对域外变量的限制?
- 1.4 lambda表达式的优缺点?
- 1.5 lambda表达式的使用场景?
- 1.6 lambda表达式的实现原理?
- 2. 函数式接口
-
- 2.1 什么是函数式接口?
- 2.2 Java8中提供的函数式接口有哪些?
- 3. 方法引用
-
- 3.1 什么是方法引用?
- 3.2 方法引用有哪几种类型?
- 4. 接口的默认方法和静态方法
-
- 5. 重复注解
-
- 5.1 Java8中引入的重复注解是什么,怎么使用?
- 6. Stream
-
- 6.1 什么是Stream?
- 6.2 创建Stream的几种方式?
- 6.3 Stream的中间操作有哪些?
- 6.4 Stream的终止操作有哪些?
- 6.5 Stream的并行流?
- 6.6 Stream的注意事项?
- 7. Optional
-
- 7.1 什么是Optional容器?
- 7.2 Optional容器创建方式有哪些?
- 7.3 Optional的API有哪些?
- 8. 新的日期时间类
-
- 8.1 Java8中新的日期时间类有哪些?
- 8.2 新的日期时间类比老版有什么优势?
1. lambda表达式
1.1 什么是lambda表达式?
lambda表达式是Java8提供的新特性之一,也可以称之为闭包;它支持Java能够进行简单的函数式编程
,也就是说可以把一个匿名函数作为一个方法的参数进行传递;其格式分为三部分,第一部分为入参列表,第二部由->
固定组成,第三部分为方法体;
1.2 lambda表达式的重要特征?
- 可选的参数类型声明;
- 可选的参数圆括号;
- 可选的大括号;
- 可选的返回关键字;
1.3 lambda表达式对域外变量的限制?
lambda表达式对域外的局部变量具有隐性final语义的限制,但对成员变量没有该限制;
1.4 lambda表达式的优缺点?
- 优点
- 使代码更加简洁;
- 减少匿名内部类的创建,节省资源;
- 缺点
- 可维护性差,必须熟悉抽象方法的参数列表;
- 可读性差,必须对lambda表达式有一定深入;
1.5 lambda表达式的使用场景?
在声明方法时,方法的形参列表包含一个或者多个函数式接口就可以使用lambda表达式;
如:
使用实现Runnable接口创建线程;
使用实现Callable接口创建FutureTask;
使用四大函数式接口消费者接口Consumer、提供者接口Supplier、断言型接口Predicate、函数型接口Function;
1.6 lambda表达式的实现原理?
lambda表达式是通过特定的语法,让编译器对java文件进行编译时,针对每一个lambda表达式会编译成一个对应的静态方法,由此也可证明lambda表达式并不是一种语法糖;
2. 函数式接口
2.1 什么是函数式接口?
函数式接口指有且仅有一个抽象方法(由Object对象继承的方法不算)(但可以有多个默认方法和静态方法)的接口,当这样的接口在作为方法参数时可以隐式的转换为lambda表达式;但是在实际项目中函数式接口表现得非常脆弱,所以Java8也提供了一个标计在接口上的注解@FunctionalInterface
去显示说明该接口是函数式接口;
2.2 Java8中提供的函数式接口有哪些?
- java.lang.Runnable
- java.util.concurrent.Callable
- java.util.Comparator
- java.util.function.*
3. 方法引用
3.1 什么是方法引用?
方法引用其实是lambda表达式的升级写法,采用::
固定语法,可以使代码更简洁、紧凑;
3.2 方法引用有哪几种类型?
-
对象引用::实例方法名
函数式接口抽象方法的形参列表与实例方法的一致,且方法的返回值类型一致;
-
类名::静态方法名
函数式接口抽象方法的形参列表与静态方法的一致,且方法的返回值类型一致;
-
类名::实例方法名
函数式接口抽象方法的第一个参数是实例方法所在类的对象,剩下的参数(或无参)是实例方法的入参,且方法的返回值类型一致;
-
类名::new
函数式接口抽象方法的形参列表与类的构造方法的一致,且抽象方法返回的类型是该类名的类型;
-
类名[]::new
函数式接口抽象方法的参数是int类型或者Integer类型,表示数组长度,抽象方法的返回值类型是该类名类型的数组;
4. 接口的默认方法和静态方法
4.1 接口的默认方法与静态方法的区别是什么?
- 默认方法用
default
关键字修饰,静态方法用static
关键字修饰;
- 默认方法子类可以选择性重写,静态方法不能被重写;
- 默认方法通过接口的实现类实例调用,静态方法通过接口类名调用;
- 当实现类拥有多个父类接口,且多个父类接口含有相同的默认方法时,实现类则必须重写该默认方法,否则会出现编译错误;
- 实现类对于多层父类接口的默认方法采用就近原则继承;
5. 重复注解
5.1 Java8中引入的重复注解是什么,怎么使用?
Java8中引入的一个新注解@Repeatable,该注解只能标记在其他注解上,表示被标记的注解可以重复声明在类、属性、方法等上面;但@Repeatable注解还是得需要定义容器注解配合才能使用,所以也只是增强了代码的可读性;
6. Stream
6.1 什么是Stream?
一种支持顺序和并行聚合操作的元素序列,能够对集合、数组进行过滤、排序、去重等操作;
6.2 创建Stream的几种方式?
6.3 Stream的中间操作有哪些?
-
过滤
filter():对元素进行过滤;
distinct():对元素进行去重,必须重写元素的hashCode()和equals()方法;
-
切片
limit():截取前面n个元素;
skip():跳过前面n个元素,当流中元素个数不足n个时,将返回一个空流;
-
映射
map():对元素进行操作,转换为另一种类型;
flatMap():对元素进行操作,转换为一种Stream流;
-
排序
sorted():若元素实现了Comparable接口,重写了compareTo方法,则采用元素内部的方法比较,否则需要传入自定义的比较函数;
6.4 Stream的终止操作有哪些?
-
查找
findFirst():返回第一个元素,注意不是直接返回的元素对象,而是被Optional容器包装的元素对象;
findAny():返回任意一个元素,注意也是返回的被Optional容器包装的元素对象;
max():返回元素中的最大值,需要传入比较函数,注意也是返回的被Optional容器包装的元素对象;
min():返回元素中的最小值,需要传入比较函数,注意也是返回的被Optional容器包装的元素对象;
-
匹配
allMatch():是否所有元素都匹配;
anyMatch():是否有任意一个元素匹配;
noneMatch():是否所有元素都不匹配;
-
统计
count():统计流中元素个数;
-
遍历
forEach():遍历元素
-
归纳
reduce():按照自定义规则对元素进行聚合操作,并返回期待的结果;
-
收集
collect():将已操作过的元素收集起来,可返回List、Set、Map等等;
6.5 Stream的并行流?
- Stream流可以通过实例的parallel和sequential两个方法在并行流和顺序流之间切换;
- Stream并行流是以Java7引入的fork/join框架为基础,以递归方式将可以并行的任务拆分成更小的任务,然后将每个子任务的结果合并起来生成整体结果;
6.6 Stream的注意事项?
- Stream自己不会存储元素;
- Stream的中间操作不会改变源对象,相反它会返回一个持有结果的新Stream实例;
- Stream的中间操作是延迟加载的,只有当终止操作存在的时候,中间操作才会执行;
- Stream的执行实际上是每一个元素沿着执行链垂直移动的,也就是说当一个元素将执行链执行完成后才会开始第二个元素,但注意排序操作例外;
- Stream的实例在执行终止操作后不能再执行其他操作,否则会抛出
stream has already been operated upon or closed
异常;
7. Optional
7.1 什么是Optional容器?
Optional是Java8提供的一个容器对象,可以包含一个为null
或者不为null
的对象;使用该对象可以更方便的避免项目中的NPE,在新版的Spring Data JPA中已经实现了对该类的支持;
7.2 Optional容器创建方式有哪些?
- Optional.empty():创建一个包含null对象的Optional对象;
- Optional.of(T value):创建一个包含value对象的Optional对象,若value为null则抛出NullPointerException;
- Optional.ofNullable(T value):创建一个包含value对象的Optional对象,若value为null则返回包含null对象的Optional对象;
7.3 Optional的API有哪些?
- get():获取Optional对象中的值,若值为null则抛出NoSuchElementException异常;
- isPresent():判断Optional对象中的值是否不为null;
- ifPresent(Consumer super T> consumer):如果Optional对象中的值不为null,则将该值作为消费者接口的参数进行消费;
- filter(Predicate super T> predicate):如果Optional对象中的值不为null,则将该值作为断言接口的参数进行断言,断言成功时返回当前Optional对象,否则返回一个包含null值得Optional对象;
- map(Function super T, ? extends U> mapper):如果Optional对象中的值不为null,则将该值作为映射接口的参数进行映射,返回一个新的Optional对象;
- flatMap(Function super T, Optional> mapper):该方法与map方法基本一致;
- orElse():如果Optional对象中的值不为null,则返回该值,否则返回other;
- orElseGet(Supplier extends T> other):如果Optional对象中的值不为null,则返回该值,否则返回生产者接口返回的值;
- orElseThrow(Supplier extends X> exceptionSupplier):如果Optional对象中的值不为null,则返回该值,否则抛出异常生产者返回的异常;
8. 新的日期时间类
8.1 Java8中新的日期时间类有哪些?
- LocalDate:本地日期,不包含时区;
- LocalTime:本地时间,不包含时区;
- LocalDateTime:本地日期+时间,内部维护者一对LocalDate与LocalTime实例,同时也不包含时区;
- ZoneId:时区标识符,是Instant和LocalDateTime之间转换的规则;
- ZoneOffset:格林威治/UTC时间之间的时区偏移量;
- ZonedDateTime:一个包含得有时区标识符和时区偏移量的日期+时间类,内部维护者LocalDateTimeZoneId、ZoneOffset三个实例;
- Instant:一个可以精确到纳秒的时间戳类;
- DateTimeFormatter:日期时间格式化与解析类;
8.2 新的日期时间类比老版有什么优势?
- 新的日期时间实例都是不可变实例,每次修改都会返回一个新的实例,更方便使用;
- 新的日期时间类都是线程安全的;
- 新的日期时间实例获取年月日时分秒比老版更方便;
- 新的日期时间实例格式化与解析也比老版更方便;