目录
一、前言
二、Lambda表达式入门
1、Lambada表达式示例
2、Lambda表达式语法说明
3、更多示例
三、Lambda表达式与函数式接口
1、Supplier接口
2、Consumer接口
3、Predicate接口
4、Function接口
四、方法引用与构造器引用
五、方法引用和构造器引用示例
1、引用类方法
2、引用特定对象的实例方法
(1) 示例1:字符串转换
(2) 示例2:反射
3、引用某类对象的实例方法
4、构造器引用
一、前言
Lambda表达式是Java 8的重要更新,也是一个被广大开发者期待已久的特性。Lambda表达式支持将代码块作为方法参数,Lambda表达式允许使用更简洁的代码来创建函数式接口(只有一个抽象方法的接口)实例。
二、Lambda表达式入门
1、Lambada表达式示例
interface ArrayProcessor { void consume(int[] array); } public class LambdaDemo { public void process(int[] array, ArrayProcessor processor) { processor.consume(array); } public static void main(String[] args) { int[] array = new int[] { 1, 2, 3, 4, 5 }; LambdaDemo lambdaDemo = new LambdaDemo(); lambdaDemo.process(array, (int[] values) -> { int sum = 0; for (int value : values) { sum += value; } System.out.println(String.format("数组元素的和为: %s", sum)); }); } }
2、Lambda表达式语法说明
从上面语法格式可以看出,Lambda表达式的主要作用就是代替匿名内部类的繁琐语法,主要由3部分组成:
形参列表:形参列表允许省略形参类型。如果形参列表中只有一个参数,甚至连形参列表的圆括号也可以省略。
箭头(->):必须通过英文中划线和大于符号组成。
代码块:如果代码块只包含一条语句,Lambda表达式允许省略代码块的花括号。如果Lambda表达式需要返回值,且代码块只有一条return语句,则return关键字可以省略。
3、更多示例
interface Eatable { void taste(); } interface Flyable { void fly(String weather); } interface Addable { int add(int first, int second); } public class LambdaDemo { public void eat(Eatable eatable) { eatable.taste(); } public void drive(Flyable flyable) { flyable.fly("晴天"); } public void calculate(Addable addable) { System.out.println(String.format("1+1的和为:%s", addable.add(1, 1))); } public static void main(String[] args) { LambdaDemo lambdaDemo = new LambdaDemo(); // 只有一条语句,可以省略后面的花括号 lambdaDemo.eat(() -> System.out.println("耍榴芒味蛋糕真不错!")); // 只有一个形参,可以省略圆括号 lambdaDemo.drive(weather -> { System.out.println(String.format("今天的天气是:%s", weather)); System.out.println("驾驶我的无限飓风号上天!"); }); // 只有一条语句,可以省略花括号。即使需要返回值,也可以省略return关键字 lambdaDemo.calculate((a, b) -> a + b); } }
耍榴芒味蛋糕真不错!
今天的天气是:晴天
驾驶我的无限飓风号上天!
1+1的和为:2
三、Lambda表达式与函数式接口
Lambda表达式的类型,也被称为”目标类型“,Lambda表达式的目标类型是“函数式接口”。所谓函数式接口就是只包含一个抽象方法的接口。函数式接口可以包含多个默认方法、类方法,但只能声明一个抽象方法。
JDK8中为函数式接口提供了@FunctionalInterface注解,下面让我们一起看下java.util.function包下一些常用的函数式接口。
1、Supplier接口
@FunctionalInterface public interface Supplier<T> { // 不需要入参,只返回一个数据。 T get();
2、Consumer接口
@FunctionalInterface public interface Consumer<T> { // 对参数进行处理,比如循环迭代处理数据,比如:stream.forEach(Consumer<T> consumer) void accept(T t); }
3、Predicate接口
@FunctionalInterface public interface Predicate<T> { // 只返回一个boolean值,通常用来筛选数据,比如stream.filter(Predicate<T> predicate) boolean test(T t); }
4、Function接口
@FunctionalInterface public interface Function<T, R> { // 对方法参数进行处理和转换,比如stream.map(Function<T,R> function) R apply(T t); }
四、方法引用与构造器引用
前面已经介绍过,如果Lambda表达式的代码块只有一条代码,程序就可以省略Lambda表达式中代码块的花括号。不仅如此,如果Lambda表达式的代码块只有一条代码,还可以在代码块中使用方法引用和构造器应用。
方法引用和构造器引用可以让Lambda表达式的代码块更加简洁,Lambda表达式支持如下所示的几种引用方式。
五、方法引用和构造器引用示例
1、引用类方法
@FunctionalInterface interface Converter { Integer convert(String source); } public class LambdaDemo { public static void main(String[] args) { // 相当于Converter converter = source -> Integer.valueOf(source); Converter converter = Integer::valueOf; System.out.println(converter.convert("1024")); } }
备注:输出结果为1024
。
2、引用特定对象的实例方法
(1) 示例1:字符串转换
@FunctionalInterface interface Converter { Integer convert(String source); } public class LambdaDemo { public static void main(String[] args) { // 相当于Converter converter = source -> "crypto.com".indexOf(source); Converter converter = "crypto.com"::indexOf; System.out.println(converter.convert("com")); } }
备注:输出结果为7
。
(2) 示例2:反射
@FunctionalInterface interface Reflectible { boolean isInstance(Object obj); } public class LambdaDemo { public static void main(String[] args) { Object object = "string"; // 相当于 Reflection reflection = obj -> String.class.isInstance(obj); Reflectible reflection = String.class::isInstance; System.out.println(reflection.isInstance(object)); } }
3、引用某类对象的实例方法
@FunctionalInterface interface Changeable { String change(String str, int start, int end); } public class LambdaDemo { public static void main(String[] args) { // Changeable changeable = (str, start, end) -> str.substring(start, end); Changeable changeable = String::substring; System.out.println(changeable.change("Hello", 1, 5)); } }
4、构造器引用
class PlaneFactory { static class Plane { private String name; public Plane(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Plane{" + "name='" + name + '\'' + '}'; } } public static Plane createPlane(Function<String, Plane> function) { return function.apply("飞鹰战机"); } } public class LambdaDemo { public static void main(String[] args) { // 这里我们用到了JDK8提供的Function<T,R>函数式接口 // 相当于 Plane plane = PlaneFactory.createPlane(name -> new Plane(name)); Plane plane = PlaneFactory.createPlane(Plane::new); System.out.println(plane); } }