百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Java Lambda表达式详解(非常全面)

liebian365 2025-02-20 16:41 4 浏览 0 评论


Java Lambda表达式是JDK8引入的,是一个比较重要的特性。@mikechen

Lambda表达式简介

Lambda 表达式是 JDK8 的一个新特性,也被称为闭包,Lambda表达式允许把函数作为一个方法的参数,即行为参数化,函数作为参数传递进方法中。

Lambda表达式可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

Lambda表达式的作用

Java 8 引入的 Lambda表达式的主要作用就是简化代码,写出更优雅的代码。

怎么一个简化优雅呢,举一Lambda语法创建线程和匿名内部类创建线程的例子,就非常清楚了。

1.匿名类创建线程

// JDK7匿名内部类写法
new Thread(new Runnable() {//接口名
        @Override
        public void run() {//方法名
            System.out.println("mikechen");
        }
    });

2.Lambda表达式创建线程

// JDK8 Lambda来创建线程 
new Thread(() -> System.out.println("mikechen"));

上述代码跟匿名内部类的作用是一样的,但比匿名内部类更进一步,这里连接口名和函数名都一同省掉了,Lambda表达式可以取代匿名内部类,写出更优雅的代码。

Lambda表达式的语法

lambda 表达式的语法格式如下:

  • ():左侧部分指定了Lambda表达式需要的所有参数。
  • ->:Lambda表达式的操作符或者箭头操作符。
  • {}:右侧部分指定了Lambda体,即方法需要实现的内容。

示例:

Lambda体只有一条语句:

示例:

() -> System.out.println("mikechen");

请注意,括号中没有内容。那就是表示lambda不带任何参数。

2.一个参数

示例:

Consumer con = (x) -> System.out.println(x);

当lambda表达式是单个参数时,也可以省略括号,如下所示:

Consumer con = x -> System.out.println(x);

3.多个参数

如果Java lambda表达式匹配的方法有多个参数,则需要在括号内列出这些参数,代码如下:

BinaryOperator bo = (a, b) -> {
System.out.println("函数式接口");
return a + b;
};

注意:仅当方法是单个参数时,才可以省略括号。

4.指定参数类型

如果编译器无法从lambda匹配的函数式接口抽象方法推断参数类型,则有时可能需要为lambda表达式指定参数类型。

(Car car) -> System.out.println("The car is: " + car.getName());

如你所见,car参数的类型(Car)写在参数名称的前面,就像在其他方法中声明参数或对接口进行匿名实现时一样。

5.只有一条语句时

当Lambda体只有一条语句时,return和大括号可以省略,示例:

BinaryOperator bo = (a, b) -> a + b;

6.参数类型不写

Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器能够通过上下文推断出数据类型,这就是“类型推断”,示例:

BinaryOperator bo = (Integer a, Integer b) -> {
return a + b;
};

等同于

BinaryOperator bo = (a, b) -> {
return a + b;
};

上述 Lambda 表达式中的参数类型都是由编译器推断得出,Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。

Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的,这就是所谓的“类型推断”。

7.Lambda表达式返回值

你可以从Java lambda表达式返回值,就像从方法中返回值一样。你只需向lambda表达式主体添加一个return,如下所示:

(param) -> {
    System.out.println("param: " + param);
    return "return value";
  }

函数式接口

Lambda表达式需要函数式接口的支持,所以,我们有必要来说说什么是函数式接口。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

一种用于表示一个接口是Java语言规范定义的函数式接口的注解类型。

对于函数式接口,我们可以理解为只有一个抽象方法的接口,除此之外它和别的接口相比并没有什么特殊的地方。

public interface MyFunctionInterface {
public T getValue(T t);
}

为了确保函数式接口的正确性,我们可以给这个接口添加@FunctionalInterface注解,这样当其中有超过一个抽象方法时就会报错。

Unexpected @FunctionalInterface annotation 
@FunctionalInterface ^ WorkerInterface is not a functional interface multiple 
 non-overriding abstract methods found in interface WorkerInterface 1 error

Java 8中每一个Lambda表达式必须有一个函数式接口与之对应,也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。

Lambda表达式的举例

学习 Lambda 表达式的最好方式是学习例子,下面我们看几个比较常用的例子。

1.lambda创建线程

使用() -> {} 替代匿名类:

//JDK 8之前
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("使用匿名内部类,开线程");
}
}).start();

//JDK 8 使用lambda表达式
new Thread(() -> System.out.println("使用lambda表达式,开线程")).start();

2.lambda事件处理

使用lambda表达式如下所示写出更好的事件侦听器的代码:

// Java 8之前:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button被点击了使用老的方式!");
}
});

// Java 8方式:
button.addActionListener( (e) -> {
System.out.println("Button被点击了使用Lambda表达式!");
});

3.lambda遍历List集合

集合的遍历,采用lambda表达式会更简洁:

// Java 8之前:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
for (String feature : features) {
System.out.println(feature);
}

// Java 8之后:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
features.forEach(n -> System.out.println(n));

// 使用Java 8的方法引用更方便,方法引用由::双冒号操作符标示,
features.forEach(System.out::println);

方法引用是使用两个冒号::这个操作符号。

4.元素排序

之前我们若要为集合内的元素排序,就必须调用 sort 方法,传入比较器重写 compare。

方法的比较器对象,现在我们还可以使用 lambda 表达式来简化代码。

public static void main(String[] args) {
    List list = new ArrayList<>();
    list.add("a");
    list.add("d");
    list.add("b");
    list.add("c");
    list.sort((o1,o2)->o1.compareTo(o2));
    list.forEach(System.out::println);
}

5.lambda Map

// 不使用lambda表达式为每个订单加上12%的税
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
for (Integer cost : costBeforeTax) {
double price = cost + .12*cost;
System.out.println(price);
}
// 使用lambda表达式
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
costBeforeTax.stream().map((cost) -> cost + .12*cost).forEach(System.out::println);

6.lambda过滤String

// 创建一个字符串列表,每个字符串长度大于2
List filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
System.out.printf("Original List : %s, filtered list : %s %n", strList, filtered);

7.lambda对集合应用函数

// 将字符串换成大写并用逗号链接起来
List G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada");
String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", "));
System.out.println(G7Countries);

8.lambda计算最大值、最小值、平均值

//获取数字的个数、最小值、最大值、总和以及平均值
List primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Highest prime number in List : " + stats.getMax());
System.out.println("Lowest prime number in List : " + stats.getMin());
System.out.println("Sum of all prime numbers : " + stats.getSum());
System.out.println("Average of all prime numbers : " + stats.getAverage());

以上就是Java 8的lambda表达式的详解,希望对你有所用!

更多架构技术干货,私信【架构】即可查看我原创的300期+BAT架构技术系列文章与1000+大厂面试题答案合集。

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: