Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Lambda表达式

Lambda表达式

作者头像
十玖八柒
发布于 2022-08-01 01:18:16
发布于 2022-08-01 01:18:16
33400
代码可运行
举报
运行总次数:0
代码可运行

基本用法

Lambda表达式本质:用作接口的实现(其实就是把之前实现接口的步骤简化了)。接口必须是函数式接口

一句话说明函数式接口:接口只有一个抽象方法 函数式接口可以使用@FunctionalInterface注解进行校验,非函数式接口使用此注解会报错

-> :Lambda操作符 ->的左边:Lambda形参列表(即抽象方法中的形参列表) ->的右边:Lambda体(即重写后的抽象方法体) 格式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  <函数式接口>  <变量名> = (参数1, 参数2...) -> {
    //方法体
  };

 // 或者

  <函数式接口>  <变量名> = (参数1, 参数2...) -> 表达式;

参数个数可为0至n个。多个参数需要用逗号,——分割。 当参数个数为1时,括号可省略; 当参数个数为0时,括号不可省略; 参数前可以不加参数类型(不加会自动推导)。 Lambda 体,可以是一个表达式,也可以是语句块;如果是多条语句,需要使用大括号{}包裹;如果只有一条语句则可省略大括号{},但是必须同时省略return; 表达式中不能加入 return 语句,因为在表达式中已经隐含了 return 语句;但是语句块中没有隐含,需要使用 return 语句;

示例1:只有一个参数,一条语句

注:Consumer是java.util包下的一个函数式接口

基本写法(匿名实现函数式接口,并调用):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Consumer<String> consumer = new Consumer<String>() {
    @Override
    public void accept(String s) {
        System.out.println(s);
    }
};
consumer.accept("测试方法一");

lambda写法(实现函数式接口,并调用):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//完整写法:
Consumer<String> consumer1 = (String s) -> {
    System.out.println(s);
};
consumer1.accept("测试方法一");

//写法二(省略数据类型)
Consumer<String> consumer2 = (s) -> {
    System.out.println(s);
};
consumer2.accept("测试方法三");

//写法三(lambda只需要一个参数时,参数的小括号可省略)
Consumer<String> consumer3 = s -> {
    System.out.println(s);
};
consumer3.accept("测试方法三");

// 写法四(最简写法)
Consumer<String> consumer4 = s -> System.out.println(s);
consumer4.accept("测试方法四");

示例2:只有一条语句,没有参数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("123");
    }
};

lambda:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Runnable r2 = () -> System.out.println("abc");

示例3:只有一条语句,且为返回语句 普通写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Comparator<Integer> comparator21 = new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return Integer.compare(o1,o2);
    }
};

lambda:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//只有一条语句时,可以省略大括号,如果是return的话,可直接省略return
Comparator<Integer> comparator22 = (o1, o2) -> Integer.compare(o1,o2);

示例四:参数个数为多条,语句为多条,且有返回值 基本写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  Comparator<Integer> comparator1 = new Comparator<Integer>() {
      @Override
      public int compare(Integer o1, Integer o2) {
          System.out.println("一");
          System.out.println("二");
          return Integer.compare(o1,o2);
      }
  };
System.out.println(comparator1.compare(0,9));

lambda:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Comparator<Integer> comparator2 = (o1, o2) -> {
    System.out.println("一");
    System.out.println("二");
    return Integer.compare(o1,o2);
};
System.out.println(comparator2.compare(0,9));

函数式接口

函数式接口只有一个抽象方法,但是可以有多个非抽象方法的接口(同理,任何接口,有且只有一个抽象方法,那么它就是一个函数式接口)。 我们在自定义函数式接口时,可以使用@FunctionalInterface注解进行约束校验。

自定义函数式接口 示例1:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@FunctionalInterface
interface FunctionTest{
    void testMethod(String name, int age);

    default void method2() {
       // 函数式接口只能有一个抽象方法,但是可以有多个非抽象方法
    }
}

lambda:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Test
public void LambdaTest(){
    FunctionTest functionTest = (name, age) -> System.out.println("姓名为:" + name + " | 年龄为:" + age);
    functionTest.testMethod("ahzoo",18); // 姓名为:ahzoo | 年龄为:18
}

示例2:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.jupiter.api.Test;


public class MethodTest {

    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    class User{
        private String name;
    }

    @FunctionalInterface
    interface UserService{
        User getUser();
    }

    @FunctionalInterface
    interface UserService2{
        User getUser(String name);
    }

    @Test
    public void userTest(){
        // 调用无参接口
        UserService userService = User::new;
        User user = userService.getUser();
        System.out.println(user); // MethodTest.User(name=null)

        // 调用有参接口
        UserService2 userService2 = User::new;
        User user2 = userService2.getUser("ahzoo");
        System.out.println(user2); // MethodTest.User(name=ahzoo)
        System.out.println(user2.getName()); // ahzoo
    }
}

引用方法

使用时机:

当我们不想重写某个匿名内部类的方法时,就可以使用lambda表达式的接口快速指向一个已经被实现的方法。将一个方法赋给一个变量或者作为参数传递给另外一个方法。

前提:

参数数量和类型与接口中定义的一致; 返回值类型与接口中定义的一致(一般也是一个函数式接口类型)。

引用格式: 方法归属者::方法名

静态方法的归属者为类名,普通方法归属者为对象; 方法名后面不能带参数。

常见引用: 对象::实例方法(例:instanceName::methodName类::静态方法(例:className::methodName类::实例方法

this::实例方法 super::实例方法

构造器::new 数组::new

示例一:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.Arrays;
import java.util.List;

public class MethodTest {
    public static void main(String[] args) {

        List<String> list = Arrays.asList("777", "999");
//        1. 对象::实例方法

        //        不使用引用:
        list.forEach(s -> new MethodTest().print(s));
        //        使用引用
        list.forEach(new MethodTest()::print);

//        2. 类::实例方法

        //        不使用引用:
        list.forEach(s -> MethodTest.toTest(s));
        //        使用引用
        list.forEach(MethodTest::toTest);

//        3. 类::静态方法

        //        不使用引用
        list.forEach(s -> System.out.println(s));
        //        使用引用
        list.forEach(System.out::println);

    }

    public void print(String s) {
        System.out.println("打印:" + s);
    }

    public static void toTest(String s) {
        System.out.println("静态:"+s);
    }
}

示例2:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.function.Supplier;
import org.junit.jupiter.api.Test;

public class MethodTest {

    @Test
    public void test() {
//        不使用引用
        Supplier<String> supplier = ()->new String();
        System.out.println(supplier);

//        使用引用
        Supplier<String> supplier2 = String::new;
        System.out.println(supplier2);
    }
}

作用域

在匿名内部类中,如果要引用外部变量,需要先将变量声明为final; 虽然在lambda表达式中并未要求一定要将外部变量声明为final,但其实在表达式中变量已经被隐式的声明为final,是不能对其进行修改的; 在lambda表达式中无法声明和局部变量相同的变量

错误示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int i = 1;
// 在lambda表达式中无法对外部变量(i)进行修改
Consumer<String> consumer = s -> System.out.println(i++); // 报错

错误示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 在lambda表达式中无法声明和局部变量(consumer)相同的变量(consumer)
Consumer<String> consumer = consumer -> System.out.println(consumer); // 报错

常用场景

其实在前面的示例中都已经写过了,这里进行一个总结

遍历

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        List<String> list = Arrays.asList("777", "999");

//        增强for
        for(String i : list){
            System.out.println(i);
        }

//         lambda写法:方法引用
        list.forEach(System.out::println);

排序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        List<Integer> list = Arrays.asList(999, 333, 777, 111);

// 匿名实现写法: 正序排序
        list.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        });


// lambda写法       

        //        正序排序时,参数数量和类型与接口中定义的一致(都是(m,n)),所以可以直接使用方法的引用
        list.sort(Integer::compare);
        System.out.println(list); // [111, 333, 777, 999]

        //      倒序排序时,参数为(m,n),接口中为(n,m),不一致,所以不能使用方法是引用
        list.sort((m, n) -> Integer.compare(n, m));
        System.out.println(list); // [999, 777, 333, 111]

线程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 匿名实现写法
 Runnable runnable = new Runnable() {
     @Override
     public void run() {
         System.out.println("启动新线程");
     }
 };
 new Thread(runnable).start();

 // lambda写法
 new Thread(() -> System.out.println("启动新线程")).start();
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
lambda表达式与函数式编程
lambda表达式是java支持函数式编程的实现方案,很多高级语言已经支持lambda表达式,像python、javascript等。lambda表达式使代码更加简洁,而且在理解了语法之后,可读性也更加好。
搬砖俱乐部
2019/09/25
6160
java8新特性(一):Lambda表达式
Lambda 是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
周三不加班
2019/09/03
4110
java8新特性(一):Lambda表达式
Java基础(二十五):Lambda表达式、方法引用、构造器引用
Java微观世界
2025/01/21
1940
Java基础(二十五):Lambda表达式、方法引用、构造器引用
Java8新特性----Lambda表达式详细探讨
​ Lambda是一个匿名函数,可以理解为一段可以传递的代码(将代码像数据一样传递);可以写出更简洁、更灵活的代码;作为一种更紧凑的代码风格,是Java语言表达能力得到提升
大忽悠爱学习
2021/11/15
2940
【JDK1.8 新特性】Lambda表达式
Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
CODER-V
2023/03/08
2800
Java8之熟透Lambda表达式
​ Lambda 表达式可以理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。
用户1195962
2019/09/29
5910
Java8之熟透Lambda表达式
Java8学习(3)- Lambda 表达式
猪脚:以下内容参考《Java 8 in Action》 本次学习内容: Lambda 基本模式 环绕执行模式 函数式接口,类型推断 方法引用 Lambda 复合 代码: https://github.com/Ryan-Miao/someTest/blob/master/src/main/java/com/test/java8/c3/AppleSort.java 上一篇: Java8学习(2)- 通过行为参数化传递代码--lambda代替策略模式 ---- 1. 结构 初始化一个比较器: Comparato
Ryan-Miao
2018/03/13
1.1K0
Java8学习(3)- Lambda 表达式
小朋友好好学学lambda表达式吧!
但他们的问题也很突出:就是**“噪声”**太多!想实现一个数组的比较功能,至少要写5行代码,但其中只有一行代码才是我们真正关注的!
你呀不牛
2021/12/02
3450
一文看懂 Java8 的 Lambda表达式!
IT领域的技术日新月异,Java14问世了,但是对于国内的许多程序员来说,连Java8都还没有真正掌握。
程序员小跃
2020/04/10
4650
JDK1.8新特性之Lambda表达式
Java8中引入了一个新的操作符“ -> ”,该操作符被称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分成两部分:
程序员波特
2024/01/19
1750
Java8 Lambda表达式与Stream API (一):Lambda表达式你要知道的Java8 匿名内部类、函数式接口、lambda表达式与Stream API都在这里
你要知道的Java8 匿名内部类、函数式接口、lambda表达式与Stream API都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本文主要讲解Java8 Stream API,但是要讲解这一部分需要匿名内部类、lambda表达式以及函数式接口的相关知识,本文将分为两篇文章来讲解上述内容,读者可以按需查阅。 Java 匿名内部类、lambda表达式与函数式接口 Java Stream API 本文是该系列博文的第一篇Java 匿名
WWWWDotPNG
2018/04/10
1.1K0
JDK8新特性总结
Lambda 需要一个参数,但是没有返回值。且 Lambda 若只需要一个参数时,参数的小括号可以省略。数据类型也可以省略,因为可由编译器推断得出,称为“类型推断”。
乐心湖
2021/01/18
3800
JDK8新特性总结
Java 8新特性
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。相比较串行的流,并行的流可以很大程度上提高程序的执行效率。
用户9615083
2022/12/25
1.4K0
Java 8新特性
Java8 Lambda表达式教程
public int add(int x, int y) {         return x + y;     }
用户7886150
2020/12/15
4610
【Java8新特性】Lambda表达式基础语法,都在这儿了!!
Lambda表达式在Java语言中引入了 “->” 操作符, “->” 操作符被称为Lambda表达式的操作符或者箭头操作符,它将Lambda表达式分为两部分:
冰河
2020/10/29
3760
【Java8新特性】Lambda表达式基础语法,都在这儿了!!
【数据结构】Lambda表达式的应用
lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块),Lambda 表达式(Lambda expression),基于数学中的λ演算得名,也可称为闭包(Closure) 。
用户11288949
2024/09/24
930
【数据结构】Lambda表达式的应用
【Java】:lambda 表达式
🔥 Lambda 表达式 是JDK8新增的特性,Lambda 表达式 可以取代大部分匿名内部类,写出更优雅的Java代码,尤其在集合的遍历和其他集合操作中,可以将函数作为一个方法的参数,也就是函数作为参数传递到方法中,极大地优化代码结构JDK也提供了大量的内置函数式接口供开发者使用,使得 Lambda 表达式 的运用更加方便、高效。
IsLand1314
2024/12/20
1360
【Java】:lambda 表达式
Lambda表达式
Lambda表达式是可以在函数式接口上使用的。函数式接口就是只定义一个抽象方法的接口。比如:
后端码匠
2019/09/02
6410
函数式编程:Lambda 表达式
曾经读过的依然令我感动的句子,生活总是不如意,但往往是在无数痛苦中,但往往是在无数痛苦中,在重重矛盾
RainbowSea
2023/03/06
6950
Java8 Lambda表达式入门
Lambda表达式的实质就是一个匿名函数。C#3.0引入了Lambda表达式,Java8也不甘示弱。Java8发布很久了,今天安装了JDK体验了Java8中的Lambda表达式。
卡尔曼和玻尔兹曼谁曼
2019/01/22
5440
相关推荐
lambda表达式与函数式编程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验