[JAVA备忘录] Lambda 表达式简单介绍

devtools/2025/1/11 14:47:37/

目录

前言

函数式接口

Lambda 表达式使用实例

简单示例

1. 无参数,无返回值

2. 有参数,无返回值

3. 无参数,有返回值

4. 有参数,有返回值

解释:

集合框架

1.forEach:遍历集合

2.排序:对集合中的元素进行排序

3.映射:将集合中的每个元素转换成另一种形式

4.使用Lambda 表达式定制优先队列

实现函数式接口

         1.Comparator接口

2.Consumer接口

3.Function接口

结尾 


前言

Lambda 表达式 是 Java 8 引入的一项新特性,它使得 Java 编程语言更加简洁、灵活,特别是在处理函数式编程时。Lambda 表达式允许你以一种更加简洁的方式表示匿名函数(即没有名字的函数),它是 Java 对函数式编程思想的支持。    通俗地总结一下,它的作用就是让JAVA代码变得更加简洁.  本文是笔者对它的简单介绍,受制于笔者自身学识的不足,也许有不充分或者错误的地方,在此先说一声抱歉.笔者会经常审阅自己的博客,尽力确保不会有错误.

以下是它的基础语法:

java">基本语法: (parameters) -> expression 或 (parameters) ->{ statements; }
1. paramaters :类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明 ,也可不声明而由JVM 隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。
2. -> :可理解为 被用于 的意思
3. 方法体 :可以是表达式也可以代码块,是 函数式接口 里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。

函数式接口

首先科普一下什么是函数式接口

1. 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
2. 如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接 口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只 有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。
java">@FunctionalInterface
interface Example {void test();
}

Lambda 表达式使用实例

简单示例

1. 无参数,无返回值

  如果没有参数, 括号里面也就没有值

java">@FunctionalInterface
interface NoArgNoReturn {void doSomething();
}public class Main {public static void main(String[] args) {// Lambda 表达式实现接口NoArgNoReturn action = () -> System.out.println("无参数,无返回值的方法执行");// 调用接口方法action.doSomething();}
}

2. 有参数,无返回值

   有参数,所以括号里面要放置我们的参数

java">@FunctionalInterface
interface WithArgNoReturn {void printMessage(String message);
}public class Main {public static void main(String[] args) {// Lambda 表达式实现接口WithArgNoReturn action = (message) -> System.out.println("Message: " + message);// 调用接口方法action.printMessage("Hello, Lambda!");}
}

3. 无参数,有返回值

 和上面的示例类似

java">@FunctionalInterface
interface NoArgWithReturn {int getNumber();
}public class Main {public static void main(String[] args) {// Lambda 表达式实现接口NoArgWithReturn action = () -> 42;  // 返回固定的数字// 调用接口方法并打印返回值System.out.println("The number is: " + action.getNumber());}
}

4. 有参数,有返回值

  (括号里面是参数 a,b), 然后我们返回 a+b的值

java">@FunctionalInterface
interface WithArgsWithReturn {int sum(int a, int b);
}public class Main {public static void main(String[] args) {// Lambda 表达式实现接口WithArgsWithReturn action = (a, b) -> a + b;  // 返回两个数的和// 调用接口方法并打印返回值System.out.println("The sum is: " + action.sum(10, 20));}
}

这么做简化在哪里呢?请看如下例子

java">import java.util.*;@FunctionalInterface
interface Example {void test();
}
public class Main {public static void main(String[] args) {Example example = new Example() {@Overridepublic void test() {System.out.println("这是一个示例");}};example.test();}
}

我们这里定义了一个接口 Example,然后在 main 方法中创建了一个匿名内部类实现了 Example 接口。这个匿名类的实现是通过 new Example() {} 来完成的。 所以对比能发现,使用Lambda确实可以简化代码.

解释:

匿名内部类(Anonymous Inner Class)是一个没有名字的类,通常在实例化时使用。它是类的一个局部实现,可以用来简化代码,尤其在只需要某个接口的一个临时实现时。

集合框架

1.forEach:遍历集合

java">List<String> list = Arrays.asList("apple", "banana", "cherry");
list.forEach(item -> System.out.println(item));


2.排序:对集合中的元素进行排序

java">List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2);
numbers.sort((a, b) -> a - b);  // 使用 Lambda 表达式进行升序排序
numbers.forEach(System.out::println);  // 输出: 1, 2, 3, 4, 5

3.映射:将集合中的每个元素转换成另一种形式
 

java">List<String> strings = Arrays.asList("apple", "banana", "cherry");
strings.stream().map(String::toUpperCase)  // 将字符串转为大写.forEach(System.out::println);

4.使用Lambda 表达式定制优先队列

我们在使用PriorityQueue时,通常需要定义这是大根堆还是小根堆,我们可以使用Lambda表达式来简化这个过程

java">PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1, o2) -> o1-o2);PriorityQueue<Integer> priorityQueue1 = new PriorityQueue<>(new Comparator<Integer>() 
{@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}
});
顺便提一嘴,这个操作为什么list不行呢?因为根据两者的源代码来看

PriorityQueue 实现了比较接口,它能够根据你提供的比较规则(Comparator)来排序元素,或者通过元素自身的自然顺序(如果元素实现了 Comparable 接口)来排序。因此,它支持自动排序。

java">    public PriorityQueue(Comparator<? super E> comparator) {this(DEFAULT_INITIAL_CAPACITY, comparator);}

List 不直接实现比较接口,它是一个普通的集合类,维护元素的插入顺序。要对 List 中的元素进行排序,必须显式地调用排序方法(比如 list.sort()),并提供一个 Comparator 或让元素实现 Comparable 接口。

java">public interface List<E> extends Collection<E>

笔者这里也是随意的举几个例子,读者们明白意思就好.

实现函数式接口

Lambda 实现函数式接口也是它的重要功能,笔者接下来举几个例子给读者看看

1.Comparator接口

如果正常地使用该接口,应该是这样的

java">import java.util.*;class Person {String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return name + ": " + age;}
}public class Main {public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));// 使用自定义 Comparator 按照年龄排序people.sort(new Comparator<Person>() {@Overridepublic int compare(Person o1, Person o2) {return o1.age - o2.age;  // 按照年龄升序排序}});// 输出排序后的列表for (Person person : people) {System.out.println(person);}}
}

如果使用Lambda 表达式,可以简化为

java">import java.util.*;public class Main {public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));// 使用 Lambda 表达式按年龄排序people.sort((o1, o2) -> o1.age - o2.age);// 输出排序后的列表for (Person person : people) {System.out.println(person);}}
}

小科普:为什么它是函数式接口

我们透过Comparator接口的源码可以看到

java"> boolean equals(Object obj);

 他其实还有这么方法,那么这是为什么呢?

答:  这是从 Object 类继承的,不属于接口本身定义的抽象方法。

根据 Java 的定义,函数式接口的判断依据是其抽象方法的数量,而不是它是否包含其他默认方法或静态方法。

  1. 继承自 Object 的方法不计入抽象方法
    equals() 是所有类(包括接口)的通用方法,它属于 Object 类,不是 Comparator 定义的抽象方法。

  2. 默认方法和静态方法不影响函数式接口的定义
    Java 8 引入默认方法和静态方法后,它们提供了更多的工具和扩展性,但这些都不影响抽象方法的唯一性。

因此,Comparator 只有一个抽象方法 compare(T o1, T o2),符合函数式接口的定义。

2.Consumer接口

以下是我的例子:

java">  List<String> list1 = new ArrayList<>();list1.add("niko");list1.add("bit");list1.add("ropz");list1.add("faker");list1.add("lwx");list1.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});list.forEach((s -> System.out.println(s)));

3.Function接口

java"> Function<Integer,Integer> function = x-> x *5;System.out.println(function.apply(2));
java"> Function<Integer,Integer> function = new Function<Integer, Integer>() {@Overridepublic Integer apply(Integer integer) {return integer*5;}};System.out.println(function.apply(2));

结尾 

我不敢恬不知耻地说这是一遍综合介绍Lambda 表达式的博客,因为受制于自身知识有限,我没有完整地拿出很多例子.但我可以说它初步介绍了Lambda 表达式,希望能给阅读到的小白一些总结性的思考.

文章来源:https://blog.csdn.net/cjejwe/article/details/144651404
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ppmy.cn/devtools/144662.html

相关文章

借助Aspose.Cells ,删除 Excel 中的空白行和列

删除 Excel 中的空白行和空白列对于维护干净有序的数据至关重要。这项任务在从金融到数据分析的各个行业中都起着至关重要的作用。通过删除不必要的空格&#xff0c;用户可以增强可读性并改善数据处理。在这篇博文中&#xff0c;我们将探讨如何使用 C# 删除 Excel 中的空白行和…

STM32-笔记4-按键点亮led

1、复制03项目流水灯&#xff0c;重命名改成05项目&#xff0c;05-按键控制翻转灯的状态 在BSP文件夹里新建key文件夹&#xff0c;在该文件夹里面&#xff0c;新建两个key.c和key.h文件 2、打开工程文件-加载文件 在品和魔术棒里面把刚才新建的key文件夹里面的.c 和.h文件加载…

故障诊断 | 一个小创新:特征提取+KAN分类

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 基于FFT CNN - BiGRU-Attention 时域、频域特征注意力融合的轴承故障识别模型-CSDN博客 基于FFT CNN - Transformer 时域、频域特征融合的轴承故障识别模型-CSDN博客 P…

apache的常见报错

文章目录 一、httpd -k install -n Apache输入后&#xff0c;提示拒绝访问怎么办解决方案 二、命令行输入&#xff1a;httpd -t 报错解决方案 三、httpd -k install -n Apache输入后&#xff0c;另外一种报错解决方案测试是否成功 四、路径问题引起报错解决方案 一、httpd -k i…

vue-element-admin npm install 安装失败,tui-editor更名导致

导语&#xff1a; 本失败原因是由于tui-editor&#xff08;富文本编辑器插件&#xff09;更名造成的&#xff0c;现在已经更名为toast-ui/editor&#xff1b; 在一个是一直以为是我的git问题 报错代码&#xff1a;code 128 ..........&#xff0c;困扰了我好长时间&#xff…

小程序中使用 Vue2 + Vuex 实现数据存储与获取

在小程序开发中&#xff0c;数据的存储与获取是一个非常重要的环节。本文将介绍如何在小程序中使用 Vue2 和 Vuex 实现数据的存储与获取。我们将通过一个具体的例子来展示如何在 Vuex 中管理用户信息和机构信息&#xff0c;并在组件中使用这些数据。 项目结构 首先&#xff0…

Android学习(六)-Kotlin编程语言-数据类与单例类

假设我们要创建一个表示书籍的数据类 Book&#xff0c;包含书名和作者两个字段。在 Java 中&#xff0c;代码如下&#xff1a; public class Book { String title; String author; public Book(String title, String author) { this.title title; this.author author; } Ove…

校园点餐订餐外卖跑腿Java源码

简介&#xff1a; 一个非常实用的校园外卖系统&#xff0c;基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化&#xff0c;提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合&am…