Lambda表达式语法及应用

前言:

JDK8后,源码中开始应用Lambda表达式,所以如果想读懂源码的同学学习它是绕不过去的,至于lambda表达式在不在开发中使用,就要看自己的需求啦,他的优点很明显,简洁,非常容易并行计算,提升开发效率,缺点是不并行计算时很多时候还没有for循环快,不容易调试,对于没有学过lambda表达式的程序员的可读性差,所以学不学看自己需求。这篇文章主要讲解下Lambda表达式语法及应用,感兴趣的可以一起探讨下。

正文:

一、什么是Lambda

1.Lambda概述

Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

Lambda 表达式体现的是轻量级函数式编程思想。

‘->’ 符号式Lambda表达式核心操作符号,符号左侧是操作数,符号右侧是操作表达式

2.MCAD模式

MCAD模式即Model Code as Data,编码及数据,尽可能轻量级的将代码封装为数据。在没有出现Lambda表达式之前,我们往往都是通过匿名内部类来让代码变得轻量级。

3.问题

匿名内部类的写法存在以下几种问题:

语法冗余,我们可以看到下面使用匿名内部类和lambda表达式的写法上的区别

 public static void main(String[] args) {
        //1.传统模式下,新线程的创建
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("threading..."+Thread.currentThread().getId());
            }
        }).start();
        
        //2.jdk8新特性,lambda表达式优化线程
        new Thread(()->{
            System.out.println("threading..."+Thread.currentThread().getId());
        }).start();
    }

变量捕获 

匿名内部类的里面的this关键字,表示当前匿名内部类型的对象。

lambda表达式的里面的this关键字,表示的就是所属方法所在类型的对象。

为什么要用Lambda

  • 它不是解决未知问题的新技术。
  • 对现有解决方案的语义化优化。
  • 需要根据实际需求考虑性能问题。

二、Lambda表达式基础知识

1.函数式接口

函数式接口,就是Java类型系统中的接口。

函数式接口,是只包含一个接口方法的特殊接口。

/**
* @Description 是否快乐的接口
**/
@FunctionalInterface
public interface IsHappy {
    /*     
    * @Description 检验是否快乐     
    * @Param [key]     
    * @return java.lang.String
    **/
    String verifyHappy(String key);
}

我们在加上语义化检测注解:@ FunctionalInterface后,只可以定义一个接口方法否则会报错

但是函数式接口是可以和默认接口方法,静态接口方法,来自Object继承的方法。 

2.Lambda表达式和函数式接口的关系

函数式接口,只包含一个操作方法。

Lambda表达式,只能操作一个方法。

Java中的Lambda表达式,核心就是一个函数式接口的实现。

3.常见的函数接口

java.util.function.Predicate<T> (接收参数对象T,返回一个boolean类型结果)

public class Test5 {
    public static void main(String[] args) {
        Predicate<String> pre=(String meimei)-> {
            return "yujie".equals(meimei);
        };
        System.out.println(pre.test("luoli"));
        System.out.println(pre.test("yujie"));
    }

}

运行结果:

java.util.function.Consumer<T>(接收参数对象T,不返回结果)

Consumer<String> con=(String message)->{
            System.out.println("要发送的消息: "+message);
            System.out.println("消息发送完成");
        };
        con.accept("新年快乐");

运行结果:

java.util.function.Function<T,R> (接收参数对象T,返回结果对象R)

 Function<String,Integer> fun=(String gender)->{
            return "male".equals(gender)?1:0;
        };
        System.out.println(fun.apply("male"));

运行结果:

4.Lambda基本语法

声明:就是和lambda表达式绑定的接口类型。

参数:包含在一对圆括号中,和绑定的接口中的抽象方法中的参数个数及顺序一致。

操作符:->

执行代码块:包含在一对大括号中,出现在操作符号的右侧。

[接口声明] = (参数)->{执行代码块};

注意事项:

  • lambda表达式,必须和接口进行绑定。
  • lambda表达式的参数,可以附带0个到n个参数,括号中的参数类型可以不用指定,jvm在运行时,会自动根据绑定的抽象方法中的参数进行推导
  • lambda表达式的返回值,如果代码块只有一行,并且没有大括号,不用写return关键字,单行代码的执行结果,会自动返回。
  • 如果添加了大括号,或者有多行代码,必须通过return关键字返回执行结果。

没有参数,没有返回值的lambda表达式绑定的接口

public class Test6 {
    public static void main(String[] args) {
      ILambda1 i1=()->{
          System.out.println("放假了");
          System.out.println("快了");
      };
      i1.test();
      //只有一行代码的时候可以省略花括号
      ILambda1 i2=()-> System.out.println("在坚持一下");
      i2.test();
    }
}
//没有参数,没有返回值的lambda表达式绑定的接口
 interface ILambda1{
    void test();
 }

带有参数,没有返回值的lambda表达式 

public class Test6 {
    public static void main(String[] args) {
        ILambda2 i1=(String n,int a)->{
            System.out.println(n+"-----------"+a);
        };
        i1.test("我喜欢",18);
        //lambda表达式会自动进行类型推导
        ILambda2 i2=(n,a)->{
            System.out.println(n+"-----------"+a);
        };
        i2.test("我喜欢",18);
    }


//带有参数,没有返回值的lambda表达式 
 interface ILambda2{
        void test(String name, int age);
}
}

带有参数,带有返回值的lambda表达式  

public class Test6 {
    public static void main(String[] args) {
        ILambda3 i1=(int x,int y)->{
            int z=x+y;
            return z;
        };
        System.out.println(i1.test(2,18));
        //lambda表达式会自动进行类型推导
        ILambda3 i2=(x,y)->x+y;
        System.out.println(i2.test(2,18));
    }


//带有参数,带有返回值的lambda表达式  
 interface ILambda3{
        int test(int x ,int y);
}
}

5.类型检查

public class Test6 {
  public static void test(MyInterface<String, List> inter){
      List<String> list=inter.strategy("hello",new ArrayList());
      System.out.println(list);
  }

    public static void main(String[] args) {
        test(new MyInterface<String, List>() {
            @Override
            public List strategy(String s, List list) {
                list.add(s);
                return list;
            }
        });
        test((x,y)->{
            y.add(x);
            return y;
        });
    }
}
@FunctionalInterface
interface MyInterface<T,R>{
    R strategy(T t,R r);
}

6.Lambda运行原理

1.lambda表达式在编译的时候生成私有的静态方法,在静态方法中会做一个方法的实现来吹

2.并且编译时还会对lambda表达式的目标接口来生成一个内部类型,实现这个接口

3.在实现接口的方法中会第一步生成的静态方法进行调用

4.最后通过new了一个内部类型对象来调用方法执行lambda表达式

三、Lambda表达式高级扩展

1.lambda对集合的基本操作

public class Test {
    public static void main(String[] args) {
        //存储Person对象的列表
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("dada","男",18));
        personList.add(new Person("dada","男",20));
        personList.add(new Person("dada","男",23));
        personList.add(new Person("dada","男",22));
        personList.add(new Person("dada","男",16));
        personList.add(new Person("dada","男",12));
      
        //lambda表达式的实现方式
        Collections.sort(personList,(p1,p2)->p1.getAge()-p2.getAge());
        System.out.println("lambda表达式的实现方式"+"-------------"+personList);
       
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Person{
    /**
     * 姓名
     **/
    private String name;
    /**
     * 性别
     **/
    private String gender;
    /**
     * 年龄
     **/
    private int age;
}

2.什么是stream

lambda表达式操作的stream并不是指io中的流对象,也不是集合元素,也不是数据结构,并不能存储数据,而是和算法和运算有关的流。

Stream结合lambda表达式的demo

 public static void main(String[] args) {
        //1.添加测试数据:存储多个账号的列表
        List<String> accounts = new ArrayList<>();
        accounts.add("dada");
        accounts.add("dada1");
        accounts.add("dada12");
        accounts.add("dada123");
        accounts.add("dada1234");
        //1.1 业务要求:长度大于等于5的有效账号
        for (String a:accounts) {
           if(a.length()>=5){
               System.out.println("有效账号:"+a);
           }
        }

        //1.3 Stream结合lambda表达式,完成业务处理
        List<String> collect = accounts.stream().filter(s -> s.length() >= 5).collect(Collectors.toList());
        System.out.println(collect);
    }

总结: 

快过年了,提前祝大家新年快乐。

然后还是分享一个鸡汤:如果事与愿违,请相信一定是另有安排。

我是阿达,一名喜欢分享知识的程序员,时不时的也会荒腔走板的聊一聊电影、电视剧、音乐、漫画,这里已经有16844位小伙伴在等你们啦,感兴趣的就赶紧来点击关注我把,哪里有不明白或有不同观点的地方欢迎留言! 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C++ lambda 表达式的语法如下: ``` [capture](parameters) -> return_type { body } ``` 其中: - `capture`:捕获列表,用于指定 lambda 表达式内部可访问的外部变量。捕获列表可以为空,也可以使用`[]`、`[=]`、`[&]`等形式进行指定。 - `[]`:不捕获任何外部变量。 - `[=]`:以值方式捕获所有外部变量。 - `[&]`:以引用方式捕获所有外部变量。 - `[var]`:以值方式捕获变量 `var`。 - `[&var]`:以引用方式捕获变量 `var`。 - `parameters`:参数列表,用于指定 lambda 表达式的参数。 - `return_type`:返回类型,用于指定 lambda 表达式的返回类型。可以省略,编译器会自动推导。 - `body`:函数体,用于实现 lambda 表达式的逻辑。 下面是一个 lambda 表达式的示例: ```cpp #include <iostream> int main() { int x = 5; int y = 10; // Lambda 表达式捕获外部变量 x,并接受一个参数 a auto lambda = [x](int a) { return x + a; }; int result = lambda(y); std::cout << "Result: " << result << std::endl; // 输出: 15 return 0; } ``` 在上面的示例中,lambda 表达式 `[x](int a) { return x + a; }` 捕获了外部变量 `x`,并接受一个参数 `a`。在 lambda 表达式内部,它实现了将 `x` 和 `a` 相加的逻辑,然后通过调用 `lambda(y)` 来计算结果,最后将结果输出到控制台。 请注意,由于 lambda 表达式的返回类型可以自动推导,所以在这个示例中我们没有显式指定返回类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心的码字达

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值