java lambda 多个参数_Java 常用的几个lambda表达式

本文详细介绍了Java 8的Lambda表达式,包括基本语法、如何简化代码、与函数式接口的关系以及在集合操作中的应用。通过实例展示了Lambda如何替代匿名内部类,使代码更简洁。同时,提到了Stream API与Lambda的结合使用,为Java编程带来革命性的变化。

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

Lambda表达式是Java 8一个非常重要的新特性。它像方法一样,利用很简单的语法来定义参数列表和方法体。目前Lambda表达式已经成为高级编程语言的标配,像Python,Swift,C#等都已经支持Lambda表达式。

在Java 8的实现中,Lambda表达式其本质只是一个“语法糖”,经过编译器推断和处理,将其转换包装为常规的Java代码,因此就像题目所写的那样,可以让你的代码更为简洁。

Lambda表达式的基本语法:(parameters) -> expression 或 (parameters) -> { statements; }

Lambda表达式并不是一个方法,它可以用来定义了一个代码块,形式上很像是Java的匿名内部类。Lambda表达式通常会赋值给一个函数式接口,函数式接口是指只有一个抽象方法的接口。Lambda表达式可以通过上下文环境来推断变量类型, 因此在使用时尽量不人为明确的指定变量类型。

举例来看,假设我们有一个List类型的列表list,如果要遍历并打印列表内容,Java 7以前的代码如下:

1 for(String s : list) {2 System.out.println(s);3 }

Java 8来实现的话:

1 list.forEach((s) -> System.out.println(s));

或者

1 list.forEach(System.out::println);

再看一个例子,假设我们要对list进行排序,Java 7的代码如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 Collections.sort(list, new Comparator() {2 @Override3 public intcompare(String p1, String p2) {4 returnp1.compareTo(p2);5 }6 });

48304ba5e6f9fe08f3fa1abda7d326ab.png

Java 8来实现的话:

1 Collections.sort(list, (String p1, String p2) -> p1.compareTo(p2));

需要注意的是,Lambda表达式可以做参数类型推断,这里我们可以充分利用这一点,p1和p2参数前面的String是不需要的,因此可以简化一步如下:

1 Collections.sort(list, (p1,p2) -> p1.compareTo(p2));

更进一步:

1 list.sort((p1,p2) -> p1.compareTo(p2));

是不是简洁了很多:)

Lambda表达式也可以用来代替匿名类。例如我们要实现Runnable接口,Java 7的代码如下:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 new Thread(newRunnable() {2 @Override3 public voidrun() {4 System.out.println("Hello world !");5 }6 }).start();

48304ba5e6f9fe08f3fa1abda7d326ab.png

Java 8来实现的话:

1 new Thread(() -> System.out.println("Hello world !")).start();

用Lambda表达式来实现Runnable,将五行代码转换成一行语句。

合理使用Lambda表达式,不仅能简化几行代码,还能做到合理的代码抽象。当我们在实现的两个很大的方法时,如果大部分的代码都是相同的,只有一小点代码不一样时,我们可以通过将Lambda表达式作为参数传入,以达到不同表意的目的。

前面提到的函数式接口(Functional Interfaces),它表示只有一个抽象方法的接口,可以用来指向Lambda表达式。例如:

1 Consumer c = (s) -> System.out.println(s);

Java 8在java.util.function包中实现了新的几个:

Function:接受一个参数T,返回结果R

Predicate:接受一个参数T,返回boolean

Supplier:不接受任何参数,返回结果T

Consumer:接受一个参数T,不返回结果

UnaryOperator:继承自Function,接受一个参数T,返回相同类型T的结果

BiFunction:接受两个参数T和U,返回结果R

BinaryOperator:继承自BiFunction,接受两个相同类型T的参数,返回相同类型T的结果

……

另外,我们最为熟悉的函数式接口还有:

Runnable:实际上是不接受任何参数,也不返回结果

Comparable:实际上是接受两个相同类型T的参数,返回int

Callable:不接受任何参数,返回结果V

通常我们应该尽量使用标准的函数式接口,如果我们要自定义的话,可以使用@FunctionalInterface注解,例如:

1 @FunctionalInterface2 public interfacefuncInterface {3 public abstractB op(A a);4 }

在将函数式接口作为参数时,需要注意尽量避免方法重载。由于Lambda表达式根据所在环境的目标类型来决定Lambda表达式的类型(也就是Target Typing), 因此方法重载有时会导致编译器犯晕。我们可以使用不同的方法名来解决这个问题。

在这里,我们还需要澄清几点:

Lambda表达式并不是函数式接口。它能赋值给函数式接口,是因为编译器将它包装成了对应的函数式接口;

更进一步,Lambda表达式也不是匿名类:

它并没有定义新的作用域,外面定义的局部变量在Lambda表达式内部是可见的;

它不能改变外部变量的值,只能读取final或者effectively final的变量;

它不能前向读取外部变量,也就是只有在外部变量申明之后才能读取,而在匿名内部类是可以的;

Java 8 还增强了对集合数据的批量操作Stream,通常会和Lambda表达式一起使用。Lambda表达式和 Stream 可以说是Java语言从添加泛型(Generics)和注解(annotation)以来最大的变化了。下一篇文章将重点介绍Stream。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值