当前位置: 首页 > news >正文

JDK8新特性之Lambda表达式

这里写目录标题

  • 一、概念
    • 1、基本概念
  • 二、Lambda表达式的使用
    • 1、函数式接口
    • 2、语法
    • 3、基本使用样例:
  • 三、Lambda表达式在集合中使用
    • 1、集合遍历
    • 2、集合排序
    • 3、集合过滤
    • 4、集合映射
    • 5、集合归约
  • 四、方法引用
    • 1、对象::实例方法
    • 2、类::静态方法
    • 3、类::实例方法
  • 五、构造引用
  • 六、总结

一、概念

1、基本概念

Lambda表达式是Java8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。举例说明下:
现在有一个接口:Message,里面包含抽象方法send(),表示message的发送动作。因为不同的消息发送方式不一样,所以具体方法在实现类中完成,这里就形成了如下代码:
Message:

public interface Message {void send();
}

实现方法调用:

public class MsgDemo {@Testpublic void test01(){sendMsg(new Message() {@Overridepublic void send() {System.out.println("这是一个Email信息");}});}public void sendMsg(Message msg){msg.send();}@Testpublic void test02(){sendMsg(()->{System.out.println("这是一个短信信息");});}
}

test01就是常规写法:sendMsg需要一个Message接口作为参数,其中Message接口的抽象方法send方法是用来实现具体方法的核心。为了省去Message的实现类,不得不使用匿名内部类,覆盖重写抽象方法send().
test02就是Lambda表达式去实现一个SMS消息的实现,简化了匿名内部类的使用,语法更加简单。
总而一句话:Lambda表达式是一种语法糖,它是用于简化匿名实现函数式接口的一种语法。
语法糖:是指在编程语言中引入的一种语法,它可以使代码更易读、更简洁,但并没有引入新的功能或改变语言的底层机制。语法糖并不会改变语言的语义,只是提供了一种更方便的编写方式。

二、Lambda表达式的使用

1、函数式接口

只有一个抽象方法的接口就是函数式接口,Lambda表达式的前置条件就是该接口必须是函数式接口。
@FunctionalInterface注解:该注解修饰的接口只能声明一个抽象方法。
其实我们的Lambda表达式就是对函数式接口的一种简写方式,所以只有是函数式接口,我们才能用Lambda表达式;再换句话说,Lambda表达式需要函数式接口的支持

2、语法

Lambda省去了面向对象的条条框框,它的标准格式由三个部分组成:

(参数类型  参数名称) -> {代码提;
}

参数列表:
表达式的参数列表位于圆括号中,因为入参的类型在接口中是定义好的,可以不写,只写参数名,参数名可以随意起名。参数可以是零个或多个,如果只有一个参数,圆括号可以省略。如果没有参数,则圆括号不可省略,使用空括号。

箭头符号:
箭头符号 -> 将参数列表与 Lambda 表达式的主体(或函数体)分隔开。

表达式主体:
表达式主体可以是一个表达式,也可以是一个代码块。方法体只有一句话的时候,{} 和 return 可以省略。

3、基本使用样例:

无返回值无形参的抽象方法:

public interface MyInterface1 {public abstract void show();}
    public static void main(String[] args) {MyInterface1 test=new MyInterface1() {@Overridepublic void show() {System.out.println("show 方法执行了..");}};test.show();//简写MyInterface1 test1 =() ->System.out.println("show1 方法执行了..");test1.show();}

无返回值有形参的抽象方法:

public interface MyInterface2 {public abstract void show(int a,int b);}
    public static void main(String[] args) {MyInterface2 test=new MyInterface2() {@Overridepublic void show(int a, int b) {System.out.println(a+b);}};test.show(10,20);//简写1:方法命可以自己推断出来MyInterface2 test1 = (int a,int b) ->{System.out.println(a+b);};test1.show(20,30);//简写2:可以省略形参类型MyInterface2 test2 = (a,b) ->{System.out.println(a+b);};test2.show(30,40);//简写3:如果抽象方法中只有一行代码,可以省略方法体的大括号,当然,如果不止一行,就不能省略MyInterface2 test3 = (a,b) ->System.out.println(a+b);test3.show(40,50);}

有返回值的抽象方法:

public interface MyInterface3 {public abstract int show(int a,int b);}
    public static void main(String[] args) {MyInterface3 test=new MyInterface3() {@Overridepublic int show(int a, int b) {return a-b;}};System.out.println(test.show(20,10));//简写1:MyInterface3 test2 = (int a, int b) -> {return a - b;};System.out.println(test2.show(30, 10));//简写2:MyInterface3 test3=(a,b)->{return a-b;};System.out.println(test3.show(40,10));//简写3:有返回值的方法,不能直接去点大括号,还要去掉returnMyInterface3 test4=(a,b)->a-b;System.out.println(test4.show(50,10));}

三、Lambda表达式在集合中使用

为了能够让Lambda和Java的集合类集更好的一起使用,集合当中,也新增了部分接口,以便与Lambda表达式对接。要用Lambda遍历集合就一定要看懂源码。

1、集合遍历

    private static List<String> list;static {list= new ArrayList<>();list.add("Java");list.add("Python");list.add("C++");}@Testpublic void test1(){list.forEach(s -> System.out.println(s));}

2、集合排序

    @Testpublic void test2(){Collections.sort(list, (s1, s2) -> s2.compareTo(s1));}

3、集合过滤

    @Testpublic void test3(){// 使用 Lambda 表达式过滤集合List<String> filteredList = list.stream().filter(s -> s.startsWith("P")).collect(Collectors.toList());System.out.println(filteredList); // 输出:[Python]}

4、集合映射

    @Testpublic void test4(){// 使用 Lambda 表达式映射集合List<String> mappedList = list.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());System.out.println(mappedList); // 输出:[JAVA, PYTHON, C++]}

5、集合归约

    @Testpublic void test5(){List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);// 使用 Lambda 表达式归约集合int sum = list.stream().reduce(0, (a, b) -> a + b);System.out.println(sum); // 输出:6}

四、方法引用

方法引用其实是Lambda表达式的另一种写法,当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用;
注意: 实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!
方法引用:使用操作符::将方法名和对象或类的名字分隔开来,三种主要使用情况为:

  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法

1、对象::实例方法

    public static void main(String[] args) {Consumer<String> consumer=new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}};consumer.accept("aaaaaaaa");//简写1:Consumer<String> consumer1 = (String s) -> {System.out.println(s);};consumer1.accept("abc");//abc//简写2:Consumer<String> consumer2 = (s) -> System.out.println(s);consumer2.accept("bcd");//简写3:Consumer<String> consumer3=System.out::println;consumer3.accept("efg");}

为什么可以写成上述方式?
因为:System.out.println(s);与void accept(String s)一样,都是使用s作为参数,返回值是void,因此就可以简写为简写3。

2、类::静态方法

    public static void main(String[] args) {BinaryOperator<Double> operator=new BinaryOperator<Double>() {@Overridepublic Double apply(Double a, Double b) {return Math.max(a,b);}};System.out.println(operator.apply(1.0, 2.0));//2.0//简写1:BinaryOperator<Double> operator1=(o,o1)->Math.max(o,o1);System.out.println(operator1.apply(2.0, 3.0));//3.0//简写2:BinaryOperator<Double> operator2= Math::max;System.out.println(operator2.apply(3.0, 4.0));//3.0}

因为Math.max()所需要的参数以及返回值与重写的accet()一样,可以简写为类::静态方法;

    public static void main(String[] args) {Comparator<Integer> comparator = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return Integer.compare(o1,o2);}};System.out.println(comparator.compare(20, 12));//1Comparator<Integer> comparator1=(a,b)->Integer.compare(a,b);System.out.println(comparator1.compare(10,20));//-1Comparator<Integer> comparator2=Integer::compareTo;System.out.println(comparator2.compare(10,10));//0}

3、类::实例方法

    public static void main(String[] args) {Comparator<Integer> comparator = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return Integer.compare(o1,o2);}};System.out.println(comparator.compare(20, 12));//1Comparator<Integer> comparator1=(a,b)->Integer.compare(a,b);System.out.println(comparator1.compare(10,20));//-1Comparator<Integer> comparator2=Integer::compareTo;System.out.println(comparator2.compare(10,10));//0}

传递过来的两个参数,一个作为调用者,一个作为参数,这时候,使用类::实例方法简写;

五、构造引用

格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!

    public static void main(String[] args) {// 使用 Supplier 提供一个 Person 实例Supplier<Person> personSupplier = Person::new;// 延迟创建 Person 对象Person person = personSupplier.get();System.out.println("Person's name: " + person.getName());  // 输出 "John Doe"}

六、总结

Lambda表达式的优点很明显,在代码层次上来说,使代码变得非常的简洁。缺点也很明显,代码不易读
优点:

  1. 代码简洁,开发迅速
  2. 方便函数式编程
  3. 非常容易进行并行计算
  4. Java 引入 Lambda,改善了集合操作
    缺点:
  5. 代码可读性变差
  6. 在非并行计算中,很多计算未必有传统的 for 性能要高
  7. 不容易进行调试

相关文章:

  • 《Windows 10下QT+OpenCV+Yolo11:AI视觉开发实战指南》
  • 【AS32系列MCU调试教程】深度解析:使用 Eclipse 调试AS32系列MCU芯片的工程搭建
  • 虚拟机时间同步
  • 【MySQL系列】MySQL 导出表数据到文件
  • 消除垃圾技术文档的思维探索
  • leetcode 10. 正则表达式匹配
  • gitcode与github加速计划
  • 探究 Java SPI 原理与实战_打造高扩展性的应用架构
  • python打卡第48天
  • 板凳-------Mysql cookbook学习 (十--2)
  • 深入浅出 Arrays.sort(DualPivotQuicksort):如何结合快排、归并、堆排序和插入排序
  • MySQL中的部分问题(2)
  • java 乐观锁的实现和注意细节
  • Linux系统的CentOS7发行版安装MySQL80
  • 【笔记】结合 Conda任意创建和配置不同 Python 版本的双轨隔离的 Poetry 虚拟环境
  • 2025HNCTF - Crypto
  • 模块缝合-把A模块换成B模块(没写完)
  • 从零开始学Flink:揭开实时计算的神秘面纱
  • Spring Boot + Flink + FlinkCDC 实现 MySQL 同步到 MySQL
  • 浏览器兼容-polyfill-本地服务-优化
  • 新建网站seo优化怎么做/百度关键词查询网站
  • 亚马逊卖家做自己网站/sem是什么的英文缩写
  • 在线视频直播网站建设/百度推广怎么优化关键词的质量
  • wordpress码字主题/西安seo关键词排名
  • 手机网站设置在哪里找/南京seo域名
  • 上海网网站建设/如何推广app让别人注册