赞
踩
概念:Lambda表达式是Java 8引入的一项重要功能,它允许我们以更简洁和灵活的方式编写代码。可以把Lambda表达式看作是一种更方便的匿名函数,可以像数据一样传递和使用。
使用Lambda表达式可以让我们写出更短、更易读的代码。它可以替代传统的匿名类,使代码更加简洁。Lambda表达式还支持函数式编程,这意味着我们可以将函数作为参数传递给其他方法,使得代码更加灵活和可扩展。
根据上面的语法,理解下面的代码:
import java.util.Arrays; import java.util.List; public class LambdaExample { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // Lambda表达式作为参数传递给forEach方法 numbers.forEach(number -> System.out.print(number+" ")); } }运行截图如下:
这个示例首先创建了一个整数列表
numbers
。然后,通过调用forEach
方法并传递一个 Lambda 表达式作为参数,对列表中的每个元素执行操作。
2.对于包含多个语句的Lambda表达式:
import java.util.Arrays; import java.util.List; public class LambdaExample { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // Lambda表达式使用多个语句块 numbers.forEach(number -> { int doubled = number * 2; System.out.println(number + " doubled: " + doubled); }); } }运行截图:
Lambda 表达式使用了一个语句块,首先计算每个数字的两倍值,并打印原始数字和计算结果。
举个简单的例子:假设我是一位厨师,需要有一位助手来帮我。你给助手提供了一个简单的任务:切洋葱。你告诉助手只需要进行切洋葱的操作,其他的工作你会负责。
在这个例子中,我们可以将这个任务看作是一个接口,而助手则是接口的实现者。这个接口定义了一个方法,即切洋葱的操作。
代码案例:
-
-
- // 定义一个函数式接口
- @FunctionalInterface
- interface Task {
- //注意只能有一个方法
- void perform();
- }
-
- public class LambdaExample {
- public static void main(String[] args) {
- // 创建一个助手对象,使用Lambda表达式实现任务
- Task assistant = () -> System.out.println("助手正在切洋葱...");
-
- // 调用厨师的方法,传递助手对象执行任务
- cookMeal(assistant);
- }
-
- public static void cookMeal(Task task) {
- // 准备食材
- System.out.println("准备食材...");
-
- // 执行任务
- task.perform();
-
- // 煮菜
- System.out.println("开始烹饪...");
- }
- }
运行截图:
如果我在接口再定义一个方法,则会报错。
但是有另外一种情况可以:
在Java 8之前,接口中只能包含抽象方法,也就是没有具体的实现。但是,Java 8引入了默认方法的概念,允许在接口中定义具有默认实现的方法。默认方法使用default
关键字进行修饰。
由于接口中的默认方法拥有具体的实现,所以你可以直接在接口中调用它们。在实现该接口的类中,可以选择是否覆盖默认方法,如果没有覆盖,默认方法会被继承并直接使用。
现在我在接口定义一个washVegetables()的默认方法。
- package demo1;
-
- // 定义一个函数式接口
- @FunctionalInterface
- interface Task {
- void perform();
-
- default void washVegetables() {
- System.out.println("助理2,帮我洗菜即可");
- }
- }
-
- public class Chef {
- public static void main(String[] args) {
- // 创建一个助手对象,使用Lambda表达式实现任务
- Task assistant1 = () -> {
- System.out.println("助手1正在切洋葱...");
- Task assistant2 = new Task() {
- @Override
- public void perform() {
- washVegetables();
- }
- };
- assistant2.perform();
- };
-
- // 调用厨师的方法,传递助手对象执行任务
- cookMeal(assistant1);
- }
-
- public static void cookMeal(Task task) {
- // 准备食材
- prepareIngredients();
-
- // 执行任务
- task.perform();
-
- // 煮菜
- startCooking();
- }
-
- public static void prepareIngredients() {
- System.out.println("准备食材...");
- }
-
- public static void startCooking() {
- System.out.println("开始烹饪...");
- }
- }
我们将助理1的任务修改为先切洋葱,然后在切洋葱完成后创建一个新的助理2对象,该对象通过实现Task
接口并重写perform
方法来调用washVegetables
默认方法。然后,我们调用助理2的perform
方法来执行洗菜操作。
- //无返回值无参数
- @FunctionalInterface
- interface NoParameterNoReturn {
- void test();
- }
- //无返回值一个参数
- @FunctionalInterface
- interface OneParameterNoReturn {
- void test(int a);
- }
- //无返回值多个参数
- @FunctionalInterface
- interface MoreParameterNoReturn {
- void test(int a,int b);
- }
- //有返回值无参数
- @FunctionalInterface
- interface NoParameterReturn {
- int test();
- }
- //有返回值一个参数
- @FunctionalInterface
- interface OneParameterReturn {
- int test(int a);
- }
- //有返回值多参数
- @FunctionalInterface
- interface MoreParameterReturn {
- int test(int a,int b);
- }
@FunctionalInterface interface NoParameterNoReturn { void test(); } public class TestDemo { public static void main(String[] args) { // 无参数无返回值的函数式接口 NoParameterNoReturn noParameterNoReturn = () -> { System.out.println("无参数无返回值"); }; noParameterNoReturn.test(); } }运行截图:
2.一个参数无返回值的函数式接口
@FunctionalInterface interface OneParameterNoReturn { void test(int a); } public class TestDemo { public static void main(String[] args) { OneParameterNoReturn oneParameterNoReturn = (int a) -> { System.out.println("一个参数无返回值:" + a); }; oneParameterNoReturn.test(10); }运行截图:
3.多个参数无返回值的函数式接口
@FunctionalInterface interface MoreParameterNoReturn { void test(int a, int b); } public class TestDemo { public static void main(String[] args) { // 多个参数无返回值的函数式接口 MoreParameterNoReturn moreParameterNoReturn = (int a, int b) -> { System.out.println("多个参数无返回值:" + a + " " + b); }; moreParameterNoReturn.test(20, 30); }运行截图:
4.有返回值无参数的函数式接口
@FunctionalInterface interface NoParameterReturn { int test(); } public class TestDemo { public static void main(String[] args) { NoParameterReturn noParameterReturn = () -> { System.out.println("有返回值无参数!"); return 40; }; int ret = noParameterReturn.test(); System.out.println(ret); }运行截图:
5.有返回值一个参数的函数式接口
@FunctionalInterface interface OneParameterReturn { int test(int a); } public class TestDemo { public static void main(String[] args) { OneParameterReturn oneParameterReturn = (int a) -> { System.out.println("有返回值有一个参数!"); return a; }; int ret = oneParameterReturn.test(50); System.out.println(ret); }运行截图:
6.有返回值多个参数的函数式接口
@FunctionalInterface interface MoreParameterReturn { int test(int a, int b); } public class TestDemo { public static void main(String[] args) { MoreParameterReturn moreParameterReturn = (int a, int b) -> { System.out.println("有返回值多个参数!"); return a + b; }; int ret = moreParameterReturn.test(60, 70); System.out.println(ret); }运行截图:
什么是匿名内部类?
匿名内部类就是没有名字的内部类 。我们这里只是为了说明变量捕获,所以,匿名内部类只要会使用就好,那么下面我们来,简单的看看匿名内部类的使用就好了。
代码案例一
- interface MyFunction {
- void printValue();
- }
-
- public class Example {
- public static void main(String[] args) {
- int x = 10; // 外部作用域的变量
-
- MyFunction myFunction = new MyFunction() {
- @Override
- public void printValue() {
- // 引用外部作用域的变量x
- System.out.println("x: " + x);
- }
- };
-
- x = 20; // 修改外部作用域的变量x
-
- myFunction.printValue(); // 输出捕获的变量x,结果为20
- }
- }
我们定义了一个函数式接口MyFunction
,其中包含了一个抽象方法printValue()
。然后,我们创建了一个匿名内部类实现了该接口,并在实现中引用了外部作用域中的变量x
,并打印出其值。
代码案例二
- interface Shape {
- void draw();
- }
-
- public class Example {
- public static void main(String[] args) {
- final int x = 10; // 外部作用域的变量
-
- Shape shape = new Shape() {
- @Override
- public void draw() {
- System.out.println("Drawing a shape with x = " + x);
- }
- };
-
- shape.draw(); // 使用匿名内部类重写的draw()方法进行绘制
- }
- }
我们定义了一个Shape
接口,其中包含了一个抽象方法draw()
。然后,我们使用匿名内部类实现了该接口,并在实现中引用了外部作用域中的变量x
。在draw()
方法中,我们打印出了变量x
的值。
Lambda表达式可以捕获外部作用域的变量,这使得Lambda表达式可以访问和操作外部作用域中的变量。捕获的变量在Lambda表达式中被视为"有效final",即虽然没有显式声明为final
,但它们在Lambda表达式中不能被修改。
代码案例:
- @FunctionalInterface
- interface NoParameterNoReturn {
- void test();
- }
-
- public class TestDemo {
- @FunctionalInterface
- interface NoParameterNoReturn {
- void test();
- }
- public static void main(String[] args) {
- int a = 10;
- NoParameterNoReturn noParameterNoReturn = ()->{
-
- System.out.println("捕获变量:"+a);
- };
- noParameterNoReturn.test();
- }
-
- }
运行截图:
现在我要修改变量a =99
则
forEach()方法
使用
forEach()
方法可以方便地遍历集合中的元素,并对每个元素执行自定义操作,从而简化了对集合的处理过程。
List<String> fruits = Arrays.asList("Apple", "Banana", "Orange"); fruits.forEach(fruit -> System.out.println("I like " + fruit)); // 输出结果: // I like Apple // I like Banana // I like Orange
removeIf() 方法
removeIf(Predicate<? super E> filter)
:使用Lambda表达式来移除集合中满足特定条件的元素。Predicate
接口的Lambda表达式用于定义过滤条件。
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); numbers.removeIf(n -> n % 2 == 0); // 移除所有偶数 // 输出结果:[1, 3, 5] System.out.println(numbers);
spliterator() 方法
返回一个可用于并行迭代集合的
Spliterator
对象。Spliterator
接口的forEachRemaining()
方法可以与Lambda表达式一起使用,对集合中的每个元素执行特定操作。
List<String> fruits = Arrays.asList("Apple", "Banana", "Orange"); Spliterator<String> spliterator = fruits.spliterator(); spliterator.forEachRemaining(fruit -> System.out.println(fruit)); // 输出结果: // Apple // Banana // Orange
stream()方法
返回一个顺序流,用于对集合中的元素进行顺序操作。可以与
forEach()
方法结合使用,对集合中的每个元素执行特定操作。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); names.stream() .forEach(name -> System.out.println("Hello, " + name)); // 输出结果: // Hello, Alice // Hello, Bob // Hello, Charlie
parallelStream() 方法
返回一个并行流,用于对集合中的元素进行并行操作。可以与
forEach()
方法结合使用,对集合中的每个元素执行特定操作。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); names.parallelStream() .forEach(name -> System.out.println("Hello, " + name)); // 输出结果: // Hello, Alice // Hello, Bob // Hello, Charlie
replaceAll()方法
使用Lambda表达式替换列表中的所有元素。
List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); numbers.replaceAll(n -> n * 2); // 将列表中的每个元素乘以2 // 输出结果:[2, 4, 6, 8, 10] System.out.println(numbers);
sort()方法
使用Lambda表达式对列表进行排序。
Comparator
接口的Lambda表达式用于定义排序逻辑。
List<String> names = new ArrayList<>(Arrays.asList("Alice", "Bob", "Charlie")); names.sort((name1, name2) -> name1.compareToIgnoreCase(name2)); // 根据名称的字母顺序排序,忽略大小写 // 输出结果:[Alice, Bob, Charlie] System.out.println(names);
forEach()方法
使用Lambda表达式对Map中的每个键值对执行特定的操作。
BiConsumer
接口的Lambda表达式用于定义操作逻辑,接受键和值作为参数。
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 90); scores.put("Bob", 80); scores.put("Charlie", 95); scores.forEach((name, score) -> System.out.println(name + ": " + score)); // 输出结果: // Alice: 90 // Bob: 80 // Charlie: 95
replaceAll()方法
使用Lambda表达式替换Map中的所有值。
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 90); scores.put("Bob", 80); scores.put("Charlie", 95); scores.replaceAll((name, score) -> score + 5); // 将每个分数加上5 System.out.println(scores); // 输出结果: // {Alice=95, Bob=85, Charlie=100}
putIfAbsent()方法
使用Lambda表达式在Map中插入键值对,仅当键不存在时才插入。Lambda表达式用于定义要插入的值,接受键作为参数。
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 90); scores.put("Bob", 80); scores.putIfAbsent("Charlie", 95); // 插入键值对"Charlie=95" System.out.println(scores); // 输出结果: // {Alice=90, Bob=80, Charlie=95}
remove()方法
使用Lambda表达式根据键和值从Map中移除指定的键值对。Lambda表达式用于定义要移除的值,接受键和当前值作为参数。
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 90); scores.put("Bob", 80); scores.put("Charlie", 95); scores.remove("Alice", 90); // 移除键值对"Alice=90" System.out.println(scores); // 输出结果: // {Bob=80, Charlie=95}
replace()方法
使用Lambda表达式替换Map中指定键的值。Lambda表达式用于定义要替换的值,接受键和当前值作为参数。
Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 90); scores.put("Bob", 80); scores.put("Charlie", 95); scores.replace("Alice", 100); // 将键"Alice"的值替换为100 System.out.println(scores); // 输出结果: // {Alice=100, Bob=80, Charlie=95}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。