【java进阶】------ Lambda表达式

关于匿名内部类的详细知识点,请查阅《【java面向对象进阶】------内部类》

关于Array的排序规则请参考本文《【java常用API】----- Arrays》


1. 什么是函数式编程

在正式学习Lambda之前,我们需要先理解一种编程思想:函数式编程(Functional Programming)。

  • 面向对象思想:强调"谁去做"。做事情必须先找一个对象,通过对象调用方法来完成。
  • 函数式思想:强调"做什么"。它忽略面向对象的复杂语法,只关注结果,不关注执行的对象是谁。

Lambda表达式正是函数式思想在Java中的具体体现。


2. Lambda表达式的标准格式

Lambda表达式是JDK 8引入的一种新语法形式,它的核心作用是简化匿名内部类的写法。

2.1 标准语法结构

Lambda表达式的标准格式由三个部分组成:

java 复制代码
(参数列表) -> { 方法体代码 }
  • ():对应着接口中抽象方法的形参列表。
  • ->:Lambda操作符(箭头操作符),是固定格式,表示指向。
  • {}:对应着接口中抽象方法的方法体。

2.2 代码演变:从匿名内部类到Lambda

让我们通过Arrays.sort的降序排序案例,看看代码是如何演变的。

需求:对整数数组进行降序排序。

2.2.1 传统写法:匿名内部类

java 复制代码
Integer[] arr = {3, 1, 4, 2};

Arrays.sort(arr, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2 - o1;
    }
});

2.2.2 Lambda写法:简化后的代码

java 复制代码
Integer[] arr = {3, 1, 4, 2};

// Lambda完整格式
Arrays.sort(arr, (Integer o1, Integer o2) -> {
    return o2 - o1;
});

对比分析:

  • 我们省略了new Comparator<>() { ... }这一大串模板代码。
  • 我们只保留了最核心的参数(o1, o2)和执行逻辑-> { return o2 - o1; }。

3. Lambda表达式的前提条件

并不是所有的匿名内部类都能用Lambda表达式简化,必须满足以下前提:

  1. 必须是接口的匿名内部类。
  2. 接口中只能有一个抽象方法。

满足上述条件的接口,被称为函数式接口。

💡 知识点:@FunctionalInterface

这是一个注解,用于检测一个接口是否是函数式接口。如果接口上有此注解,但包含多个抽象方法,编译器会报错。虽然不写这个注解也能运行,但为了代码的严谨性,建议在函数式接口上加上此注解。


4. Lambda表达式的省略写法

Lambda之所以流行,是因为它支持大量的语法省略。其核心原则只有一条:可推导,可省略。即编译器能根据上下文推导出类型的,都可以省略。

4.1 省略规则速查表

规则描述 示例(假设接口方法为 void run() 或 int compare(...))
参数类型可省略 (Integer o1, Integer o2) → (o1, o2)编译器根据泛型自动推断类型
单参数可省略括号 若仅有一个参数 且省略了类型 ,则 () 可省略。例如:(e) → e(若保留类型如 (String e),则括号不可省)
单行代码可省略大括号 若方法体仅有一行代码,{}、; 及 return 可同时省略 。例如:(x, y) -> { return x + y; } → (x, y) -> x + y

4.2 省略演示

让我们继续使用排序的例子,看看代码是如何一步步"瘦身"的。

场景 :对整数数组进行降序排序。

4.2.1 第一阶段:Lambda完整格式

java 复制代码
Arrays.sort(arr, (Integer o1, Integer o2) -> {
    return o2 - o1;
});

4.2.2 第二阶段:省略参数类型

编译器可以通过arr数组的类型推导出o1和o2都是Integer类型。

java 复制代码
Arrays.sort(arr, (o1, o2) -> {
    return o2 - o1;
});

4.2.3 第三阶段:省略大括号、return和分号

因为方法体只有一行代码,我们可以将其简化为一行流式写法。

java 复制代码
// 最终形态
Arrays.sort(arr, (o1, o2) -> o2 - o1);

5. 实战练习:字符串长度排序

为了巩固Lambda的使用,我们来完成一个实际的小练习。

需求:

  1. 定义一个字符串数组 {"a", "aaaa", "aaa", "aa"}。
  2. 使用Arrays.sort进行排序。
  3. 排序规则 :按照字符串的长度进行降序排序(长的在前,短的在后)。

5.1 传统匿名内部类写法

java 复制代码
package com.example;
import java.util.Arrays;
import java.util.Comparator;

public class ArraysDemo {
    public static void main(String[] args) {
        String[] arr = {"a", "aaaa", "aaa", "aa"};

        Arrays.sort(arr, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // 按照长度比较:o2长度 - o1长度
                return o2.length() - o1.length();
            }
        });
        //输出结果:[aaaa, aaa, aa, a]
        System.out.println(Arrays.toString(arr));
    }
}

5.2 Lambda省略写法(推荐)

我们可以直接利用省略规则,将代码简化到最极致:

java 复制代码
package com.example;
import java.util.Arrays;

public class ArraysDemo {
    public static void main(String[] args) {
        String[] arr = {"a", "aaaa", "aaa", "aa"};
        // 参数类型省略 + 大括号/return省略
        Arrays.sort(arr,(o1,o2) -> o2.length()-o1.length());
        //输出结果:[aaaa, aaa, aa, a]
        System.out.println(Arrays.toString(arr));
    }
}

5.3 扩展知识:空指针风险与防御式编程

在实际开发中,如果数组中混入了 null 值,直接调用 .length() 会立即抛出 NullPointerException。

Java 8 的 Comparator 提供了 nullsFirst 或 nullsLast 工厂方法,能让我们优雅地定义空值的排序位置(排最前或排最后),从而避免程序崩溃。

示例:将 null 值视为最小值,排在最前面

java 复制代码
// 处理可能包含 null 的字符串数组
Arrays.sort(arr, Comparator.nullsFirst(Comparator.comparing(String::length)));
相关推荐
iCxhust7 小时前
51单片机电力载波应用开发(七)广播通讯
c语言·开发语言·单片机·嵌入式硬件·51单片机
殷色玫瑰7 小时前
C++ STL:stack、queue、priority_queue 与容器适配器详解
java·开发语言·数据结构·c++·算法·visualstudio
IT方大同7 小时前
java输入输出+方法
java·开发语言·python
滕州市燕猫虎计算机科技工作室个体工商户7 小时前
《Rust程序设计》学习笔记一
开发语言·rust·学习笔记·rust程序设计
Yyyyyy~7 小时前
【Java】String
java
Wang's Blog8 小时前
Java框架 SpringCloud 快速入门: 服务拆分之服务远程调用
java·开发语言·spring cloud
努力努力再努力wz8 小时前
【CUDA入门系列】CUDA编程实战:设备选择、显存管理、Kernel、Stream 与 Event 全流程梳理
开发语言·c++
Wang's Blog8 小时前
Java框架 SpringCloud 快速入门: 路由断言工厂
java·spring·spring cloud
ym hyd 1118 小时前
门诊挂号系统源码 Java+SpringBoot+Vue3 前后分离
java·vue.js·spring boot·毕设
杨丰玮4188 小时前
C语言核心语法
java·c语言·开发语言·学习方法