00-Java8新特性
01. Java8 接口
- java8.0之前的接口组成
- 公开静态常量
- public static final 属性
- 公开抽象方法
- public abstract 方法
- 公开静态常量
- java8.0的接口组成
default 方法
static 方法
- java9.0的接口组成
private 方法
1.1 接口中的default方法
作用
- 解决接口下不同实现资料的功能扩展问题
不使用default方法
1 |
|
需要编写大量的子接口对新的功能进行维护。
使用default方法
1 |
|
- 哪一个实现子类需要对功能进行扩展,就重写default方法
1.2 接口中的static方法
- 格式
1 |
|
注意事项
- 接口中的静态方法只能通过接口名调用,不能通过接口的实现子类对象调用。
02. lambda表达式
Lambda表达式和匿名内部类对象的区别?
- 概念
- lambda表达式可以看作是匿名内部类对象的语法糖
- 区别
- 使用匿名内部类对象会产生三个class文件,使用lambda表达式会产生两个class文件;也就是说,使用lambda表达式,不仅仅只是语法的精简,还可以使程序的执行效率更加高效。
2.1 lambda使用场景
- 使用 Lambda 作为参数:开启线程
1 |
|
- 使用函数是接口作为返回值:数组排序
1 |
|
2.2 lambda日志案例
- 非lambda表达式
1 |
|
当日志级别不为1的时候是不需要打印日志的,但是依然对日志内容进行了拼接,这就影响了程序的执行性能
lambda表达式
1 |
|
- 使用lambda表达式,只有当日志级别为1的时候才会对日志内容进行拼接。
03. 函数式接口
概念
- 指的是只有一个抽象方法的接口
- 适用于函数式编程
- 在java中函数式编程就是lambda表达式,也就是说函数式接口适用于lambda表达式
语法糖
- 从语法使用上变得更加的方便
- 比如:增强for循环就是for循环一种语法糖,底层还是迭代器
- lambda表达式可以也是匿名内部类对象的语法糖,但是从原理上有着本质不同。
- 匿名内部类对象就是一个接口、类的子类对象。
格式
1 |
|
一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会
报错。需要注意的是,
即使不使用该注解
,只要满足函数式接口的定义,这仍然是一个函数式接口
,使用起来都一样。
- 优势
- 函数式接口比匿名内部类对象产生更少的字节码对象,提升java执行效率。
3.1 函数式接口基本使用
函数式接口作为方法参数,且接口中的方法没有参数
- MyFunctionalInterface02
1 |
|
- Demo02
1 |
|
函数式接口作为方法参数,且接口中的方法有参数
- MyFunctionalInterface03
1 |
|
- Demo03
1 |
|
函数式接口作为方法返回值,且接口中的方法有参数
- MyFunctionalInterface04
1 |
|
- Demo04
1 |
|
函数式接口的方法有返回值
- MyFunctionalInterface05
1 |
|
- Demo05
1 |
|
- 总结
1 |
|
- 可以省略参数类型
- 如果方法体只有一行代码,方法体的大括号可以省略
- 如果方法体只有一行代码,且是一个返回语句,那可以省略return
3.2 预定义的函数式接口
- 概念
- java已经内置的一些函数式接口,这些接口都有特定的作用。
- 常用函数式接口
- Supplier接口
- 对外提供数据
- Consumer接口
- 消费外部数据
- Predicate接口
- 对数据进行判断
- Supplier接口
3.3 Supplier接口
概念
- java.util.function.Supplier<T> 对外提供数据,该数据的类型由 Supplier 接口的泛型决定。
常用方法
- T get();
- 获取T类型的数据
- T get();
基本使用
1 |
|
- 综合案例
1 |
|
3.4 Consumer接口
概念
- Consumer接口是消费外部提供的数据
常用方法
- void accept(T t);
- 消费外部数据t
- default Consumer<T> andThen(Consumer<? super T> after)
- 用以串联多个消费动作
- void accept(T t);
代码实现
1 |
|
3.5 Consumer接口综合案例
需求
- 下面的字符串数组当中存有多条信息,请按照格式“ 姓名:XX。性别:XX。 ”的格式将信息打印出来。
- 要求将打印姓 名的动作作为第一个 Consumer 接口的Lambda实例
- 将打印性别的动作作为第二个 Consumer 接口的Lambda实例
代码实现
1 |
|
3.6 Predicate接口基本使用
概念
- 用以处理条件判断
常用方法
boolean test(T t);
* 进行两次判断,将两次判断的结果进行与操作1
2
3
4
5
6
7
8
* 判断数据t
* ```java
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}```java
default Predicatenegate() {
return (t) -> !test(t);
}1
2
3
4
5
6
7
8
* 进行取非操作
* ```
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}- 进行两次判断,将两次判断结果进行或操作
代码实现
1 |
|
3.7 Predicate综合案例
需求
- 将姓名长度为4,性别为女的信息保存并打印
代码实现
1 |
|
04. Stream流
概念
- 说到Stream便容易想到I/O Stream,而实际上,谁规定“流”就一定是“IO流”呢?
- 在Java 8 中,得益于Lambda所带 来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合 类库既有的弊端。
需求
- 筛选出姓张且名字长度为3的人名并打印
1 |
|
- 该 demo 作为开发者,不仅要关注做什么,同时还要关注怎么做!
1 |
|
- 该 demo 作为开发者,只需要关注做什么即可!
4.1 流式思想
概述
- 流式思想类似于工厂车间的“生产流水线”。
- Stream(流)是一个来自数据源的元 素队列 元素是特定类型的对象,形成一个队列。
- 数据源 流的来源。 可以是集合,数组等
获取Stream流
CollectionObj.stream
方法- 获取单列集合对应的Stream流对象
Stream.of
方法- 获取数组对应的Stream流对象
代码实现
1 |
|
4.2 Stream常用方法
方法分类
- 延迟方法
- 方法的返回值是Stream类对象;支持链式编程。
- 终结方法
- 方法的返回值不是Stream类对象;不支持链式编程。
- 延迟方法
常用方法
- 逐一处理:void
forEach
(Consumer<? super T> action)- 为 终结方法
- 给流中每一个元素执行一个动作
- 动作是什么,由Consumer接口决定
- 为 终结方法
- 过滤处理:Stream<T>
filter
(Predicate<? super T> predicate)- 为 延迟方法
- 返回一个能够匹配Predicate接口条件的流
- 为 延迟方法
- 统计个数:long
count
()- 为 终结方法
- 返回流中的元素数量
- 为 终结方法
- 取前几个:Stream<T>
limit
(long maxSize)- 为 延迟方法
- 获取流中前maxSize个元素
- 为 延迟方法
- 跳过几个:Stream<T>
skip
(long n)- 为 延迟方法
- 获取跳过n个元素之后的元素
- 为 延迟方法
- 将流组合:Stream<T>
concat
(Stream<? extends T> a, Stream<? extends T> b)- 为 延迟方法
- 将两个流合并成一个新的流
- 为 延迟方法
- 逐一处理:void
4.3 Stream综合案例
需求
- a. 第一个队伍只要名字为3个字的成员姓名;
- b. 第一个队伍筛选之后只要前3个人;
- c. 第二个队伍只要姓张的成员姓名; s
- d. 第二个队伍筛选之后不要前2个人;
- e. 将两个队伍合并为一个队伍;
- f. 打印整个队伍的Person对象信息
代码实现
1 |
|
- 注意事项
- 当一个Stream调用终结方法后,Stream处于关闭状态,就不能再去调用Stream类的方法了。
00-Java8新特性
https://janycode.github.io/2016/04/30/02_编程语言/01_Java/02_Java8/00-Java8新特性/