- 接口的默认方法与静态方法
- 函数式接口
- lambda表达式
- 方法引用
- stream
- Optional
- 时间类
1. 接口的默认方法与静态方法
java8之前接口只能有方法声明,不能有方法实现,且子类必须实现父类的接口,java8中接口可以有默认方法与静态方法,子类默认继承父类的默认方法,不能继承父类的静态方法,当子类实现多个接口,且多个接口有相同方法名的默认方法时,子类需要自己指定父类方法。
2. 函数式接口
函数式接口与普通接口的区别在于函数式接口的方法中只有一个方法是抽象的,可以用注解@FunctionalInterface表示接口是一个函数式接口,起到验证接口的作用,当多了或少了一个接口,注解都会报错,当接口只有一个抽象方法时,不用@FunctionalInterface注解修饰也可以,函数式接口必须配合lambda表达式使用。
java8中常用的4个函数式接口
接口 | 描述 |
---|---|
Supplier | 无参数,返回一个结果 |
Function | 有参数,返回一个结果 |
Consumer | 有参数,无返回结果 |
Predicate | 有参数,返回布尔结果 |
3. lambda表达式
lambda表达式是一种语法糖,可以看作是不用指定接口名和参数类型名的匿名内部类,java编译器在自动推测出方法的返回类型,lambda表达式多用在函数式接口的实现。
几种常用的lambda表达式:
- () -> 0 没有传入参数,且方法体只有一行代码,返回值不用return
- ()-> {int a = 1+2; return a;} 没有传入参数,且方法体有多行代码return
- i -> 0 ,传入一个参数,有返回值,且方法体只有一行代码,返回值不用return
- i -> {int a = 1+2; return a;} 传入一个参数,有返回值,且方法体有多行代码
- i -> System.out.println(i) 有参,无返回值
- (i, j) -> System.out.println(i),有两个参数,无返回值
- (i, j) -> i+j;,传入两个参数,且方法体只有一行代码,返回值不用return
- (i, j) -> {int a = i+j; return a;} 传入两个参数,且方法体有多行代码,返回值return
4. 方法引用
-
实例对象::实例方法名
-
类名::静态方法名
-
类名::实例方法名
-
构造函数
public class Student {
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static Student create(final Supplier<Student> supplier) {
return supplier.get();
}
public void sayName() {
System.out.println(this.name);
}
public static void sayNameStatic(Student student) {
System.out.println(student.name);
}
}
public class Teacher {
public void sayStudentName(Student student) {
System.out.println(student.getName());
}
}
public static void main(String[] args) {
// 构造函数
Student student = Student.create(Student::new);
Student mingStudent = new Student("小明");
Student hongStudent = new Student("小红");
Student tianStudent = new Student("小天");
List<Student> studentList = new ArrayList<>();
studentList.add(mingStudent);
studentList.add(hongStudent);
studentList.add(tianStudent);
// 类名::实例方法名
studentList.forEach(Student::sayName);
// 类名::静态方法名
studentList.forEach(Student::sayNameStatic);
// 实例对象::实例方法名
Teacher teacher = new Teacher();
studentList.forEach(teacher::sayStudentName);
}
5. stream
使用stream,分为三个步骤,生成stream、数据处理、终止操作
-
生成stream
// 数组转stream Stream stream = Stream.of(1, "2", 3); String[] strArr = {"1", "2", "3"}; Stream<String> strArrStream = Stream.of(strArr); Stream<String> strArrayStream = Arrays.stream(strArr); // list转steaam List<String> list = Arrays.asList(strArr); Stream<String> listStream = list.stream();
-
数据处理
筛选和切片
- distinct:根据equals和hashcode去重
List<Integer> distinctList = list.stream().distinct().collect(Collectors.toList());
-
filter:按条件过滤
```java List<Integer> filterList = list.stream().filter(str -> !str.equals("2")).collect(Collectors.toList()); ```
-
limit:限制数量
```java List<Integer> limitList = list.stream().limit(3).collect(Collectors.toList()); ```
-
skip:跳过
```java List<Integer> skipList = list.stream().skip(2).collect(Collectors.toList()); ```
映射
-
map:将对象类型进行一对一转换
-
flatMap:将对象类型进行转换,得到一个流对象,最后将所有的流合在一起
System.out.println("list:" + JSON.toJSONString(teacherList));
List<List<Student>> mapCollect = teacherList.stream().map(a -> a.getStudent()).collect(Collectors.toList());
List<Student> flatMapCollect = teacherList.stream().flatMap(a -> a.getStudent().stream()).collect(Collectors.toList());
System.out.println("map:" + JSON.toJSONString(mapCollect));
System.out.println("flatMap:" + JSON.toJSONString(flatMapCollect));
排序
- sorted
studentList.stream().sorted((a,b) -> a.getAge() - b.getAge()).collect(Collectors.toList());
查找与匹配
- allMatch
boolean b = studentList.stream().allMatch(a -> a.getAge() >= 9);
- anyMatch
boolean b = studentList.stream().anyMatch(a -> a.getAge() == 19);
- noneMatch
boolean b = studentList.stream().noneMatch(a -> a.getAge() == 19);
- findFirst
Student student = studentList.stream().findFirst().get();
- findAny
Student student = studentList.stream().findAny().get();
归约 reduce(三种用法)
Optional reduce(BinaryOperator accumulator)
List<Integer> list = Arrays.asList(1, 2, 3, 4);
// 求和
System.out.println(list.stream().reduce(Integer::sum).get()); // 10
// 求最大值
System.out.println(list.stream().reduce(Integer::max).get()); // 4
// 求最小值
System.out.println(list.stream().reduce(Integer::min).get()); // 1
// 求乘积
System.out.println(list.stream().reduce((a, b) -> a * b).get()); // 24
T reduce(T identity, BinaryOperator accumulator)
// 给初始值,在求和
System.out.println(list.stream().reduce(10, Integer::sum)); // 20
U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator combiner)
当串行流时,第三个参数的lambda表达式不会执行,当并行流时第三个参数的lambda才会执行,且第二个lambda表达式并行执行完才会执行第三个
Integer num = list.stream().reduce(10, (a, b) -> a + b, (a, b) -> a * b); // 20
Integer num = list.stream().parallel().reduce(10, (a, b) -> a + b, (a, b) -> a * b); // 24024
- 终止操作
List<Integer> list = Arrays.asList(1, 2, 2, 4);
// 求个数
long count = list.stream().count();
System.out.println(count);
// 求最大
Integer maxInt = list.stream().max(Integer::max).get();
System.out.println(maxInt);
// 求最小
Integer minInt = list.stream().max(Integer::min).get();
System.out.println(minInt);
// 求和
int sum = list.stream().mapToInt(a -> a).sum();
System.out.println(sum);
// forEach循环
list.stream().forEach(System.out::println);
list.forEach(System.out::println);
// collect
Set<Integer> set = list.stream().collect(Collectors.toSet());
System.out.println(set);
6. Optional
方法 | 描述 |
---|---|
empty | 返回一个空的Optional实例 |
filter | 如果值存在并且满足提供的过滤条件,则返回包含该值的Optional对象;否则就返回一个空的Optional对象 |
map | 如果值存在,就对该值执行提供的mapping函数调用 |
flatMap | 如果值存在,就对该值执行提供的mapping函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象 |
ifPresent | 如果值存在,就执行使用该值的方法调用,否则什么也不做 |
of | 将指定值用Optional封装之后返回,如果该值为null,则抛出一个NPE |
ofNullable | 将指定值用Optional封装之后返回,如果该值为null,则返回一个空的Optional对象 |
orElse | 如果有值则返回,否则返回一个默认值 |
orElseGet | 如果有值则返回,否则返回一个由指定的Supplier接口生成的值(如果默认值的生成代价比较高的话,则适合使用orElseGet方法) |
orElseThrow | 如果有值则返回,否则返回一个由指定的Supplier接口抛出的异常 |
get | 如果值存在,则返回该值,否则抛出一个NoSuchElementException异常 |
isPresent | 如果值存在则返回true,否则返回false |