- 一、前言
- 二、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部分组成:
3、更多示例
- 形参列表:形参列表允许省略形参类型。如果形参列表中只有一个参数,甚至连形参列表的圆括号也可以省略。
- 箭头(->):必须通过英文中划线和大于符号组成。
- 代码块:如果代码块只包含一条语句,Lambda表达式允许省略代码块的花括号。如果Lambda表达式需要返回值,且代码块只有一条return语句,则return关键字可以省略。
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 Supplier2、Consumer接口{ // 不需要入参,只返回一个数据。 T get(); }
@FunctionalInterface public interface Consumer3、Predicate接口{ // 对参数进行处理,比如循环迭代处理数据,比如:stream.forEach(Consumer consumer) void accept(T t); }
@FunctionalInterface public interface Predicate4、Function接口{ // 只返回一个boolean值,通常用来筛选数据,比如stream.filter(Predicate predicate) boolean test(T t); }
@FunctionalInterface public interface Function{ // 对方法参数进行处理和转换,比如stream.map(Function function) R apply(T t); }
四、方法引用与构造器引用
前面已经介绍过,如果Lambda表达式的代码块只有一条代码,程序就可以省略Lambda表达式中代码块的花括号。不仅如此,如果Lambda表达式的代码块只有一条代码,还可以在代码块中使用方法引用和构造器应用。
方法引用和构造器引用可以让Lambda表达式的代码块更加简洁,Lambda表达式支持如下所示的几种引用方式。
| 种类 | 示例 | 说明 | 对应的Lambda表达式 |
|---|---|---|---|
| 引用类方法 | 类名::类方法 | 函数式接口中被实现方法的全部参数传给该类方法作为参数 | (a,b) -> 类名.类方法(a,b) |
| 引用特定对象的实例方法 | 特定对象::示例方法 | 函数式接口中被实现方法的全部参数传给该方法作为参数 | (a,b)-> 特定对象.实例方法(a,b) |
| 引用某类对象的实例方法 | 类名::实例方法 | 函数式接口中被实现方法的第一个参数作为调用者,后面的参数全部传给该方法作为参数 | (a,b,c) -> a.实例方法(b,c) |
| 引用构造器 | 类名::new | 函数接口中被实现方法的全部参数传给该构造器作为参数 | (a,b) -> new 类名(a,b) |
五、方法引用和构造器引用示例 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"));
}
}
2、引用特定对象的实例方法 (1) 示例1:字符串转换备注:输出结果为1024。
@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"));
}
}
(2) 示例2:反射备注:输出结果为7。
@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、引用某类对象的实例方法备注:输出结果为true。
@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、构造器引用备注:输出结果为ello。
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 function) {
return function.apply("飞鹰战机");
}
}
public class LambdaDemo {
public static void main(String[] args) {
// 这里我们用到了JDK8提供的Function函数式接口
// 相当于 Plane plane = PlaneFactory.createPlane(name -> new Plane(name));
Plane plane = PlaneFactory.createPlane(Plane::new);
System.out.println(plane);
}
}
备注:控制台输出为Plane{name='飞鹰战机'}。



