Lambda的语法极为简单(Lambda表达式的前置条件:必须是“函数式接口”),类似如下结构:
无参:() -> expression;
有参:(parameters) -> expression;
有参:(parameters) -> { statements; };
Lambda表达式由三部分组成:
接口的抽象方法有几种场景,我们来看一下
无参数、无返回值
public void print(){
// 函数式接口的方法实现
System.out.println("Hello Lambda!");
}
Lambda表达式写法
() -> System.out.println("Hello Lambda!");
1个参数,无返回值
public void print(String str){
// 函数式接口的方法实现
System.out.println("Hello " + str);
}
Lambda的写法
(str) -> System.out.println("Hello " + str);
如果是1个参数,可以去掉小括号
str -> System.out.println("Hello " + str);
多个参数、有返回值,且多条语句
public int add(int x,int y){
// 函数式接口的方法实现
System.out.println("执行加法运算!");
return x+y;
}
Lambda的写法
(x, y) -> {
System.out.println("执行加法运算!");
return x+y;
}
此处因为是多条语句,所以一定要用花括号。
多个参数,有返回值,且一条语句,省掉花括号以及return
public int add(int x,int y){
// 函数式接口的方法实现
return x + y;
}
用Lambda表达式可以写成
(x, y) -> x + y;
例如:自定义一个排序器,实现compare函数(函数式接口Comparator唯一的抽象方法)。返回0表示元素相等,-1表示前一个元素小于后一个元素,1表示前一个元素大于后一个元素。这个规则和java 8之前没什么区别。
下面代码用自定义接口实现类的的方式实现:按照年龄的倒序排序
employees.sort(new Comparator<Employee>() {
@Override
public int compare(Employee em1, Employee em2) {
if(em1.getAge() == em2.getAge()){
return 0;
}
return em1.getAge() - em2.getAge() > 0 ? -1:1;
}
});
employees.forEach(System.out::println);
如果以lambda表达式简写。箭头左侧是参数,右侧是函数体,参数类型和返回值根据上下文自动判断。如下:
employees.sort((em1,em2) -> {
if(em1.getAge() == em2.getAge()){
return 0;
}
return em1.getAge() - em2.getAge() > 0 ? -1:1;
});
employees.forEach(System.out::println);
例:自定义一个lambada表达式
public class LambdaTest {
interface Printer{
void print(String sys);
}
public void printSome(String str, Printer printer) {
printer.print(str);
}
public static void main(String[] args) {
LambdaTest lambdaTest = new LambdaTest();
// 普通实现方式
// Printer printer = new Printer() {
// @Override
// public void print(String sys) {
// System.out.println(sys);
// }
// };
// lambada实现方式-左侧是参数,右侧是实现
// Printer printer = (String sys) -> {
// System.out.println(sys);
// };
// lambada实现方式(简化)
Printer printer = sys -> System.out.println(sys);
lambdaTest.printSome("我要打印......", sys -> System.out.println(sys)); // 函数式接口的方法实现
lambdaTest.printSome("我要打印......", printer);
}
}
@FunctionalInterface
public interface Formatter {
void format(String name, int age);
}
public class LambdaTest {
public static void main(String[] args) {
print((String name, int age)-> System.out.println(String.format("name:%s age:%d", name, age)), "ziyu", 18);
}
public static void print(Formatter formatter, String name, int age) {
formatter.format(name, age);
}
}
public class LambdaTest2 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello lambda");
}
}).start();
new Thread(() -> System.out.println("hello lambda")).start();
}
}
public interface IdFactory {
String generateId();
}
import java.util.UUID;
public class LambdaTest3 {
public static void main(String[] args) {
String name = getId(()-> UUID.randomUUID() + "");
System.out.println(name);
}
static String getId(IdFactory factory) {
return factory.generateId();
}
}
符号表示:::
符号说明:双冒号为方法引用运算符,而它所在的表达式被称为方法引用。
应用场景:如果Lambad表达式所要实现的方案,已经有其他方法存在相同的方案,那么则可以使用方法引用。
总结:方法引用是对Lambda表达式符合特定情况下的一种缩写形式,它使得我们的Lambda表达式更加精简,也可以理解为lambad表达式的缩写形式,不过要注意的是方法引用只能引用已经存在的方法。
public interface Calculator {
int compute(int a, int b);
}
public class LambdaTest3 {
public static void main(String[] args) {
int a = 10;
int b = 20;
// 这里不能用 (a, b), 那样的话会产生歧义,使得编译器报错
runIt((x, y)->{
System.out.print(x);
System.out.print(" + ");
System.out.print(y);
System.out.print(" = ");
System.out.println(x + y);
return x + y;
}, a, b);
}
static void runIt(Calculator calculator, int a, int b) {
calculator.compute(a, b);
}
}
public class LambdaTest6 {
static int sum(int x, int y) {
// 函数式接口的方法实现
System.out.println(x + y);
return x + y;
}
static void runIt(Calculator calculator, int a, int b) {
calculator.compute(a, b);
}
public static void main(String[] args) {
int a = 10;
int b = 20;
runIt(LambdaTest6::sum, a, b);
}
}
@Test
public void test() {
Supplier<Long> supplier = () -> {
return System.currentTimeMillis();
};
System.out.println(supplier.get());
// 静态方法引用实现
Supplier<Long> supplier1 = System::currentTimeMillis;
System.out.println(supplier1);
}
如果一个类中已经存在一个成员方法,则可以通过对象名引用成员方法。
注意事项:
public class LambdaTest7 {
int sum(int x, int y) {
// 函数式接口的方法实现
System.out.println(x + y);
return x + y;
}
static void runIt(Calculator calculator, int a, int b) {
calculator.compute(a, b);
}
public static void main(String[] args) {
int a = 10;
int b = 20;
runIt(new LambdaTest7()::sum, a, b);
}
}
new LambdaTest7()::sum
: 先新建对象LambdaTest7
,并且通过该对象来使用成员变量引用
@Test
public void test() {
Date now = new Date();
Supplier supplier = () -> {return now.getTime();};
System.out.println(supplier.get());
// 方法引用实现
Supplier supplier1 = now::getTime;
System.out.println(supplier1.get());
}
@Test
public void test() {
Function<String, Integer> function = (s) -> {
return s.length();
};
System.out.println(function.apply("hello"));
// 通过方法引用来实现
Function<String, Integer> function1 = String::length;
System.out.println(function1.apply("hello"));
}
由于构造器的名称和类名完全一致,所以构造器引用使用::new
的格式使用。
@Test
public void test() {
Supplier supplier = () -> {return new Person();};
System.out.println(supplier.get());
// 通过方法引用来实现
Supplier supplier1 = Person::new;
System.out.println(supplier1.get());
BiFunction<Long, String, Person> biFunction = Person::new;
System.out.println(biFunction.apply(12L, "Tom"));
}
@Test
public void test() {
Function<Integer, String[]> function = (len) -> {
return new String[len];
};
String[] a = function.apply(3);
System.out.println("数组的长度: " + a.length);
// 方法的方式来调用数组的构造器
Function<Integer, String[]> function1 = String[]::new;
String[] a1 = function1.apply(3);
System.out.println("数组的长度: " + a1.length);
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。