你之所以能优于别人,正是因为你坚持了别人所不能坚持的。
本文相关代码在我的Github,欢迎Star~
Lambda
Lambda
是一个匿名函数,是一个可传递的代码块,可以在以后执行一次或多次。使用 Lambda
表达式,可以写出更加紧凑、更加简洁、更加灵活的代码。
语法
(parameters) -> expression
(parameters) -> { statements; }
(参数) -> 方法体(表达式/代码块)
使用的限制
Lambda
并不是任何地方都可以使用,Lambda
表达式需要“函数式接口”的支持。
函数式接口
接口中只有一个抽象方法的接口,称为函数式接口,可以用 @FunctionalInterface
修饰一下,这里需要注意的是:未使用 @FunctionalInterfaces
注解的接口未必就不是函数式接口,一个接口是不是函数式接口的条件只有一条,即接口中只有一个抽象方法的接口( Object
类中的方法不算)。而使用 @FunctionalInterface
注解修饰了的接口就一定是函数式接口,添加 @FunctionalInterface
注解可以帮助我们检查是否是函数式接口。
常用的函数式接口
Consumer<T> : 消费型接口(无返回值,有去无回)
void accept(T t);
Supplier<T> : 供给型接口
T get();
Function<T,R> : 函数型接口
R apply(T t);
Predicate<T> : 断言型接口
boolean test(T t);
四大核心接口的-->扩展子接口
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
@FunctionalInterface
public interface Supplier<T> {
T get();
}
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
其他的类似,这些函数式接口都在java.util.function包下,读者可去这个包下去查询。
Lamdba表达式的重要特征
-
可选的类型声明:不需要声明参数类型,编译器可以统一识别参数值
-
可选的参数周围的括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
-
可选的大括号:如果表达式体里面只有一个语句,那么你不必用大括号括起来。
-
可选的返回关键字:如果表达式体只有单个表达式用于值的返回,那么编译器会自动完成这一步。若要指示表达式来返回某个值,则需要使用大括号。
Lambda表达式实例
1.不需要参数
() -> 5
2.接收一个参数
x -> x * 2
3.接收两个参数
(int x, int y) -> x * y
(x, y) -> x - y
4.接收一个 String 对象
(String s) -> System.out.println(s)
/**
* lambda表达式
*/
public class Demo {
public static void main(String[] args) {
Demo demo = new Demo();
// 表达式
Cal addCal = (x, y) -> x + y;
Cal subCal = (int x, int y) -> {return (x - y); };
Cal mulCal = (x, y) -> x * y;
Cal divCal = (int x, int y) -> x / y;
System.out.println("10 + 2 =" + demo.cals(10, 2, addCal));
System.out.println("10 - 2 =" + demo.cals(10, 2, subCal));
System.out.println("10 * 2 =" + demo.cals(10, 2, mulCal));
System.out.println("10 / 2 =" + demo.cals(10, 2, divCal));
}
public static int cals(int a, int b, Cal cal) {
return cal.calNumbers(a,b);
}
}
interface Cal{
int calNumbers(int a, int b);
}
方法引用
方法也是一种对象,可以通过名字来引用。不过方法引用的唯一用途是支持Lambda的简写,使用方法名称来表示Lambda。不能通过方法引用来获得诸如方法签名的相关信息。
方法引用可以通过方法的名字来引用其本身。方法引用是通过::
符号(双冒号)来描述的。
- 构造器引用。语法是Class::new,或者更一般的Class< T >::new,要求构造器方法是没有参数
- 静态方法引用。语法是Class::static_method,要求接受一个Class类型的参数
- 特定对象的方法引用,它的语法是instance::method。要求方法接受一个参数
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* 方法引用
*/
public class Demo1 {
public static void main(String[] args) {
//构造方法
Supplier<DaBoJava> supplier = DaBoJava::new;
System.out.println(supplier.get());
//静态方法
Consumer<String> consumer = DaBoJava::staticMethod;
consumer.accept("DaBoJava");
//对象方法
DaBoJava daBoJava = new DaBoJava();
Consumer<String> consumer1 = daBoJava::method;
consumer1.accept("instance");
}
}
class DaBoJava{
public DaBoJava() {
}
public static void staticMethod(String name) {
System.out.println(name);
}
public void method(String name){
System.out.println(name);
}
}
总结
Lambda
虽然代码看上去简洁,但是如果复杂的话还是比较难看明白的。
在学习 Lambda
的时候,我们应该清楚有哪些常见的函数式接口,并且了解相应的函数式接口的用法(参数,返回值类型)
Lambda
表达式返回的是 接口对象实例 ,如果 函数式接口的实现恰好可以通过调用一个方法来实现 ,那么我们可以使用方法引用来替代Lambda表达式
相关代码记录于GitHub中,欢迎各位伙伴 Star !
有任何疑问 微信搜一搜 [程序猿大博] 与我联系~
如果觉得对您有所帮助,请 点赞 ,收藏 ,如有不足,请评论或私信指正,谢谢~