##java8内容
1.Lambda表达式 ★
2.函数式接口 ★
3.方法引用 ★
4.构造器引用|数组引用 ★
5.StreamAPI ★
6.接口中可以定义默认方法和静态方法 ★
7.Optional类的引入:为了减少空指针异常【了解】
8.新日期API【了解】
9.重复注解【了解】
10.Nashone引擎的使用:在jvm上运行js【后面课程】
##Java8引进
1995年推出jdk1.0
04年推出 jdk5 ,改革非常大
06年推出 jdk6 ,企业中使用的最长久版本
--------被Oralce公司收购-----------
11年 推出 jdk7
14年 推出 jdk8 LTS版本:受商业公司支持的长期版本
17年 9月份推出 jdk9, “六个月版本升级计划” 小版本
18年 3月份 推出jdk10 小版本
18年 9月份 推出jdk11 LTS版本:
##Lambda表达式
###理解
理解成一段可以传递的代码,作为函数式接口的实例出现
###应用场景
示例1:
接口 a = Lambda表达式;
示例2:【居多】
method(Lambda表达式);
public void method(接口 a){
}
###好处
1、语句更加简洁
2、更加紧凑,使java语言的表达能力得到了提升!
###语法 ★
(参数类型 参数名,参数类型 参数名)->{方法体的实现/Lambda体}
示例:
(String o1, String o2)->{return o1.compareTo(o2);}
特点:
①左侧参数列表中的参数类型可以省略!
②如果左侧参数列表中,只有一个参数,则小括号也可以省略
③右侧的Lambda体中如果仅有一句话,则大括号可以省略
④右侧的Lambda体中仅有的一句话为return语句,则return要求省略
##函数式接口
理解:
只有一个抽象方法的接口,称为函数式接口
Consumer消费型接口
Supplier供给型接口
Function<T,R>函数型接口
Predicate 断定型接口
##方法引用
###理解
* 方法引用实质上就是Lambda表达式的简化,同样可以作为函数式接口的实例出现
* 能用方法引用 的肯定能用Lambda表达式
* 能用Lambda表达式的不一定能用方法应用,除非满足以下要求:
###要求:
①Lambda体中仅仅只有一句话
②仅有的一句话为 方法调用!
③调用方法的参数列表和Lambda体实现的抽象方法的参数列表一致!
调用方法的返回类型和Lambda体实现的抽象方法的返回类型一致!
特例:类名::普通方法
调用方法的调用者正好是 抽象方法的第一个参数,并且其他参数一致
调用方法的返回类型和抽象方法的返回类型一致!
###语法:
类名或对象::方法名
###情况:
* 1、对象::普通方法
* 2、类名::静态方法
* 3、类名::普通方法
##关于方法引用、数组引用、构造器引用的总结
1.能使用方法引用|数组引用|构造器引用的地方,肯定能用Lambda表达式!
2.能用Lambda表达式的地方,不一定能用方法引用|数组引用|构造器引用,必须满足以下条件
3.能使用Lambda表达式的地方,肯定能用匿名内部类
能用匿名内部类的,不一定能用Lambda表达式,必须满足:
实现的接口为 函数式接口(里面只有一个抽象方法的接口)!
方法引用:
①Lambda体只有一句话
②仅有的一句话为调用方法
③方法的参数列表、返回类型正好与抽象方法的参数列表、返回类型一致!
特殊:如果是类名::普通方法,则要求方法的调用者为抽象的方法的第一个参数,其他一致
此类用于演示方法引用 * 举例: * 匿名内部类: * UnaryOperator<Double> up = new UnaryOperator<Double>(){ * public Double apply(Double t){ * return Math.sqrt(t); * } * }; * Lambda: * UnaryOperator<Double> up =d->Math.sqrt(d); * 方法引用: UnaryOperator<Double> up = Math::sqrt; */ public class TestMethodRef { //1、对象::普通方法 @Test public void test1_1() { //匿名内部类 // Runnable r = new Runnable() { // @Override // public void run() { // System.out.println(); // } // }; //方法引用 Runnable r2 = System.out::println; r2.run(); } //对象::普通方法 @Test public void test1_2() { //匿名内部类 // Consumer<String> con = new Consumer<String>() { // @Override // public void accept(String t) { // System.out.println(t); // // } // }; //方法引用 Consumer<String> con2 = System.out::println; con2.accept("赵丽颖和冯绍峰已经结婚了"); } //2、类名::静态方法 @Test public void test2() { //匿名内部类 Comparator<Double> com = new Comparator<Double>() { @Override public int compare(Double o1, Double o2) { return Double.compare(o1, o2); } }; //Lambda Comparator<Double> com1 = (o1,o2)->Double.compare(o1, o2); //方法引用 Comparator<Double> com2 =Double::compare; } //3、类名::普通方法 @Test public void test3() { //匿名内部类 // Function<Employee,String> fun = new Function<Employee,String>(){ // @Override // public String apply(Employee t) { // return t.getName(); // } // }; //方法引用 Function<Employee,String> fun2 = Employee::getName; System.out.println(fun2.apply(new Employee("张无忌", 12, 1000, '男'))); } //3、类名::普通方法 @Test public void test3_2() { //匿名内部类 // BiFunction<String, String, Boolean> bf = new BiFunction<String, String, Boolean>() { // @Override // public Boolean apply(String t, String u) { // return t.equals(u); // } // }; //方法引用 BiFunction<String, String, Boolean> bf2 = String::equals; System.out.println(bf2.apply("hello", "Hello")); } }
构造器引用
理解:构造器引用本质上就是Lambda表达式,只是语句更加简洁。作为函数式接口的实例,一般作为参数传递给方法!
能用构造器引用的地方,肯定能用Lambda表达式
但能用Lambda表达式的地方,不一定能用构造器引用
要求:
①Lambda体中仅仅只有一句话
②仅有的一句话为调用构造器 new ClassName(实参列表);
③抽象方法的参数列表和构造器的参数列表完全一致
抽象方法的返回类型为构造器所属的类型。
语法:
类名::new
此类用于演示构造器引用 public class TestConstructorRef { //案例1:返回new String(); @Test public void test1() { //匿名内部类 // Supplier<String> sup = new Supplier<String>() { // @Override // public String get() { // return new String(); // } // }; //构造器引用 Supplier<String> sup2 = String::new; int length = sup2.get().length(); System.out.println(length); } //案例2:返回new StringBuffer(int capacity); @Test public void test2() { Function<Integer,StringBuffer> fun = new Function<Integer,StringBuffer>(){ @Override public StringBuffer apply(Integer t) { return new StringBuffer(t); } }; Function<Integer,StringBuffer> fun2 = StringBuffer::new; } //案例3:返回new Employee("段誉", 22, 10000, '男') @Test public void test3() { A<String,Integer,Double,Character,Employee> a1 = (s,i,d,c)->new Employee(s,i,d,c); A<String,Integer,Double,Character,Employee> a = Employee::new; } } interface A<T,R,U,M,N>{ N test(T t,R r,U u,M m); }
数组引用
理解:数组引用本质上就是Lambda表达式,只是语句更加简洁。作为函数式接口的实例,一般作为参数传递给方法!
能用数组引用的地方,肯定能用Lambda表达式
但能用Lambda表达式的地方,不一定能用数组引用
要求:
①Lambda体仅仅有一句话
②仅有的一句话为返回一个新数组 new 数组类型[长度];
③抽象方法的参数只有一个,就是数组的长度;抽象方法的返回为创建的新数组类型
语法:
数组类型[]::new
此类用于演示数组引用 public class TestArrayRef { //案例1:返回一个String[] s = new String[5] @Test public void test1() { //匿名内部类 // Function<Integer,String[]> fun = new Function<Integer,String[]>(){ // @Override // public String[] apply(Integer t) { // return new String[t]; // } // }; //数组引用 Function<Integer,String[]> fun2 = String[]::new; String[] arr = fun2.apply(5); for (String string : arr) { System.out.println(string); } } //案例2:返回一个Employee[] @Test public void test2() { Function<Integer,Employee[]> fun = Employee[]::new; Employee[] apply = fun.apply(3); for (Employee employee : apply) { System.out.println(employee); } } }
综述:匿名内部类》Lambda表达式》方法引用|数组引用|构造器引用
##StreamAPI
###好处
1、更高效
2、易于使用,提供了丰富强大的方法。
###使用步骤
1.开始操作(√)
说明:创建Stream对象,指向一个具体的数据源(集合、数组、一系列值、无线流)
2.中间操作(可选 0——n)
说明:对数据源数据的计算、处理
3.终止操作(√)
说明:想要一个结果(打印、计数、去最值等)
###使用特点
1、Stream讲究的是“计算”,可以处理数据,但不能更新源数据 2、Stream 属于“惰性操作”,必须等待终止操作执行后,前面的中间操作或开始操作才会处理 3、Stream只能消费一次,一旦消费,就不能再次使用,除非重新创建Stream对象 4、Stream的中间操作可以有0个或多个,每个操作都会返回一个新的Stream 5、Stream相当于一个 更强大的Iterator,可以处理更加复杂的数据,并且实现并行化,效率更高!