lambda表达式

本文深入探讨了Java 8中的Lambda表达式和方法引用,通过对比不同方式的代码实现,展示了Lambda表达式如何简化代码并提高编程效率。同时,详细解析了Lambda表达式的语法特点及其在实际应用中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

举个栗子

我们在讨论lambda表达式之前先看个例子。

现在有个类Person,并且我们创建了数组,要求时根据这些人的年龄排序,我们可以用Arrays类的sort方法进行排序,但是要求需要传入一个比较器,而比较器的具体内容是要我们自己实现的。现在我们可以写成这样:

import java.util.Arrays;
import java.util.Comparator;

public class Test {
	public static void main(String[] args) {
		Person[] persons = {new Person(20, "张三"), new Person(18, "李四"), new Person(26, "王五"), new Person(30, "赵六")};
		Arrays.sort(persons, new MyComparator());
		for (Person person : persons) 
			System.out.println(person.toString());
	}
}

class MyComparator implements Comparator<Person> {
	@Override
	public int compare(Person o1, Person o2) {
		return o1.getAge() - o2.getAge();
	}
	
}

class Person {
	private int age;
	private String name;
	
	public Person(int age, String name) {
		this.age = age;
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public String getName() {
		return name;
	}
	
	public String toString() {
		return String.format("%s %d", this.name, this.age);
	}
}

因为Comparator是个接口,所有我们要完成一个实现这个接口的类MyComparator。这样写虽然可以完成,但是有点臃肿,当比较方法不一样了还要写个实现Comparator接口的类,所以我们可以改成用匿名函数的写法:

	public static void main(String[] args) {
		Person[] persons = {new Person(20, "张三"), new Person(18, "李四"), new Person(26, "王五"), new Person(30, "赵六")};
		Arrays.sort(persons, new Comparator<Person>() {
			@Override
			public int compare(Person o1, Person o2) {
				return o1.getAge() - o2.getAge();
			}
		});
		for (Person person : persons) 
			System.out.println(person.toString());
	}

这样写我们就不需要再完成一个实现Comparator接口的类了,减少了代码量,也显得优雅。但是现在再看一下代码,其实起到作用的只有return o1.getAge() - o2.getAge();,那能不能再精简一下能,这时候就需要lambda表达式了。

lambda表达式

什么是lambda表达式

什么是lambda表达式?lambda表达式就是一种匿名函数,我们先看一下上面的例子用lambda表达式怎么写:

		Person[] persons = {new Person(20, "张三"), new Person(18, "李四"), new Person(26, "王五"), new Person(30, "赵六")};
		Arrays.sort(persons, (Person o1, Person o2) -> {return o1.getAge() - o2.getAge();});
		for (Person person : persons) 
			System.out.println(person.toString());

之前传入的比较器现在被(Person o1, Person o2) -> {return o1.getAge() - o2.getAge();}代替。我们先看一下为什么原本的用匿名类传参可以写成现在这种样子。

在java8中的新特性中,如果接口只有一个抽象接口则这个接口叫做函数式接口(我们创建函数式接口时可以用@FunctionalInterface进行注解,同时java中也提供了一些常用的函数式接口,如:RunnableSupplier<T>等),就可以使用lambda表达式,而Comparator接口的源码中只有compare是抽象接口,因此Comparator接口就是函数式接口,所以一个比较器我们还可以写成这样:

Comparator<Person> comparator = (Person o1, Person o2) -> {return o1.getAge() - o2.getAge();};

代码可以进行根据上下文进行判断,用lambda表达式写成的匿名函数就是接口中唯一一个抽象接口的实现,同时再创建一个实现函数式接口的具体类。

lambda表达式的语法

在上面的示例中,Comparator接口中compare是抽象接口已经定义了是两个参数,所以在lambda表达式中是(Person o1, Person o2),如果只有一个参数可以写成(Person o1),若没有参数必须有括号()

(Person o1) -> {return o1.getAge();};
() -> {return 1;};

在函数式接口中的抽象方法中我们已经定义了入参的类型,因此可以吧声明类型去掉:

Arrays.sort(persons, (o1, o2) -> {return o1.getAge() - o2.getAge();});

如果只有一个入参,把声明类型去掉后还可以吧括号去掉:

o1 -> {return o1.getAge();};

说完入参我们再来看看代码块。若只有一个return语句,我们可以把return{}都去掉:

Arrays.sort(persons, (o1, o2) -> o1.getAge() - o2.getAge());

lambda代码中的作用域

lambda代码块中的引用的外部变量必须是final修饰的常量。因为lambda代码有可能是多线程或者延时执行,如果引用了外部普通变量,当lambda代码中使用此变量时,此时变量的值已经改变或者,这样可能导致严重问题。

在lambda代码中变量名称不能与父级方法中的变量相同。

方法引用

在了解方法引用之前,来先看个例子:

public class Test1 {
	public static void main(String[] args) {
		System.out.println(test(-10, x -> {
			if (x < 0) 
				return 0 - x;
			else 
				return x;
		}));
	}
	
	private static int test(int x, MyFunctionInterface functionalInterface) {
		return functionalInterface.operate(x);
	}
}

@FunctionalInterface
interface MyFunctionInterface {
	int operate(int x);
}

这段代码,创建了一个函数式接口MyFunctionInterface和一个静态方法test,在静态方法test中调用函数式接口中的operate方法处理入参,最后我们用lambda表达式实现了取绝对值的功能。不过在java的Math中也有取绝对值的方法abs,我们可以改写成:

System.out.println(test(-10, x -> Math.abs(x)));

这时候可以用到lambda中的方法引用:

System.out.println(test(-10, Math::abs));

从上面可以看出,其实就是把Math的abs方法作为函数式接口抽象接口的具体实现。

上面的例子中引用的是Math类的静态方法abs,方法引用主要分三种:

  1. Class::staticMethod
  2. object::instanceMethod
  3. Class::instanceMethod

对于前两种引用很好理解,都可以等价于x -> Class.staticMethod(x)或者x -> object.instanceMethod(x),而第三种引用等价于(x, y) -> x.instanceMethod(y)

<think>我们正在讨论Lambda表达式。根据用户需求,用户想了解Lambda表达式的概念和用法,以及在编程中的使用和示例。根据提供的引用,我们可以总结如下:引用[1]:Lambda表达式函数式编程、并发编程和简化代码等方面有广泛应用(Java)。引用[2]:C++Lambda表达式可以定义匿名函数,具有参数、返回值、捕获等特性。引用[3]:Scala中Lambda表达式有简写方式,左侧参数列表,右侧表达式,可以有返回值。引用[4]:C#中Lambda表达式可以转换为表达式树,用于动态生成代码,也用于异步编程。因此,我们可以从以下几个方面介绍:1.概念:Lambda表达式是一种匿名函数,可以捕获上下文变量,通常用于简化代码和实现函数式编程。2.用法:在不同语言中的语法和特性。3.示例:展示几种常见语言中的Lambda表达式示例。注意:回答中引用的段落末尾要添加引用标识,如[^1]。但注意,我们实际引用的内容来自用户提供的引用,所以需要对应。由于用户要求使用中文,并且要求生成相关问题,我们在最后生成相关问题。另外,注意数学表达式的格式要求(但本问题可能较少涉及数学表达式,如果有则按规则处理)。结构:一、Lambda表达式的概念二、Lambda表达式的一般特点三、不同编程语言中的Lambda表达式用法和示例1.Java2.C++3.Scala4.C#四、总结五、生成相关问题注意:引用标识的添加要自然,在引用内容的末尾添加。</think>### Lambda表达式的概念、用法与示例 #### 一、概念解析 Lambda表达式是一种**匿名函数**的简洁表示方式,核心特点包括: 1. **无函数名**:无需显式定义函数名称 2. **即时定义**:可在需要函数对象的位置直接声明 3. **捕获上下文**:可访问外部作用域的变量(通过值捕获或引用捕获) 4. **函数式编程核心**:支持高阶函数操作(如map/filter/reduce) 其通用语法为: `(参数列表) -> { 函数体 }` 在类型推断明确的场景中,参数类型和花括号常可省略[^2][^3]。 #### 二、核心应用场景 1. **简化回调函数**(事件处理/异步编程) 2. **集合操作**(流式处理/数据转换) 3. **替代单方法接口**(如Java的Runnable/Comparator) 4. **延迟执行逻辑**(表达式树/惰性求值) 5. **并发编程**(线程任务封装)[^1][^4] #### 三、多语言示例 ##### 1. Java:集合过滤 ```java List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); // Lambda过滤长度>3的字符串 List<String> filtered = names.stream() .filter(s -> s.length() > 3) .collect(Collectors.toList()); // 输出: [Alice, Charlie] ``` `->` 符号连接参数与表达式,实现`Predicate`接口的简写[^1]。 ##### 2. C++:自定义排序 ```cpp std::vector<int> nums = {5, 3, 7, 1}; // Lambda实现降序排序 std::sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; }); // 结果: {7, 5, 3, 1} ``` `[]`为捕获列表,此处为空表示不捕获外部变量[^2]。 ##### 3. C#:表达式树 ```csharp // 将Lambda转换为表达式树 Expression<Func<int, int, int>> expr = (a, b) => a * b + 2; var compiled = expr.Compile(); Console.WriteLine(compiled(3, 4)); // 输出14 ``` 此特性被ORM框架广泛用于SQL查询转换[^4]。 ##### 4. Scala:高阶函数 ```scala val numbers = List(1, 2, 3, 4) // Lambda实现平方映射 val squares = numbers.map(x => x * x) // 结果: List(1, 4, 9, 16) ``` 箭头`=>`左侧为参数,右侧为表达式[^3]。 #### 四、关键优势 1. **代码简洁性**:减少模板代码(如Java匿名类) 2. **可读性提升**:逻辑更贴近调用点 3. **函数组合能力**:支持链式操作(如Java Stream API) 4. **运行时优化**:延迟执行提升性能(如C#表达式树)[^4] > Lambda表达式已成为现代编程语言的标配特性,在函数式编程范式、并发处理和API简化方面发挥着关键作用[^1][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值