

函数接口是一个具有单个抽象方法的接口,接口设计主要是为了支持 Lambda 表达式和方法引用,使得 Java 能更方便地实现函数式编程风格。
特点和用途:
一个抽象方法,但可以有多个默认方法(default)或静态方法(static)。Java 8 提供了几个标准的函数接口,接口通常位于
java.util.function包中。
常见的函数接口:
Consumer<String> printConsumer = str -> System.out.println(str);
printConsumer.accept("Hello World!"); Supplier<Double> randomSupplier = () -> Math.random();
System.out.println(randomSupplier.get()); Function<Integer, String> intToString = num -> String.valueOf(num);
System.out.println(intToString.apply(123)); Predicate<Integer> isEven = num -> num % 2 == 0;
System.out.println(isEven.test(5)); // false UnaryOperator<Integer> square = num -> num * num;
System.out.println(square.apply(5)); // 25自定义函数接口:只需确保接口中只有一个抽象方法即可。
@FunctionalInterface
interface MyFunctionalInterface {
void myMethod();
// 允许有默认方法和静态方法
default void anotherMethod() {
System.out.println("Default method");
}
}
// 使用自定义的函数接口
MyFunctionalInterface myFunc = () -> System.out.println("Hello Custom Functional Interface");
myFunc.myMethod();
myFunc.anotherMethod();Lambda 表达式可以被视为匿名函数的一种声明方式,允许将函数作为方法参数传递,或者在需要函数式接口的地方使用。
基本结构:
// parameters:参数列表,可以为空或非空
// ->:箭头符号,分隔参数列表和Lambda表达式的主体
// expression:单行表达式作为 Lambda 主体
(parameters) -> expression
// { statements; }:代码块作为 Lambda 主体,可以包含多条语句和返回语句
(parameters) -> { statements; }表达式的特点:
案例:通过 Lambda 表达式为
MathOperation接口的operation方法提供了四种不同的实现:加法、减法、乘法和除法。
interface MathOperation {
int operation(int a, int b);
}public class LambdaDemo {
public static void main(String[] args) {
// Lambda 表达式实现加法
MathOperation addition = (int a, int b) -> a + b;
System.out.println("10 + 5 = " + operate(10, 5, addition));
// Lambda 表达式实现减法
MathOperation subtraction = (a, b) -> a - b;
System.out.println("10 - 5 = " + operate(10, 5, subtraction));
// Lambda 表达式实现乘法
MathOperation multiplication = (int a, int b) -> { return a * b; };
System.out.println("10 * 5 = " + operate(10, 5, multiplication));
// Lambda 表达式实现除法
MathOperation division = (a, b) -> a / b;
System.out.println("10 / 5 = " + operate(10, 5, division));
}
private static int operate(int a, int b, MathOperation mathOperation) {
return mathOperation.operation(a, b);
}
}Lambda 表达式有自己特定的作用域规则,可以捕获和访问其周围的变量, 可以随意引用外部变量,但如果外部变量是在当前作用域声明的,则一定不可以进行第二次赋值,哪怕是在 lambda 语句之后。
1.局部变量:Lambda 表达式可以访问它们所在方法的局部变量,但是这些变量必须是隐式最终或实际上是最终的(final)。这意味着变量一旦赋值后不再改变。Lambda 表达式内部不允许修改这些局部变量的值,否则编译器会报错。
public class LambdaScopeDemo {
public static void main(String[] args) {
int num = 10; // 局部变量
MathOperation addition = (int a, int b) -> {
// num = 5; // 错误!Lambda 表达式不能修改局部变量的值
// 这里访问了局部变量 num
return a + b + num;
};
System.out.println(addition.operation(5, 3));
}
}2.字段:Lambda 表达式可以访问外部类的字段(成员变量),包括实例字段和静态字段。
public class LambdaScopeDemo {
private static int staticNum; // 静态字段
private int instanceNum; // 实例字段
public void testLambdaScope() {
MathOperation addition = (int a, int b) -> {
// 访问实例字段和静态字段
int result = a + b + instanceNum + staticNum;
return result;
};
System.out.println(addition.operation(5, 3));
}
}3.接口的默认方法:Lambda 表达式可以访问接口中定义的默认方法,但不能访问接口中定义的实例字段。
使用Lambda表达式时,常见的场景包括对集合的遍历、排序、过滤以及与函数式接口的结合使用。
常见的Java 8 Lambda表达式示例:
1.遍历集合
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// 使用 Lambda 表达式遍历集合
names.forEach(name -> System.out.println(name));
}2.使用函数式接口进行计算
参考:二、Lambda表达式简介
3.使用函数式接口进行条件过滤
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 使用 Lambda 表达式过滤偶数
System.out.println("偶数:");
filter(numbers, n -> n % 2 == 0);
// 使用 Lambda 表达式过滤大于 5 的数
System.out.println("大于 5 的数:");
filter(numbers, n -> n > 5);
}
private static void filter(List<Integer> numbers, Predicate<Integer> condition) {
for (Integer number : numbers) {
if (condition.test(number)) {
System.out.print(number + " ");
}
}
System.out.println();
}4.使用Comparator进行集合排序
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// 使用 Lambda 表达式进行排序(根据字符串长度)
names.sort((s1, s2) -> s1.length() - s2.length());
// 输出排序后的结果
names.forEach(name -> System.out.println(name));
}5.使用 Runnable 执行代码块
参考:五、Runnable Lambda表达式
使用 Lambda 表达式来简洁地实现
Runnable接口的实例化。Runnable接口是一个函数接口,它只包含一个抽象方法void run(),用于定义一个可以由线程执行的任务。
1.匿名内部类(Java 7 及之前):
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Running in a separate thread");
}
};
Thread thread = new Thread(runnable);
thread.start();2.Lambda 表达式(Java 8+):
Runnable runnable = () -> {
System.out.println("Running in a separate thread");
};
Thread thread = new Thread(runnable);
thread.start();3.更简洁的方式:任务非常简单,可以进一步简化,直接将 Lambda 表达式作为参数传递给 Thread 的构造函数:
Thread thread = new Thread(() -> {
System.out.println("Running in a separate thread");
});
thread.start();这种方式避免了显式地声明 Runnable 变量,使代码更加紧凑和易读。
案例:
public static void main(String[] args) {
// 使用 Lambda 表达式创建一个新的线程
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("线程执行:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 启动线程
thread.start();
}莫道君行早,更有早行人
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。