Java Lambda表达式入门:一行代码实现简单函数式接口

你有没有想过,每次处理只有一个抽象方法的接口时,都要写一大段匿名内部类代码?比如启动一个线程,或者对集合排序,这些地方都需要实现一个只有一个方法的接口,代码看起来总是显得有些繁琐。Java 8引入的Lambda表达式,就是为了解决这种“代码冗余”的问题,让我们能用更简洁的方式实现这些简单的函数式接口。

为什么需要Lambda表达式?

在Java 8之前,如果要使用只有一个抽象方法的接口(比如RunnableComparator),通常需要写一个匿名内部类。例如,启动一个线程时,代码可能像这样:

// 旧写法:使用匿名内部类实现Runnable
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("线程运行了!");
    }
}).start();

这段代码中,new Runnable() {}是匿名内部类,包含了run()方法的实现。但对只有一行逻辑的情况来说,这种写法显得冗余:需要写new Runnable()@Override和大括号,反而影响了代码的简洁性。

Lambda表达式的出现,就是为了用更简短的语法替代这种繁琐的匿名内部类写法。

什么是函数式接口?

要理解Lambda表达式,首先要明白函数式接口的概念:函数式接口是只有一个抽象方法的接口。比如:
- Runnable接口:只有一个run()方法(无参数、无返回值)。
- Comparator接口:只有一个compare(T o1, T o2)方法(两个参数,返回int)。

Java 8还提供了很多内置函数式接口(如ConsumerSupplier等),但对初学者来说,先掌握RunnableComparator这类基础接口就够了。

Lambda表达式的语法基础

Lambda表达式的核心语法是“参数列表 -> 表达式体”,具体可分为以下几种情况:

1. 无参数的情况

如果函数式接口的抽象方法没有参数,参数列表用空括号()表示,表达式体直接写结果。例如:

() -> System.out.println("Hello, Lambda!")

2. 1个参数的情况

如果只有一个参数,小括号可以省略,直接写参数名。例如:

s -> System.out.println(s)  // 等价于 (String s) -> System.out.println(s)

3. 多个参数的情况

参数列表用小括号包裹,类型可省略(编译器自动推断)。例如:

(a, b) -> a + b  // 等价于 (int a, int b) -> a + b

4. 表达式体的写法

  • 单行表达式:如果表达式体只有一行代码,大括号{}可以省略,结果会自动返回。例如:(a, b) -> a - b
  • 多行表达式:如果有多行代码,必须用大括号,且需要显式写return。例如:
  (a, b) -> {
      int result = a * 2 + b;
      return result;
  }

实例演示:用Lambda简化常见场景

场景1:使用Runnable接口(线程)

旧写法(匿名内部类):

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("线程启动了!");
    }
}).start();

Lambda简化后:

new Thread(() -> System.out.println("线程启动了!")).start();

解释()表示无参数,->后直接写run()的逻辑,一行代码搞定。

场景2:使用Comparator接口(排序)

对字符串列表按长度排序,旧写法:

List<String> list = Arrays.asList("apple", "banana", "cherry");
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return a.length() - b.length();
    }
});

Lambda简化后:

Collections.sort(list, (a, b) -> a.length() - b.length());

解释(a, b)compare的两个参数,->后直接返回长度差,无需大括号和return

场景3:自定义函数式接口

假设我们自定义一个简单的函数式接口Calculator,只有一个add方法:

@FunctionalInterface // 确保是函数式接口(仅一个抽象方法)
interface Calculator {
    int add(int a, int b);
}

用Lambda实现它:

Calculator calc = (a, b) -> a + b;
System.out.println(calc.add(3, 5));  // 输出 8

解释(a, b)对应add的参数,a + b是返回值,一行代码完成接口实现。

总结:Lambda表达式的优势

Lambda表达式让代码更简洁、可读性更高,尤其适合处理只有一个抽象方法的函数式接口。通过参数列表 -> 表达式体的语法,我们能用一行代码替代冗长的匿名内部类,大幅减少模板代码,让逻辑更清晰。

掌握Lambda表达式后,你会发现处理线程、集合排序等场景变得异常简单。后续学习中,还可以结合Java 8的Stream API等特性,进一步提升代码效率!

小夜