Lambda表达式:是一个匿名函数,一段可以传递的代码(将代码像数据一样进行传递)
语法格式一:无参无返回值
@Test public void test(){ Runnable r1=new Runnable(){ @Override public void run(){ System.out.println("haha"); } }; r1.run(); System.out.println("=======以下为Lambda表达式==========="); Runnable r2=()->System.out.println("我是Lambda表达式"); r2.run(); }
Lambada使代码更加简洁,在实现某一接口,并且此接口只有一个方法需要重写的时候即可使用此种表达式,以上代码为线程的实现Runnable重写run() ,方法没有形参,直接将所实现的接口省略,用()表示为形参列表,本质就是接口中抽象方法的形参列表,->为lambda操作符或箭头操作符,右边为lambda体,表示下面会进行重写的方法的内容,如上图。【本质:作为接口的一个实例,作为函数式接口的实现】。
函数式接口:如果一个接口中只声明了一个抽象方法,这个接口就叫做函数式接口(1.8新特性),这个接口上也会有一个注解”@FuncationalInterface“.
语法格式二:有参无返回值 /有参有返回
@Test public void test2(){ //比较两个对象的大小 Comparator<Integer> com1=new Comparator<Integer>() { @Override public int compare(Integer o1,Integer o2) { return Integer.compare(o1,o2); } }; int com2=com1.compare(121, 21); System.out.println(com2); System.out.println("=========Lambda表达式==========="); Comparator<Integer> com=(a,b)->Integer.compare(a,b); int compare=com.compare(11, 21); System.out.println(compare); System.out.println("=========Lambda表达式 方法引用==========="); //方法引用 Comparator<Integer> com3=Integer::compare; int compare3=com3.compare(50, 21); System.out.println(compare3); }
当需要重写的方法需要带有形参的时候,如上图:简写的时候,形参需要放进()中,参数类型可以省略,数据类型可由编译器推断得出,称为“类型推断”,这里重写的为return 后面的内容,不需要将return写上。
当Lambda体只有一条语句时候,return与大括号均可省略
语法格式四:若只有一个参数,小括号可以省略
@Test public void test3(){ //消费型接口 Consumer<String> con1=(s)-> System.out.println(s); con1.accept("hello world!"); System.out.println("************************"); Consumer<String> con2=s-> System.out.println(s); con2.accept("hello world!"); }
语法格式五:有多条执行语句且有返回值
@Test public void test4() { Comparator<Integer> com1 = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); } }; System.out.println(com1.compare(12,23)); System.out.println("==============================="); Comparator<Integer> com2 = (a, b) -> { System.out.println(a); System.out.println(b); return a.compareTo(b); }; System.out.println(com1.compare(12,23)); }
需要带{ },且将需要执行的多条语句放入,且将return写入进去即可,参数依然要写
在java.util.function包下定义了Java 8的丰富的函数式接口
内置四大函数式接口:
函数式接口 | 参 数 类 型 | 返 回 类 型 | 用 途 |
---|---|---|---|
Consumer<T>消费型接口 | T | void | 对类型为T的对象应用操作,包含方法voidaccept(T t) |
Supplier<T>供给型接口 | 无 | T | 返回类型为T的对象,包含方法:T get() |
Function<T,R>函数型接口 | T | R | 对类型为T的对象应用操作,并返回结果,结果是R类型的对象。包含方法 R apply(T t) |
Predicate<T>断定型接口 | T | boolean | 去顶类型为T的对象是否满足某约束,并返回boolean值。包含方法:boolean test(T t) |
例:
//消费型接口 @Test public void test1(){ happyTime(500, new Consumer<Double>() { @Override public void accept(Double aDouble) { System.out.println("我要去休息,花费:"+aDouble); } }); System.out.println("*************************"); happyTime(300, money->System.out.println("我要去休息,花费:"+money)); } public void happyTime(double money, Consumer<Double> con){ con.accept(money); } //断言型接口 @Test public void test2(){ List<String> list= Arrays.asList("jack","rose","南京","北京","普京"); List<String> filterStr = filterString(list, new Predicate<String>() { @Override public boolean test(String s) { return s.contains("京"); } }); System.out.println(filterStr); System.out.println("*************Lambda***************"); List<String> filterStr1=filterString(list,s->s.contains("京")); System.out.println(filterStr); } //根据给定的规则,过滤集合中的字符串,此规则由Predicate的方法决定 断言成功 执行 public List<String> filterString(List<String> list, Predicate<String> pre){ ArrayList<String> filterList=new ArrayList<>(); for(String s:list){ //断言返回的是boolean值 if(pre.test(s)){ filterList.add(s); } } return filterList; }
方法引用(Method References)
【本质上就是lambda表达式,作为函数式接口的实例,所以方法引用,也是函数式接口的实例】
1.使用情景:当要传递给lambda体的操作,已经有实现的方法了,可以使用方法的引用。
2.使用格式:类(或对象)::方法名
3.具体三种情况:
对象 ::非静态方法(实例方法)
类::静态方法
类::非静态方法(实例方法)
4.要求:接口中的抽象方法的形参列表和返回值类型,与方法引用的方法的形参列表和返回 值类型均相同才行(第三种情况除外)
//对象::实例方法 //Consumer 中void accept(T t) //PrintStream中的void println(T t) Comsumer<Integer> con=str -> System.out.println(str); con.accept("jack") System.out.println("========= 方法引用==========="); PrintStream ps= System.out; Comsumer<Integer> con1= ps ::println; con1.accept("jack");
Employee emp=new Employee(100,"jack",18) Supplier<String> sup=()->emp.getName(); System.out.println(sup1.getName); System.out.println("=========方法引用==========="); Supplier<String> sup2= emp::getName; System.out.println(sup2.getName);
//情况二:类::静态方法 //Comparator中的int compare(T t1, T t2) //Integer中的int compare(T t1,T t2) Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1,t2); System.out.println(com1.compare(12,23)); System.out.println("========= 方法引用==========="); Comparator<Integer> com2 =Integer::compare; System.out.println(com2.compare(12,23));
//情况三:类::实例方法 //Comparator中的int compare(T t1, T t2) //String 中的int t1.compare(t2) 这里t1作为方法的调用者出现 Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2); System.out.println(com1.compare("abc","bcd")); System.out.println("========= 方法引用==========="); Comparator<String> com2 =String :: compareTo; System.out.println(com2.compare(12,23));
构造器引用
和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致,抽象方法的返回值类型即为构造器所属的类。
//构造器引用 //Supplier中的T get() //Employee的空参构造器 Employee() Supplier<Employee> sup=()->new Employee(); System.out.println(sup.get()); System.out.println("========= 构造器引用==========="); Supplier<Employee> sup1=Employee::new; System.out.println(sup1.get()); //Function 中的R apply(T t) //Employee(id)含参构造 Function<Integer,Employee> func =id -> new Employee(id); Employee employee =func.apply(100); System.out.println(employee); System.out.println("========= 构造器引用==========="); Function<Integer,Employee> func1 = Employee :: new; Employee employee =func1.apply(1002); System.out.println(employee);
数组引用
可以将数组,看作是一个特殊的类,写法与构造器引用一致
//数组引用 //Function 中的R apply(T t) Integer定义数组的长度 Function<Integer,String[]> func =length -> new String[length]; String[] arry=func.apply(5); System.out.println(Arrays.toString(arry)); System.out.println("========= 数组引用==========="); Function<Integer,String[]> func1 = String[] ::new; String[] arry1=func1.apply(2); System.out.println(Arrays.toString(arry1));