Lambda 是什么
Lambda 表达式,是 JDK8 的特性之一。
它允许把函数作为方法的一个参数传递进方法中;也可以取代大部分的匿名内部类。
语法形式为 () -> {}
,其中 ()
用来描述参数列表,{}
用来描述方法体,->
为 lambda 运算符。
Lambda 的使用场景
-
实现被
@FunctionalInterface
修饰的函数式接口的抽象方法,且接口的抽象方法只有一个。(ps:Jdk 8 另一个特性:default
, 被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用) -
列表的迭代
函数式接口
Lambda 对语法的简化
-
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值
(int a, int b) -> {System.out.println(a + "," + b)}
等价于
(a, b) -> {System.out.println(a + "," + b)}
-
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号
(a) -> {System.out.println(a)}
等价于
a -> {System.out.println(a)}
-
可选的大括号:如果主体包含了一个语句,就不需要使用大括号
a -> {System.out.println(a)}
等价于
a -> System.out.println(a)
-
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值
a -> return a
等价于
a -> a
示例
// 无参数、无返回值
@FunctionalInterface
public interface NoReturnNoParam {
void method();
}
// 1参数、无返回值
@FunctionalInterface
public interface NoReturnOneParam {
void method(String a);
}
// 多参数、无返回值
@FunctionalInterface
public interface NoReturnMultiParam {
void method(String a, String b);
}
// 无参数、有返回值
@FunctionalInterface
public interface ReturnNoParam {
String method();
}
// 1参数、有返回值
@FunctionalInterface
public interface ReturnOneParam {
String method(String a);
}
// 多无参数、有返回值
@FunctionalInterface
public interface ReturnMultiParam {
String method(String a, String b);
}
public class LambdaTest {
public static void main(String[] args) {
// 无参数、无返回值
NoReturnNoParam noReturnNoParam = () -> {
};
// 1参数、无返回值
NoReturnOneParam noReturnOneParam = a -> {
};
// 多参数、无返回值
NoReturnMultiParam noReturnMultiParam = (a, b) -> {
};
// 无参数、有返回值
ReturnNoParam returnNoParam = () -> "a";
// 1参数、有返回值
ReturnOneParam returnOneParam = a -> "a";
// 多无参数、有返回值
ReturnMultiParam returnMultiParam = (a, b) -> "a";
}
}
public class Test {
public static void main(String[] args) {
// 1.简化参数类型,可以不写参数类型,但是必须所有参数都不写
NoReturnMultiParam lamdba1 = (a, b) -> {
System.out.println("简化参数类型");
};
lamdba1.method(1, 2);
// 2.简化参数小括号,如果只有一个参数则可以省略参数小括号
NoReturnOneParam lambda2 = a -> {
System.out.println("简化参数小括号");
};
lambda2.method(1);
// 3.简化方法体大括号,如果方法条只有一条语句,则可以胜率方法体大括号
NoReturnNoParam lambda3 = () -> System.out.println("简化方法体大括号");
lambda3.method();
// 4.如果方法体只有一条语句,并且是 return 语句,则可以省略方法体大括号
ReturnOneParam lambda4 = a -> a + 3;
System.out.println(lambda4.method(5));
ReturnMultiParam lambda5 = (a, b) -> a + b;
System.out.println(lambda5.method(1, 1));
}
}
普通方法的引用
sometimes 我们不是必须要自己重写某个匿名内部类的方法,我们可以可以利用 lambda 表达式的接口快速指向一个已经被实现的方法。
该方法参数的数量、类型以及返回值类型,都要与接口中定义的抽象方法一致
语法: 方法归属者::方法名,静态方法的归属者为类名,普通方法归属者为对象
public class LambdaTest {
public static void main(String[] args) {
// 方式一
ReturnOneParam lambda1 = a -> subString(a);
// 方式二
ReturnOneParam lambda2 = LambdaTest::subString;
// 方式三
LambdaTest lambdaTest = new LambdaTest();
ReturnOneParam lambda3 = lambdaTest::subString2;
}
public static String subString(String a) {
return a.substring(0, 1);
}
public String subString2(String a) {
return a.substring(0, 1);
}
}
构造方法的引用
一般我们需要声明接口,该接口作为对象的生成器,通过 类名::new 的方式来实例化对象,然后调用方法返回对象。
interface MadCatNoParam {
MadCat getMadCat();
}
interface MadCatMultiParam {
MadCat getMadCat(String catName, int catAge, double catWorth);
}
public class LambdaTest {
public static void main(String[] args) {
// 方式一
MadCatNoParam madCatNoParam = () -> new MadCat();
MadCat a = madCatNoParam.getMadCat();
// 方式二
MadCatNoParam madCatNoParam2 = MadCat::new;
MadCat b = madCatNoParam2.getMadCat();
// 方式三
MadCatMultiParam madCatMultiParam = MadCat::new;
MadCat c = madCatMultiParam.getMadCat("MadCat", 3, 1.02d);
}
}
创建线程
// 源码
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
// 实现方法
public class LambdaTest {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
});
thread.start();
}
}
集合
集合的遍历
// 源码
public interface Iterable<T> {
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
}
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
// 实现方法
public class LambdaTest {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5);
list.forEach(System.out::println);
list.forEach(element -> {
System.out.println(element);
});
}
}
删除元素
// 源码
public interface Collection<E> extends Iterable<E> {
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
}
@FunctionalInterface
public interface Predicate<T> {
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
}
// 实现方法
public class LambdaTest {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5);
list.removeIf(element -> element == 2);
}
}
元素排序
public class LambdaTest {
public static void main(String[] args) {
List<MadCat> list = new ArrayList<>();
list.add(new MadCat("a", 9, 0));
list.add(new MadCat("b", 2, 0));
list.add(new MadCat("c", 5, 0));
list.sort((a, b) -> a.getCatAge() - b.getCatAge());
list.forEach(System.out::println);
System.out.println(list);
}
}