目录
1 Lambda表达式
1.1 什么是Lambda表达式
Lambda表达式是一个匿名函数,我们可以把Lambda表达式理解为一段可以传递的代码(将代码像数据一样进行传递)。
我们先看看以前我们是怎么使用匿名内部类的。
Runnable r1 = new Runnable(){
@Override
public void run() {
System.out.println("hello world!");
}
}
那么这段代码用Lambda表达式写起来是什么样的呢?
Runnable r1 = () -> System.out.println("hello world!");
再看看使用匿名内部类作为参数传递
TreeSet<String> ts = new TreeSet<>(new Comparator<String>(){
@Override
public int compare(String o1, String o2){
return Integer.compare(o1.length(), o2.length());
}
});
//使用Lambda表达式
TreeSet<String> ts = new TreeSet<>((o1, o2) -> Integer.compare(o1.length(), o2.length()));
是不是比原来简单许多?
1.2 Lambda表达式语法
Lambda表达式在java语言中引入了一个新的语法元素和操作符“->”,该操作符被称为箭头操作符或Lambda操作符,它将Lambda表达式分成左右两部分:
左侧:Lambda表达式所需要的所有参数
右侧:Lambda体,即要执行的功能
- 无参,无返回值,Lambda体只有一条语句(只有一条语句时“{}”可以省略)
Runnable r1 = () -> System.out.println("hello world!");
- 一个参数,无返回值,Lambda体只有一条语句(只有一个参数时左侧的“()”可以省略)
Consumer<String> con = (args) -> System.out.println(args);
- 两个参数,有返回值,Lambda体有多条语句
BinaryOperator<Long> bo = (x, y) -> {
System.out.println(args);
return x + y;
}
上述Lambda表达式中的参数类型都是有编译器推断得出的。 所以Lambda表达式中无需指定类型。
2 函数式接口
2.1 什么是函数式接口
说到Lambda表达式就必须要说一下函数式接口,函数式接口指的是只包含一个抽象方法的接口。
可以使用注解@FunctionalInterface修饰,检查是否是函数式接口。
@FunctionalInterface
public interface MyNumber<T>{
public T getValue(T t);
}
2.2 java四大内置函数式接口
- 消费型接口:对类型T的对象进行操作,无返回值
public interface Consumer<T>{
void accept(T t);
}
- 供给型接口:返回类型为T的对象
public interface Supplier<T>{
T get();
}
- 函数型接口:对T类型的对象进行操作,并返回R类型的对象
public interface Function<T, R>{
R apply(T t);
}
- 断言型接口:判断T类型的对象是否满足某种约束,返回boolean值
public interface Predicate<T>{
boolean test(T t);
}
3 方法引用与构造器引用
3.1方法引用
当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)),"abc","abc");
//等同于
compare(String::equals, "abc","abc");
注意:当需要引用的方法的第一个参数是调用对象,并且第二个参数是需要引用方法的第二个参数(或无参时),可以使用类名**:?*方法名。
2.2 构造器引用
格式:类名::new
与方法引用类似。调用的构造方法的参数列表与抽象方法的参数列表一致。
Function<Integer, MyClass> fun = (n) -> new MyClass(n);
//等同于
Function<Integer, MyClass> fun = MyClass::new;
构造器方法同样适用于数组,如:
Function<Integer, Integer[]> fun = (n) -> new Integer[n];
//等同于
Function<Integer, Integer[]> fun = Integer[]::new;