?、Lambda表达式简介
什么是Lambda?
Lambda表达式是Java 8推出的?个新特性。从本质上讲,Lambda表达式是?个匿名函数。
为什么要使?Lambda?
使?Lambda表达式可以对?个接?进??常简洁的实现。
之前我们在给?个接?引?赋值的时候,可以使?接?实现类,或者匿名内部类。但是有了
Lambda表达式,我们可以更加?便的实现这个需求。
interface Comparator<T>?{
int compare(T o1, T o2);
}
class Program?{
public static void main(String[] args) {
// 1. 使?接?实现类实现
class Impl implements Comparator<Integer>?{
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}
Comparator<Integer> c1 = new Impl();
// 2. 使?匿名内部类实现
Comparator<Integer> c2 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
};
// 3. 使?Lambda表达式实现
Comparator<Integer> c3 =?(o1, o2) -> o1 - o2;
}
}
从上述例?中,我们可以看到: 对同样?个接?引?的实现,Lambda最简单!
Lambda对接?的要求?虽然Lambda表达式可以很便捷的实现接?,但并不是所有的接?都可以使?Lambda表达式来实现。
可以?Lambda表达式来简洁实现的接?是有要求的。因为Lambda表达式本质上来讲,就是?个匿名
函数,?这个匿名函数来实现接?中的?法。所以,如果接?中有多个必须要实现抽象?法时,
Lambda表达式将?法是?。
注:Lambda表达式要求接?中只有?个必须要实现的抽象?法。但是JAVA 8对接?也有?个
拓展。现在,我们可以在接?中,是?default来修饰?个?法,此时,这个?法需要有实
现。那么,实现类在实现接?的时候,对于default?法,可以实现,也可以不实现。所以,
这?所说的接?中只有?个必须实现的抽象?法,与default?法?关。
@FunctionalInterface**
@FunctionalInterface
因为Lambda表达式要求接?中有且只能有?个必须实现的抽象?法,所以,对接?可以使?
@FunctionalInterface接?来进?限定。这个注解约束了接?中只能有?个必须实现的抽象?
法。使?这个注解修饰的接?,?叫做函数式接?。
?、Lambda表达式基础语法
Lambda表达式,本质上就是?个匿名?法,所以离不开?法的?个必要的组成部分:返回值、?法
名、参数、?法体。但是由于他是?个匿名?法,所以?法名可以忽略。同时,Lambda中也不需要
显式声明返回值类型。所以,我们在写Lambda表达式的时候,只需要关?参数和?法体即可。
参数: 以()包围起来,多个参数以逗号分隔
(int a, int b)
?法体: 以{}包围起来
{ System.out.println("hello world"); }
->:?Lambda运算符,?来分隔参数和?法体
(int a, int b) -> {};
有了这?个组成部分,我们就可以对任意的函数式接?使?Lambda进?实现
// ?参、?返回值
() ->?{ System.out.println("hello world"); };
// int, int参数、?返回值
(int a, int b) ->?{ System.out.println(a + b); };
// int, int参数、int返回值
(int a, int b) ->?{ return a + b; };
三、Lambda表达式语法精简
接?中定义的?法,已经声明了?法的参数类型、数量和返回值类型。所以,使?Lambda表达式在
实现的时候,对应的部分可以省略参数精简
- 参数的类型可以精简
(int a, int b) -> { System.out.println(a + b); }
可以精简为:
(a, b) -> { System.out.println(a + b); }
- 如果参数数量只有?个,?括号可以精简
(int a) -> { System.out.println(a); }
可以精简为:
a -> { System.out.println(a); }
?法体精简
- 如果?法体中只有?条语句,则?括号可以省略
a -> { System.out.println(a); }
可以精简为:
a -> System.out.println(a);
- 如果?法体中唯?的?条语句是返回值,在精简掉?括号后,return也必须省略
a -> { return a * 2; }
可以精简为:
a -> a * 2;
四、Lambda表达式语法进阶之?法引?
什么是?法引?
如果在使?Lambda进?接?实现的时候,需要实现的逻辑已经在某?个?法中实现,则可以直接使
??法引?,指向指定的?法。
interface Calculate?{
int calculate(int a, int b);
}
public class Program?{
public static void main(String[] args) {
// 接?引?
Calculate c =?(a, b) -> a + b;
}
public static int add(int a, int b) {
return a + b;
}
}在上述代码中,main函数中Calculate引?c的实现部分,下?已经有?个?法 add 进?了实现。
所以此时,我们不需要再实现?次,只需要直接指向已经写好的实现即可。所以,可以进?如下改
造:
Calculate c = Program::add;
上?的 Program::add 就是?个?法引?。引?了Program类中的?个静态?法add。
在使??法引?的时候需要注意
- 引?的?法参数数量、参数类型、返回值类型必须和函数式接?中的?法定义?致。
- ?法引?必须有引?主体,即?法的?属者。例如:上?的add?法是?个静态?法,需要使?
类来调?。所以?法引?就是 类::?法,如果是?个成员?法,则需要使? 对象::?法 的
形式来引?。
构造?法的引?
如果需要引??个构造?法,需要使? 类::new 进?引?
interface CreatePerson?{
Person getPerson();
}
class Person?{}
class Program?{
public static void main(String[] args) {
CreatePerson c = Person::new;
}
}
五、Lambda表达式之综合案例: 排序Comparator
// 排序
list.sort((o1, o2) -> o2.age - o1.age);
// 使?Lambda表达式来实现Comparator接?,并实例化?个TreeSet对象
TreeSet<Person> set = new TreeSet<>((o1, o2) ->?{
if?(o1.age >= o2.age) {
return -1;
}
else?{
return 1;
}
});
六、Lambda表达式之综合案例: forEach()// 将集合中的每?个元素都带?到?法accept中。
list.forEach(System.out::println);
// 输出集合中所有的偶数
list.forEach(ele ->?{
if?(ele % 2 == 0) {
System.out.println(ele);
}
});
七、Lambda表达式之综合案例: removeIf()
// 将集合中的每?个元素都带?到test?法中, 如果返回值是true,则删除这个元素
// 删除集合中的年龄?于10岁的元素
list.removeIf(ele -> ele.age > 10);
?、Lambda表达式之综合案例: 线程实例化
new Thread(() ->?{
for?(int i = 0; i < 100; i++) {
System.out.println(i);
}
}).start();
九、系统内置函数式接?
系统已经给我们提供了很多函数式接?,?便我们的使?。因此,如果我们需要?到以下?法的时
候,不需要再设计接?,直接使?指定的接?即可。函数式接?
参
数
返回值 特殊说明:?个特殊实现的?接?
Predicate T boolean
IntPredicate :参数:int,返回值:boolean
LongPredicate :参数:long,返回值:boolean
DoublePredicate :参数:double,返回值:boolean
Consumer T void
IntConsumer :参数:int,返回值:void LongConsumer :
参数:int,返回值:void DoubleConsumer :参数:int,返
回值:void
Function<T, R> T R
IntFunction<R> :参数:int,返回值:R
IntToDoubleFunction :参数:int,返回值:double
IntToLongFunction :参数:int,返回值:long
LongFunction<R> :参数:long,返回值:R
LongToDoubleFunction :参数:long,返回值:double
LongToIntFunction :参数:long,返回值:int
DoubleFunction<R> :参数:double,返回值:R
DoubleToIntFunction :参数:double,返回值:int
DoubleToLongFunction :参数:double,返回值:long
Supplier ? T
BooleanSupplier :参数:?,返回值:boolean
IntSupplier :参数:?,返回值:int LongSupplier :参
数:?,返回值:long DoubleSupplier :参数:?,返回值:
double
UnaryOperator T T
IntUnaryOperator :参数:int,返回值:int
LongUnaryOperator :参数:long,返回值:long
DoubleUnaryOperator :参数:double,返回值:double
BinaryOperator T,
T T
IntBinaryOperator :参数:int, int,返回值:int
LongBinaryOperator :参数:long, long,返回值:long
DoubleBinaryOperator :参数:double, double,返回值:
double
BiPredicate<L,
R>
L,
R boolean
BiConsumer<T,
U>
T,
U void
BiFunction<T,
U, R>
T,
U R
上述接?中,最常?的是?Predicate、Consumer、
原文地址:https://blog.51cto.com/14479068/2433704