接口中的默认方法与静态方法
默认方法与静态方法使用概述
https://www.runoob.com/java/java8-default-methods.html
常用类中的日期相关API
注解中的类型注解与重复注解
集合在jdk8底层有一些变化
- jdk8以前,实在new对象时就把底层数组造好了, jdk8的时候new对象的时候不造, 等到第一次添加数据的时候再造出数组
- HashMap在jdk8时候应用了红黑树
Lambda表达式
Lambda表达式的应用举例
Lambda表达式的使用
- 举例: (o1,o2) -> Integer.compare(o1,o2)
-
格式:
-> : lambda操作符 或 箭头函数
->左边: lambda形参列表(其实就是接口中的抽象方法的形参列表)
->右边: lambda体 (其实就是重写的抽象方法的方法体)
- lambda表达式的使用, 6种情况
- lambda表达式的本质: 作为函数式接口的实例(接口具体实现类的对象)
- 如果一个接口中, 只声明了一个抽象方法, 则此接口就称为函数式接口
-
总结:
->左边: lambda形参列表的参数类型可以省略(类型推断); 如果参数列表只有一个参数, 一对()可以省略
->右边: lambda体应该使用一对{}进行包裹; 如果lambda体只有一条执行语句(可能是return语句), 则可以省略这一对{}和return关键字
lambda语法格式一: 无参数无返回值
lambda语法格式二: 需要一个参数,没有返回值
lambda语法格式三: 数据类型可以省略, 因为可由编译器推断得出, 称为"类型推断"
什么是类型推断?
在lambda表达式中如果前面的接口带着泛型, 后面的方法的参数可以自动推断出来,则可以省略lambda后面的类型
lambda语法格式四: lambda若只需要一个参数时, 参数的小括号可以省略
lambda语法格式五: Lambda需要两个或以上的参数, 多条执行语句, 并且可以有返回值
lambda语法格式六: 当lambda体只有一条语句时, return与大括号若有, 都可以省略
函数式(Functional)接口
- Lambda表达式的本质: 作为函数式接口的实例
- 如果一个接口中, 只声明了一个抽象方法, 则此接口就称为函数式接口. 我们可以在一个接口上使用@FunctionalInterface注解, 这样做可以检查它是否是一个函数式接口.
- 所以以前用匿名实现类表示的现在都可以用Lambda表达式来写.
Java内置的四大核心函数接口
消费型接口 Consumer void accept(T t)
供给型接口 Supplier T get()
函数型接口Function<T,R> R apply(T t)
断定型接口Predicate boolean test(T t)
Consumer接口举例
Predicate接口举例
其他接口
方法引用与构造器引用
方法引用举例
Employee类, 字段, get/set方法 toString 构造器, equals, hashCode都有
EmployeeData类,提供用于测试的数据
方法引用的使用
- 使用情境: 当要传递给Lambda体的操作, 已经有实现的方法了, 可以使用方法引用
- 方法引用, 本质上就是Lambda表达式, 而Lambda表达式作为函数式接口的实例. 所以方法引用也是函数式接口的实例
- 使用格式: 类(或对象) :: 方法名
-
具体分为如下的三种情况:
情况1 对象 :: 非静态方法
情况2 类 :: 静态方法
情况3 类 :: 非静态方法
- 方法引用使用的要求: 要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同, 即 方法引用的方法和函数式接口的方法 形参列表和返回值都需要相同(针对于情况1 情况2)
方法引用情况一: 对象::实例方法
例如Consumer中的void accept(T t)方法, 放一个泛型对象, 然后不返回, 发现PrintStream中的void println(T t) 这个方法也是放一个对象不返回, 他们是一样的
例如: Supplier中的 T get() 和Employee总的String getName() 是一样的
方法引用情况二: 类::静态方法
例如: Comparator中的int compare(T t1, T t2)与Integer中的int compare(T t1, T t2)
例如: Function中的 R apply (T t) 与Math中的Long round(Double d)
方法引用情况三: 类::实例方法(有难度) 其中一个参数作为方法的调用者
例如: Comparator中的int compare(T t1, T t2)与 String 中的int t1.compareTo(t2)
例如: BiPredicate 中的 boolean test(T t1, T t2); 与 String 中的boolean t1.equals(t2);
例如: Function中的R apply(T t) 与 Employee中的String getName();
构造器引用
和方法引用类似, 函数式接口的抽象方法的形参列表和构造器的形参列表一致.
抽象方法的返回值类型即可构造器所属的类的类型
例如 Supplier中的T get()
例如 Function中的R apply(T t)
例如: BiFunction中的R apply(T t, U u)
数组引用
可以把数组看做是一个特殊的类, 则写法与构造器引用就一致了
强大的Stream API
- Stream关注的是对数据的运算, 与CPU打交道; 集合关注的是数据的存储, 与内存打交道
- Stream自己不会存储元素; Stream不会改变源对象. 相反, 他们会返回一个持有结果的新Stream; Stream操作时延迟执行的. 这意味着他们会等到需要结果的时候才执行
- Stream执行流程
- Stream实例化
- 一系列中间操作(过滤, 映射…)
- 终止操作
- Stream是一个中间操作链, 对数据源的数据进行处理; 只有执行终止操作的时候, 中间操作才会被执行. 要是不执行终止操作, 中间操作链就不会被执行. 终止操作后会产生一个结果, 一旦终止操作了, 它就不会再次被使用了, 如果还想用必须再重新造一个Stream
实例化
方式一: 通过集合
并行流和顺序流的区别, 顺序流是按照集合顺序, 一个一个取的. 并行流是相当于开启多个线程一起处理数据
方式二: 通过数组
方式三: 通过Stream的of()
方式四: 创建无限流
中间操作
1. 筛选与切片
2. 映射
flatMap如果里面是一个流, 会把流中的每个值单独处理, 并拼接, map如果里面是一个流, 不会拆开处理, 而是当成一个对象来处理
类似于list的addAll和add方法
3. 排序
终止操作
1. 匹配与查找
2. 归约,相当于聚合, 求sum值等等
3. 收集
Collectors可以返回的值
Optional类
其他新特性