欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > java_Lambda表达式

java_Lambda表达式

2025/5/4 18:47:18 来源:https://blog.csdn.net/CxK6666667/article/details/147684245  浏览:    关键词:java_Lambda表达式

1、背景

lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。lambda表达式就和方法一样样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式和一个代码块)。Lambda表达式,基于数学中的λ演算得名,也可成为闭包。

1.1 Lambda表达式的语法

基本语法:(parameters)-> expression 或 (parameters)->{statements;}

Lambda表达式由三部分组成:

1. paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。

2. ->:可理解为被用于的意思

3. 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不返回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。

1.2函数式接口

要了解lambda表达式,首先要了解函数式接口,函数式接口的定义:一个接口有且只有一个方法。

注意: 

1、如果一个接口有且只有一个抽象方法,那么该接口是函数式接口。

2、保障该接口是函数式接口:如果我们在一个接口上声明了@FunctionalInterface注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果该接口中有两个抽象方法,程序编译就会报错的。

如图所示,为一个函数式接口:

如果多一个方法,此时注解就会报错。 

我们之前在抽象类和接口-CSDN博客中讲到:在jdk1.8之后,接口中的default方法可以有具体实现,如果添加进去,该接口任然为函数式接口。

2、lambda表达式的基本使用

在我们之前的文章 Map&Set 4 面试题汇总 _map的面试题-CSDN博客中,有这么一道题:692. 前K个高频单词 - 力扣(LeetCode),它需要建一个小根堆,之前我们使用匿名内部类完成,下面,我们通过lambda表达式进行完成。

匿名内部类代码如下:

public class Test {public static void main(String[] args) {PriorityQueue<Map.Entry<String,Integer>> priorityQueue = new PriorityQueue<>(new Comparator<Map.Entry<String, Integer>>() {@Overridepublic int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {return o1.getValue()-o2.getValue();}});}
}

lambda表达式代码:

public class Test {public static void main(String[] args) {PriorityQueue<Map.Entry<String,Integer>> priorityQueue = new PriorityQueue<>((Map.Entry<String,Integer> o1,Map.Entry<String,Integer> o2) ->{return o1.getValue() - o2.getValue();});}
}

到了这里相信大家已经对lambda表达式有了初步认识,下面我们通过完成一些lambda表达式的练习,对lambda表达式的使用进行巩固。

首先先准备好如下函数式接口,然后尝试在main方法中使用lambda表达式完成这些接口

//无返回值无参数
@FunctionalInterface
//函数式接口
//只能有一个方法
interface NoParameterNoReturn {void test();
}
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {void test(int a);
}
//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {void test(int a,int b);
}
//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {int test();
}
//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {int test(int a);
}
//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {int test(int a,int b);
}

实现:

  public static void main(String[] args) {NoParameterNoReturn noParameterNoReturn = () -> System.out.println("hello,world");OneParameterNoReturn oneParameterNoReturn = (a) -> System.out.println(a);MoreParameterNoReturn moreParameterNoReturn = (a, b) -> System.out.println(a+b);NoParameterReturn noParameterReturn = ()-> {return 0;};OneParameterReturn oneParameterReturn = (a) -> {return a;};MoreParameterReturn moreParameterReturn = (a, b) -> {return a+b;};}

测试:

2.1 语法精简

1、参数类型可以省略,如果需要省略,每个参数的类型都有省略。

2、参数的小括号里面只有一个参数,那么小括号可以省略。

3、如果方法体当中只有一句代码,则大括号可以省略

4、如果方法体中只有一条语句,而且是return语句,那么大括号可以省略,且去掉return关键字。

 示例代码:

 public static void main(String[] args) {//  1.参数类型可以省略,如果需要省略,每个参数的类型都有省略。MoreParameterNoReturn moreParameterNoReturn = (a,b) -> System.out.println(a+b);//  2.参数的小括号里面只有一个参数,那么小括号可以省略。OneParameterNoReturn oneParameterNoReturn = a -> {System.out.println(a);};// 3.如果方法体当中只有一句代码,则大括号可以省略NoParameterNoReturn noParameternoReturn = ()-> System.out.println("hello world");// 4.如果方法体中只有一条语句,而且是return语句,那么大括号可以省略,且去掉return关键字NoParameterReturn noParameterReturn = () -> 0;}

3、变量捕获

Lambda表达式中存在变量捕获,了解了变量捕获之后,才能更好的理解Lambda表达式的作用域。

3.1 匿名内部类的变量捕获

下面通过代码来展示匿名内部类中的变量捕获:

首先,有这么一个接口:

interface NoParameterNoReturn {void test();
}

实现的匿名内部类如下:

public static void main(String[] args) {int a = 10;new NoParameterNoReturn(){@Overridepublic void test() {System.out.println(a);}}.test();}

此时,点击运行,代码是能够正常执行的:

那如果我们在内部类中修改当前a的值为99,它还能够正常运行吗?

 可以看到,程序报错。这就是匿名内部类的变量捕获,也就是说:传入匿名内部类中的量,必须是常量或者没有改变过值的量。

3.2 lambda表达式的变量捕获

lambda表达式也存在变量捕获机制,和上面的匿名内部类同理:

4、Lambda表达式在集合中的使用

为了能够让 Lambda Java 的集合类集更好的一起使用,集合当中,也新增了部分接口,以便与Lambda表达式对接。

以上方法的作用可自行查看java帮助手册,这里进行一些方法的使用示例。

注意:Collection的forEach方法是从接口java.lang.Iterable拿过来的。

4.1 List接口

foreach方法和Sort方法

public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("hello");list.add("abc");list.add("adc");System.out.print("排序前的结果: ");list.forEach((s -> System.out.print(s + " ")));System.out.println();System.out.print("排序后的结果: ");list.sort((o1,o2)->o1.compareTo(o2));list.forEach(s -> System.out.print(s + " "));}

 4.2 Map接口

foreach方法

    public static void main(String[] args) {Map<String,Integer> map = new HashMap<>();map.put("hello",4);map.put("abv",3);map.put("666",6);map.forEach((s, integer) -> System.out.println("key: "+s+" val: "+integer));}

5、总结

lambda表达式:

优点 :

1、代码简洁,开发迅速

2、方便函数式编程

3、非常容易进行并行计算

缺点:

1、代码可读性变差

2、在非并行计算中,很多计算未必有传统的for性能高

3、不容易进行调试

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词