网站首页 > 技术文章 正文
1. Lambda 表达式
1.1 语法
??Lambda表达式是Java SE 8引入的一种函数式编程语法,它的语法形式是:
rust复制代码(parameters) -> expression
(parameters) -> { statements; }
- parameters是参数列表,可以是空的或者包含一个或多个参数。如果有多个参数,用逗号分隔。
- ->是Lambda运算符,将参数列表和Lambda表达式的主体分开。
- expression是一个表达式,可以是常量、变量、方法调用、操作符、Lambda表达式或其他表达式。
- { }中的语句是Lambda表达式的主体,可以是一个或多个语句,也可以是一个代码块,是函数式接口里方法的实现。
Java复制代码// 1. 不需要参数,返回值为 2
() -> 2
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的和
(x, y) -> x + y
// 4. 接收2个int型整数,返回他们的乘积
(int x, int y) -> x * y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
1.2 函数式接口
??Lambda表达式必须搭配函数式接口使用。
??函数式接口定义:一个接口有且只有一个抽象方法 。
形如下面的接口:
java复制代码interface FunctionalInterface{
void print();
//可以加 default 方法,只要保证接口中只有一个抽象方法就行了
default void test2() {
System.out.println("JDK1.8新特性,default默认方法可以有具体的实现");
}
}
1.3 Lambda 的使用
??现有如下的函数接口:
java复制代码//无返回值无参数
interface NoParameterNoReturn {
void test();
}
//无返回值一个参数
interface OneParameterNoReturn {
void test(int a);
}
//无返回值多个参数
interface MoreParameterNoReturn {
void test(int a,int b);
}
//有返回值无参数
interface NoParameterReturn {
int test();
}
//有返回值一个参数
interface OneParameterReturn {
int test(int a);
}
//有返回值多参数
interface MoreParameterReturn {
int test(int a,int b);
}
java复制代码public static void main(String[] args) {
//无返回值无参数
NoParameterNoReturn noParameterNoReturn = ()-> System.out.println("通过Lambda的方式:这是 test 方法");
NoParameterNoReturn noParameterNoReturn1 = new NoParameterNoReturn() {
@Override
public void test() {
System.out.println("通过匿名内部类的方式:这是 test 方法");
}
};
noParameterNoReturn.test();
noParameterNoReturn1.test();
}
结果:
通过Lambda的方式:这是 test 方法
通过匿名内部类的方式:这是 test 方法
?? Lambda 与匿名内部类非常相似,它们的作用都是创建一个匿名类并重写里面的方法,但是 Lambda 的形式比较简单,但是只适用于函数接口;而匿名内部类可用于接口中多个抽象方法的情况。
java复制代码public class Main {
public static void main(String[] args) {
//无返回值无参数
NoParameterNoReturn noParameterNoReturn = ()-> System.out.println("通过Lambda的方式:这是 test 方法");
noParameterNoReturn.test();
//无返回值一个参数,可以省略:a->System.out.println(a);
OneParameterNoReturn oneParameterNoReturn = (int a)-> System.out.println(a);
oneParameterNoReturn.test(100);
//无返回值多个参数,int 可以省略:(a,b)-> System.out.println("a: " + a+" " + "b: " + b);
MoreParameterNoReturn moreParameterNoReturn = (int a,int b)-> System.out.println("a: " + a+" " + "b: " + b);
moreParameterNoReturn.test(200,300);
//有返回值无参数,return 可以省略: ()->100;
NoParameterReturn noParameterReturn = ()-> {
int a = 100;
return a;
};
System.out.println(noParameterReturn.test());
//有返回值多参数
MoreParameterReturn moreParameterReturn = (int a,int b)->{
return a + b;
};
System.out.println(moreParameterReturn.test(100, 200));
}
}
- 参数类型可以省略,如果需要省略,每个参数的类型都要省略。
- 参数的小括号里面只有一个参数,那么小括号可以省略。
- 如果方法体当中只有一句代码,那么大括号可以省略。
- 如果方法体中只有一条语句,其是return语句,那么大括号可以省略,且去掉return关键字。
2. 变量捕获
2.1 匿名内部类的变量捕获
??所谓变量捕获就是:匿名内部类中访问所在方法或代码块中的局部变量,这个过程被称为“变量捕获”。
typescript复制代码public static void main(String[] args) {
//变量捕获
int a = 100;
NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {
@Override
public void test() {
//捕获 a 变量
System.out.println(a);
}
};
noParameterNoReturn.test();
}
结果:
100
??但是,只有在局部变量是“有效的最终变量”时,匿名内部类才能够引用它。如果局部变量不是有效的最终变量,则无法在匿名内部类中引用它,会导致编译错误。
??有效的最终变量指的是一个在生命周期中没有被修改过的局部变量,它可以被认为是一个常量。
2.2 Lambda 的变量捕获
??同样的,Lambda 的变量捕获也是只有在局部变量是“有效的最终变量”时,才能够引用它。
java复制代码public static void main(String[] args) {
//变量捕获
int a = 100;
NoParameterNoReturn noParameterNoReturn = ()->{
//捕获 a 变量
System.out.println(a);
};
noParameterNoReturn.test();
}
结果:
100
2.3 匿名内部类的变量捕获 与 Lambda 的变量捕获的区别
??区别:Lambda表达式可以捕获外面的this,而匿名内部类无法直接捕获外面的this。
??在Lambda表达式中,this关键字引用的是Lambda表达式所在的类的实例,而不是Lambda表达式内部的类的实例。这个特性被称为“闭包”。
??匿名内部类中的this关键字引用的是匿名内部类的实例,而不是外部类的实例。
java复制代码public class Student {
//外部类的属性
String name = "Student";
int age;
NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {
//内部类自己的属性
String name = "hello";
@Override
public void test() {
System.out.println(this.name);
}
};
NoParameterNoReturn noParameterNoReturn2 = ()->{
String name = "hello";
System.out.println(this.name);
};
public static void main(String[] args) {
Student student = new Student();
student.noParameterNoReturn.test();
student.noParameterNoReturn2.test();
}
}
结果:
??如果想让匿名内部类的捕获外面的 this,就需要使用外部类的类名或对象引用来访问。。
java复制代码public class Student {
//外部类的属性
String name = "Student";
int age;
NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {
//内部类自己的属性
String name = "hello";
@Override
public void test() {
System.out.println(Student.this.name);
}
};
}
结果:
Student
3. Lambda 在集合当中的使用
对应的接 口 | 新增的方法 |
Collection | removeIf() spliterator() stream() parallelStream() forEach() |
List | replaceAll() sort() |
Map | getOrDefault() forEach() replaceAll() putIfAbsent() remove() replace() computeIfAbsent() computeIfPresent() compute() merge() |
3.1 Collection 接口中的 forEach() 方法
??这个方法是在接口 Iterable 当中的:
??这个方法表示用于对集合中的每个元素执行指定的操作。
java复制代码public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("bit");
list.add("hello");
list.add("lambda");
//匿名内部类 遍历 list
list.forEach(new Consumer<String>() {
//执行的操作
@Override
public void accept(String s) {
System.out.println(s);
}
});
System.out.println("---------------------");
//Lambda 遍历 list
list.forEach((String s)->{
System.out.println(s);
});
}
}
结果:
Hello
bit
hello
lambda
---------------------
Hello
bit
hello
lambda
3.2 List 接口中的 sort() 方法
java复制代码public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("bit");
list.add("hello");
list.add("lambda");
//匿名内部类
list.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
System.out.println(list);
List<String> list2 = new ArrayList<>();
list2.add("hello");
list2.add("lambda");
list2.add("Hello");
list2.add("bit");
//Lambda
list2.sort((o1,o2)->o1.compareTo(o2));
System.out.println(list2);
}
}
3.3 Map接口的 forEach() 方法
??这个方法的源码:
java复制代码public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "hello");
map.put(2, "bit");
map.put(3, "hello");
map.put(4, "lambda");
//匿名内部类
map.forEach(new BiConsumer<Integer, String>() {
@Override
public void accept(Integer integer, String s) {
System.out.println(integer + "=" + s);
}
});
System.out.println();
//Lambda
map.forEach((integer,s)->{System.out.println(integer + "=" + s);});
}
结果:
1=hello
2=bit
3=hello
4=lambda
1=hello
2=bit
3=hello
4=lambda
猜你喜欢
- 2024-09-18 面试时被问到单例模式,怎么回答才能让面试官眼前一亮?
- 2024-09-18 JVM系列之:对象的锁状态和同步(对象锁和方法锁)
- 2024-09-18 心理测试:四个卫生间你会选择哪一个,测出你是一个怎样的人!
- 2024-09-18 用这个方法,发现你命中注定的另一半
- 2024-09-18 Mybatis为什么查询结果为空时返回值为NULL或空集合?
- 2024-09-18 ES6对象拦截器 Proxy(electron拦截请求)
- 2024-09-18 求教!CAD多段线在布局视口中变成了“空心”,怎么办
- 2024-09-18 张明楷刑法笔记(13-15)结果、因果关系、结果归属
- 2024-09-18 Mybatis查询结果为空时,为什么返回值为NULL或空集合?
- 2024-09-18 一个单相思的女孩,写给暗恋对象的信
- 1513℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 561℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 506℃MySQL service启动脚本浅析(r12笔记第59天)
- 485℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 483℃启用MySQL查询缓存(mysql8.0查询缓存)
- 463℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 443℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 440℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)