0%

Java8

Java8特性

Lambda表达式

允许把函数作为一个方法的参数,将函数作为参数传递到方法中。

本质:函数式接口的实例,给接口提供一个实现类的对象时用到lambda表达式,要求接口只有一个抽象方法

以前用匿名实现类表示的,现在都可以用Lambda表达式来写。

语法说明 -> lambda 操作符 左边: lambda 形参列表,接口中的抽象方法的形参列表。参数类型可以省略,只有一个参数可以省略括号 右边: lambda 体,重写的抽象方法体。如果只有一条执行语句,可以省略大括号、return。

注意: 1.用来定义行内执行的方法类型接口。 2.免去了使用匿名方法的麻烦。

1
2
3
4
5
6
7
8
9
10
11
12
// 1.无参,无返回值
Runnable r2 = () -> System.out.print();
// 2.有参,无返回值
Runnable r2 = (String x) -> {System.out.print(x);}
// 3.数据类型可以省略,进行类型推断
Runnable r2 = (x) -> {System.out.print(x);}
// 4.参数的小括号可以省略
Runnable r2 = x -> {System.out.print(x);}
// 5.多个参数,多条执行语句,可以有返回值
Comparator<Integer> com = (x,y)->{return Integer.compare(x,y);}
// 6.只有一条执行语句,可以省略大括号和return
Comparator<Integer> com = (x,y)->Integer.compare(x,y);

函数式接口

有且仅有一个抽象方法,但可以有很多非抽象方法的接口。

之前用匿名实现类的表示,现在都可以用lambda表达式来写。

内置函数式接口
  1. 消费型 Comsumer,包含void accept(T t);
  2. 供给型接口 Supplier,包含T get();
  3. 函数型接口Function<T,R>,包含R apply(T t);
  4. 断言型接口Predicate,包含boolean test(T t);

方法引用

当要传递给Lambda体的操作,已经有实现的方法,可以使用方法引用。

本质上还是Lambda表达式,作为函数式接口的实例。

使用格式:类(或对象)::方法名

1
2
3
4
5
6
7
8
9
// 1.对象::实例方法
Comsumer<String> con = System.out :: println;
con.accept(String);
// 2.类::静态方法
Comparator<Integer> com = Integer :: compare;
com.compare(T1,T2);
// 3.类::实例方法
Comparator<Integer> com = String :: compareTo;
com.compare(T1,T2);

构造器引用

和方法引用类似,函数式接口的抽象方法的形参列表和构造器参数列表一致。

抽象方法的返回值类型即为构造器所属的类的类型。

Class::new

Stream API

把函数式编程运用到Java,可以对集合数据进行操作。 Stream不会存储数据,会返回一个持有结果的新Stream。

步骤:创建Stream对象、中间操作、终止操作。

创建对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 通过集合创建
// 返回一个顺序流
List <Employee> employees = EmployeeData.getEmployees();
Stream <Employee> stream = employees.stream();
// 返回一个并行流
Stream <Employee> parallelStream = employees.parallelStream();

// 通过数组
int[] arr = new int[]{1,2};
IntStream stream = Arrays.stream(arr);

// 通过Stream的of()方法
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);

//创建无限流
中间操作
  1. 筛选与切片
1
2
3
4
5
6
7
8
// 1.接受lambda,从流中排除某些元素
stream.filter(Predicate p)
// 2.截断流,使其不超过给定数量
stream.limit(n);
// 3.跳过元素,
stream.skip(n);
// 4.筛选,通过流所生成的元素的hashCode()和equals()去除重复元素
stream.distinct();
  1. 映射
1
2
3
4
5
// 接受一个函数作为参数,映射每个元素到对应的结果
stream.map(Function f);
// 接受一个参数,将流中的值都换成另一个流,然后把所有流连接成一个流
// 类似于addAll
stream.flatmap(Function f);
  1. 排序
1
2
3
4
// 产生一个新流,按照自然顺序排序
stream.sorted();
// 产生一个新流,按照比较器顺序排序
stream.sorted(Comparable com);
终止操作
  1. 匹配与查找
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 匹配
// 检查是否匹配所有元素
allMatch(Predicate p);
// 检查是否至少匹配一个元素啊
anyMatch(Predicate p);
// 检查是否没有匹配的元素
noneMatch(Predicate p);

// 查找
// 返回第一个元素
findFirst();
// 返回任意一个元素
findAny();
// 返回流中元素总数
count();
// 返回流中最大值
max(Comparator c);
// 返回流中最小值
min(Comparator c);
  1. 规约
1
2
3
// 将流中的元素反复结合起来,得到一个值。
reduce(T identity, BinaryOperator);
reduce(BinaryOperator);
  1. 收集
1
2
// 将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总
collect(Collector c);

Optional类

optional是一个容器类,可以保存类型T的值,代表值存在。保存null代表值不存在,可以避免空指针异常。

1
2
3
4
5
6
7
8
9
10
11
// 创建Optional对象
Optional.of(T t);
Optional.empty();
Optional.ofNullalbe(T t);
// 判断容器中是否包含对象
boolean isPresent();
void ifPresent(Consumer <?super T> consumer);
// 获取Optional容器的对象
//
T get();
T orElse(T other);

默认方法

接口可以有实现方法,而且不需要实现类去实现其方法。