Java8新特性(1):Lambda表达式

简介:

Java8新特性(1):Lambda表达式

Lambda表达式可以理解为一种匿名函数:没有名称,但有参数列表、函数主体、返回类型。它是行为参数化的一种实现,行为参数化是指将不同的行为作为参数传递给方法,方法的所具备的能力取决于它接收的行为参数。使用Lambda表达式使我们不必为这些行为去编写一堆固定的实现类就能应对不断变化的需求,在1.8之前,可以使用匿名内部类的方式达到相同的效果,只是相对于Lambda表达式来说,匿名内部类的方式会显得啰嗦。

函数式接口
Lambda表达式的使用依赖于函数式接口,只有在接受函数式接口的地方才可以使用Lambda表达式。函数式接口是指只声明了一个抽象方法的接口,可以有多个静态方法、默认方法,如下所示:

Copy
@FunctionalInterface
public interface Calculation {

int calculate(int a, int b);
AI 代码解读

}
@FunctionalInterface注解表示被标注的接口将被设计成一个函数式接口,不是必须的,它主要是在接口违背函数式接口原则时会出现编译错误。比如修改Calculation接口,再添加一个抽象方法就会出现Multiple non-overriding abstract methods found in interface com.cf.demo.lambda.Calculation编译错误:

Copy
//编译错误:Multiple non-overriding abstract methods found in interface com.cf.demo.lambda.Calculation
@FunctionalInterface
public interface Calculation {

int calculate(int a, int b);

int calculate2(int a, int b);
AI 代码解读

}
注意:Object类的方法是特例,即使接口声明了多个Object类的方法,也不会被算入“只声明了一个抽象方法”的计数中。如下Calculation接口是正确的函数式接口:

Copy
@FunctionalInterface
public interface Calculation {

int calculate(int a, int b);

boolean equals(Object obj);
AI 代码解读

}

Java8提供了一些常用的函数式接口,位于java.util.function包下,并且为了避免装箱操作,还提供了和基本类型对应的接口,我们在实际使用时,可以优先使用这些内置的函数式接口。当然在某些情况我们也需要使用自定义的函数式接口,如需要在Lambda表达式中抛异常时,这种情况就需要自定义一个函数式接口,并声明异常。

Lambda表达式语法
Lambda表达式由参数列表、箭头(Lambda操作符)、Lambda主体三个部分组成。Lambda表达式的参数列表要和函数式接口的参数列表相对应,Lambda主体的返回值也要和函数式接口的返回类型相对应。现在有如下doArithmetic方法,接收两个整型参数以及一个Calculation,doArithmetic方法的行为是由传递的Calculation来决定的,我们可以调用该方法传递不同的Calculation来完成不同的计算:

Copy

public static int doArithmetic(int a, int b, Calculation calculation){
    return calculation.calculate(a, b);
}
AI 代码解读

现在要计算两个数的乘积,用内部类的方式:

Copy

int result = doArithmetic(3, 2, new Calculation() {
        @Override
        public int calculate(int a, int b) {
            return a * b;
        }
});
System.out.println(result);//6
AI 代码解读

用Lambda表达式的方式要更简洁:

Copy

int result = doArithmetic(3, 2, (int a, int b) -> a * b);
System.out.println(result);//6
AI 代码解读

(int a, int b)是Lambda表达式的参数列表部分,只有一个参数的时候可以省略小括号,这里有多个参数,所以要保留小括号。参数类型可以省略,因为Java编译器能通过上下文推断出数据类型,无需显示的声明:

Copy

int result = doArithmetic(3, 2, (a, b) -> a * b);
System.out.println(result);//6
AI 代码解读

Lambda主体只有一个语句时,可以省略{}和return,(int a, int b) -> a * b)就是省略之后的写法,我们也可以使用完整的写法:

Copy

int result = doArithmetic(3, 2, (a, b) -> {
        return a * b;
});
System.out.println(result);//6
AI 代码解读

当需要在Lambda表达式中使用‘外部局部变量’时,这个‘外部局部变量’默认是final的,‘外部局部变量’这里是指非Lambda表达式内部定义的局部变量。修改doArithmetic方法,添加一个‘外部局部变量’,为乘积赋个初始值,以下代码是编译不通过的:

Copy

int initialValue = 1;
int result = doArithmetic(3, 2, (a, b) -> a * b + initialValue);
initialValue = 2;//Variable used in lambda expression should be final or effectively final
System.out.println(result);
AI 代码解读

方法引用
方法引用可以对‘某种特殊情况’下的Lambda表达式进行简化,‘某种特殊情况’是指Lambda表达式要做的事情别的方法实现了,那我们就可以直接使用这个方法,然后像Lambda表达式一样传递即可。方法引用的语法为目标引用放在分隔符::前,方法的名称放在后面,目标引用可以是类名也可以是对象名。通过以下三个例子来介绍方法引用的三种使用方法,新增Arithmetic类,Arithmetic类包含一个静态方法和一个实例方法:

Copy

public class Arithmetic {
    public static int multiply(int a, int b){
        return a * b;
    }

    public int add(int a, int b){
        return a + b;
    }
}
AI 代码解读

1.指向静态方法的方法引用

Copy

int multiplyResult = doArithmetic(3, 2, Arithmetic::multiply);
System.out.println(multiplyResult);//6
AI 代码解读

2.指向现有对象的实例方法的方法引用

Copy

Arithmetic arithmetic = new Arithmetic();
int addResult = doArithmetic(3, 2, arithmetic::add);
System.out.println(addResult);//5
AI 代码解读

3.指向任意类型实例方法的方法引用,这种情况有个特点,就是在引用一个对象的方法,而这个对象本身是Lambda的一个参数。比如现在需要实现比较两个数的大小,首先修改calculate方法参数类型为包装类型Integer:

Copy

@FunctionalInterface
public interface Calculation {
    int calculate(Integer a, Integer b);
}
AI 代码解读

比较a和b的大小可以这样写:

Copy

int result = doArithmetic(3, 2, Integer::compareTo);//Integer::compareTo等于a.compareTo(b) 
System.out.println(result);//1
AI 代码解读

构造函数引用
对于一个现有构造函数,可以使用它的名称和new来创建一个它的引用: ClassName::new。再使用构造函数引用时,需要调用的构造器参数列表要和函数式接口的抽象方法的参数要一致。举个例子,现在添加了两个生成String对象的方法:

Copy

public static String generateString(Supplier<String> supplier) {
    return supplier.get();
}

public static String generateString(String value, Function<String, String> function) {
    return function.apply(value);
}
AI 代码解读

分别使用构造函数引用:

Copy

String result = generateString(String::new);//调用String()构造方法
System.out.println(result);

result = generateString("hello Lambda", String::new);//调用String(String original)构造方法
System.out.println(result);
AI 代码解读

作者: 布禾

出处:https://www.cnblogs.com/seve/p/12765098.html

目录
打赏
0
0
0
0
10
分享
相关文章
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
112 6
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
Java中的Lambda表达式:简洁代码的利器####
本文探讨了Java中Lambda表达式的概念、用途及其在简化代码和提高开发效率方面的显著作用。通过具体实例,展示了Lambda表达式如何在Java 8及更高版本中替代传统的匿名内部类,使代码更加简洁易读。文章还简要介绍了Lambda表达式的语法和常见用法,帮助开发者更好地理解和应用这一强大的工具。 ####
Java中的Lambda表达式:简化代码的现代魔法
在Java 8的发布中,Lambda表达式的引入无疑是一场编程范式的革命。它不仅让代码变得更加简洁,还使得函数式编程在Java中成为可能。本文将深入探讨Lambda表达式如何改变我们编写和维护Java代码的方式,以及它是如何提升我们编码效率的。
|
4月前
|
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
48 0
探索Java中的Lambda表达式与Stream API
【10月更文挑战第22天】 在Java编程中,Lambda表达式和Stream API是两个强大的功能,它们极大地简化了代码的编写和提高了开发效率。本文将深入探讨这两个概念的基本用法、优势以及在实际项目中的应用案例,帮助读者更好地理解和运用这些现代Java特性。
Java 8新特性之Lambda表达式与Stream API的探索
【9月更文挑战第24天】本文将深入浅出地介绍Java 8中的重要新特性——Lambda表达式和Stream API,通过实例解析其语法、用法及背后的设计哲学。我们将一探究竟,看看这些新特性如何让Java代码变得更加简洁、易读且富有表现力,同时提升程序的性能和开发效率。
|
7月前
|
Java 8新特性:Lambda表达式与Stream API的深度解析
【7月更文挑战第61天】本文将深入探讨Java 8中的两个重要特性:Lambda表达式和Stream API。我们将首先介绍Lambda表达式的基本概念和语法,然后详细解析Stream API的使用和优势。最后,我们将通过实例代码演示如何结合使用Lambda表达式和Stream API,以提高Java编程的效率和可读性。
19 Java8概述(Java8概述+lambda表达式+函数式接口+方法引用+Stream+新时间API)
19 Java8概述(Java8概述+lambda表达式+函数式接口+方法引用+Stream+新时间API)
85 8

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等