Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码 像数据一样进行传递)。可以写出更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升。
@Test public void LambdaExTest1(){ //匿名内部类 Runnable r1 = new Runnable(){ @Override public void run() { System.out.println("匿名内部类"); } }; //lambda Runnable r2 = ()-> System.out.println("lambda"); new Thread(r1).start(); new Thread(r2).start(); } 得到结果: 匿名内部类 lambda @Test public void LambdaExTest2(){ TreeSet<String> ts1 = new TreeSet<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return Integer.compare(o1.length(), o2.length()); } }); //lambda表达式作为参数传递 TreeSet<String> ts2 = new TreeSet<>((o1,o2)->Integer.compare(o1.length(), o2.length())); }Lambda 表达式在Java 语言中引入了一个新的语法元 素和操作符。这个操作符为 “->” , 该操作符被称 为 Lambda 操作符或剪头操作符。它将 Lambda 分为 两个部分: 左侧:指定了 Lambda 表达式需要的所有参数 右侧:指定了 Lambda 体,即 Lambda 表达式要执行 的功能。
语法总结
语法格式一:无参,无返回值,Lambda 体只需一条语句
Runnable r2 = ()-> System.out.println("lambda");语法格式二:Lambda 需要一个参数
Consumer<String> fun = (args) -> System.out.println(args);语法格式三:Lambda 只需要一个参数时,参数的小括号可以省略
Consumer<String> fun2 = args -> System.out.println(args);语法格式四:Lambda 需要两个参数,并且有返回值
BinaryOperator<Long> bo = (x,y) -> { System.out.println("lambda"); return x+y; };语法格式五:当 Lambda 体只有一条语句时,return 与大括号可以省略
BinaryOperator<Long> bo2 = (x,y) -> x+y;类型推断
上述 Lambda 表达式中的参数类型都是由编译器推断 得出的。Lambda 表达式中无需指定类型,程序依然可 以编译,这是因为 javac 根据程序的上下文,在后台 推断出了参数的类型。Lambda 表达式的类型依赖于上 下文环境,是由编译器推断出来的。这就是所谓的 “类型推断”
作为参数传递 Lambda 表达式
@Test public void Test(){ String newStr = toUpperString((str) -> str.toUpperCase(),"apple"); } public String toUpperString(MyFunc<String> mf,String str){ return mf.getValue(str); }作为参数传递 Lambda 表达式:为了将 Lambda 表达式作为参数传递,接 收Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口 的类型。
Java 内置四大核心函数式接口
函数式接口参数类型返回类型用途Consumer 消费型接口Tvoid对类型为T的对象应用操 作,包含方法: void accept(T t)Supplier 供给型接口无T返回类型为T的对象,包 含方法:T get();Function<T,R> 函数型接口TR对类型为T的对象应用操 作,并返回结果。结果 是R类型的对象。包含方 法:R apply(T t);Predicate 断定型接口Tboolean确定类型为T的对象是否 满足某约束,并返回 boolean 值。包含方法 boolean test(T t);当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用! (实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!) 方法引用:使用操作符 “::” 将方法名和对象或类的名字分隔开来。 如下三种主要使用情况:
对象::实例方法
类::静态方法
类::实例方法
(x) -> System.out.println(x); 等同于 System.out::println; BinaryOperator<Double> bo = (x,y) -> Math.pow(x,y); 等同于 BinaryOperator<Double> bo = Math::pow; compare((x,y) -> x.equals(y),"problem","answer") 等同于 compare(String::equals,"problem","answer") //注意:当需要引用方法的第一个参数是调用对象,并且第二个参数是需要引用方法的第二个参数(或无参数) //时:ClassName::methodName构造器引用 ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。 可以把构造器引用赋值给定义的方法,与构造器参数 列表要与接口中抽象方法的参数列表一致!
Function<Integer,Myclass> fun = (n) -> new Myclass(n); 等同于 Function<Integer,Myclass> fun = Myclass::new数组引用 type[] :: new
Function<Integer,Integer[]> fun = (n) -> new Integer[n]; 等同于 Function<Integer,Integer[]> fun = Integer[]::new;