java8 —— Lambda 表达式

什么是Lambda 表达式

Lambda 是一个 匿名函数,我们可以把 Lambda 表达式理解为是 一段可以传递的代码 (将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使 Java 的语言表达能力得到了提升。

查看从匿名类到 Lambda 的转换

匿名内部类:

Runnable r1=new Runnable(){
    @Override
    public void run() {
    	System.out.println("Hello World!");
    }
};

Lambda 表达式:

Runnable r1=()-> System.out.println("Hello World!");

上面两段代码是等价的。

Lambda 表达式作为参数传递

使用匿名内部类作为 参数传递:

TreeSet<String> ts2 = new TreeSet<>(new Comparator<String>(){
    @Override
    public int compare(String o1, String o2) {
        return Integer.compare(o1.length(), o2.length());
    }			
});

Lambda 表达式作为参数传递:(此处的Lambda 表达式 就是一个实现类

TreeSet<String> ts2 = new TreeSet<>(
	(x, y) -> Integer.compare(x.length(), y.length())
);

Lambda 表达式语法

Lambda 表达式的基础语法:Java8中引入了一个新的操作符 “->” ,该操作符称为 箭头操作符Lambda 操作符。它将 Lambda 表达式拆分成两部分:

  • 左侧:Lambda 表达式的参数列表;
  • 右侧:Lambda 体,Lambda 表达式中所需执行的功能。

语法格式

  1. 语法格式一:无参数,无返回值
Runnable r2=()-> System.out.println("Hello World!");
  1. 语法格式二:有一个参数,并且无返回值
@Test
public void test2(){
    Consumer<String> con = (x) -> System.out.println(x);  //此处是Consumer接口的实现类,accept()方法中实现是打印参数。
    con.accept("我在学习java 的 Lambda 表达式");   //实现类的方法调用
}
  1. 语法格式三:若只有一个参数,小括号可以省略不写
@Test
public void test2(){
    Consumer<String> con = x -> System.out.println(x);  //此处是Consumer接口的实现类,accept()方法中实现是打印参数
    con.accept("我在学习java 的 Lambda 表达式");   //实现类的方法调用 。
}

将参数 x 的括包省略不写。

  1. 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句, return 和 大括号都必须写
Comparator<Integer> com = (x, y) -> {
    System.out.println("函数式接口");
    return Integer.compare(x, y);
};
  1. 语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
  1. 语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);

可省略写成

Comparator<Integer> com = (x, y) -> Integer.compare(x, y);

自定义函数式接口

接口中只有一个抽象方法的接口,称为函数式接口。
可以使用注解 @FunctionalInterface 修饰 接口类 ,可以检查 接口类 是否是 函数式接口 。

注解 @FunctionalInterface 的作用就是约束 接口类 只能有一个抽象方法,如果有多个方法时,会编译异常。

@FunctionalInterface 接口类 只有一个抽象方法时,编译正常:

在这里插入图片描述

多个方法时,编译异常:

在这里插入图片描述

异常信息是 Invalid '@FunctionalInterface' annotation; MyPredicate<T> is not a functional interface ,如图所示:

在这里插入图片描述

@FunctionalInterface
public interface MyFun {
	public Integer getValue(Integer num);	
}
public class TestLambda2 {

	//需求:对一个数进行运算
	@Test
	public void test6(){
		Integer num = operation(100, (x) -> x * x);
		System.out.println(num);
		
		System.out.println(operation(200, (y) -> y + 200));
	}
	
	//运算方法
	public Integer operation(Integer num, MyFun mf){
		return mf.getValue(num);
	}
}

此处 Lambda表达式 作为 参数传递,其实就是 实现类 作为 参数传递 。

内置四大核心函数式接口

在这里插入图片描述

方法引用

若 Lambda 体中的功能,已经有方法提供了实现,可以使用 方法引用

方法引用理解为 Lambda 表达式的另外一种表现形式 。

一、方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用
(可以将方法引用理解为 Lambda 表达式的另外一种表现形式)

主要有三种语法格式:

  1. 对象的引用 :: 实例方法名
  2. 类名 :: 静态方法名
  3. 类名 :: 实例方法名

注意:
①方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
②若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式:
ClassName::MethodName

二、构造器引用 :构造器的参数列表,需要与函数式接口中参数列表保持一致!

  1. 类名 :: new

三、数组引用
类型[] :: new;

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import org.junit.Test;


public class TestMethodRef {
	
    //对象的引用 :: 实例方法名
	@Test
	public void test1(){
		PrintStream ps = System.out;
		Consumer<String> con = (str) -> ps.println(str);
		con.accept("Hello World!");
		
		System.out.println("--------------------------------");
		
		Consumer<String> con2 = ps::println;
		con2.accept("Hello Java8!");
		
		Consumer<String> con3 = System.out::println;
	}    
    
    //对象的引用 :: 实例方法名
	@Test
	public void test2(){
		Employee emp = new Employee(101, "张三", 18, 9999.99);
		
		Supplier<String> sup = () -> emp.getName();
		System.out.println(sup.get());
		
		System.out.println("------------------------------");
		
		Supplier<String> sup2 = emp::getName;
		System.out.println(sup2.get());
	}
    
    //类名 :: 静态方法名
	@Test
	public void test3(){
		BiFunction<Double, Double, Double> fun = (x, y) -> Math.max(x, y);
		System.out.println(fun.apply(1.5, 22.2));
		
		System.out.println("-------------------------------");
		
		BiFunction<Double, Double, Double> fun2 = Math::max;
		System.out.println(fun2.apply(1.2, 1.5));
	}	
	
	//类名 :: 静态方法名
	@Test
	public void test4(){
		Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
		
		System.out.println("---------------------------------");
		
		Comparator<Integer> com2 = Integer::compare;
	}

	//类名 :: 实例方法名
    //注意:当需要引用方法的第一个参数是调用对象,并且第二个参数是需要引
    //用方法的第二个参数(或无参数)时:ClassName::methodName 
	@Test
	public void test5(){
		BiPredicate<String, String> bp = (x, y) -> x.equals(y);
		System.out.println(bp.test("abcde", "abcde"));
		
		System.out.println("-----------------------------------------");
		
		BiPredicate<String, String> bp2 = String::equals;
		System.out.println(bp2.test("abc", "abc"));
		
		System.out.println("========================================");
		
		
		Function<Employee, String> fun = (e) -> e.show();
		System.out.println(fun.apply(new Employee()));
		
		System.out.println("-----------------------------------------");
		
		Function<Employee, String> fun2 = Employee::show;
		System.out.println(fun2.apply(new Employee()));		
	}
	
    
    //构造器引用
	@Test
	public void test6(){
		Supplier<Employee> sup = () -> new Employee();
		System.out.println(sup.get());
		
		System.out.println("------------------------------------");
		
		Supplier<Employee> sup2 = Employee::new;
		System.out.println(sup2.get());
	}
	
    //构造器引用
	@Test
	public void test7(){
		Function<String, Employee> fun = Employee::new;
		
		BiFunction<String, Integer, Employee> fun2 = Employee::new;
	}
    
    
	//数组引用
	@Test
	public void test8(){
		Function<Integer, String[]> fun = (args) -> new String[args];
		String[] strs = fun.apply(10);
		System.out.println(strs.length);
		
		System.out.println("--------------------------");
		
		Function<Integer, Employee[]> fun2 = Employee[] :: new;
		Employee[] emps = fun2.apply(20);
		System.out.println(emps.length);
	}
	
}

猜你喜欢

转载自blog.csdn.net/xiaojin21cen/article/details/89315285