Lambda表达式

来源:互联网 发布:省市区县乡镇数据库 编辑:程序博客网 时间:2024/06/05 02:20

Lambda表达式是什么?

一个不用被绑定到一个标识符上,并且可能被调用的函数。这个解释还不够通俗,lambda表达式可以这样定义(不精确,自己的理解):一段带有输入参数的可执行语句块。这样就比较好理解了吧。

1.Demo

比如对一个List排序,Java8之前则通常需要以下代码来完成。

    List<String> names = ...;    Collections.sort(names, new Comparator<String>() {      @Override      public int compare(String o1, String o2) {        return o1.compareTo(o2);      }    });

但是有了Lambda表达式之后一句话完成

    Collections.sort(names,(s1,s2)->s1.compareTo(s2));

第二个例子:每个字符串都转换成全小写的字符串

List<String> names = new ArrayList<>();names.add("1");names.add("2");List<String> lowercaseNames = new ArrayList<>();for (String name : names) {  lowercaseNames.add(name.toLowerCase());}

利用Stream和Lambda表达式配合

names.stream().map((String name)->{return name.toLowerCase();}).collect(Collectors.toList());

map方法调用,这里map方法就是接受了一个lambda表达。其实是一个java.util.function.Function的实例。

好了,例子举了带着疑问我们了解以下Lambda的详细语法。

2.Lambda语法详解

lambda表达式的一般语法:

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {  statment1;  statment2;  //.............  return statmentM;}

这是比较复杂的定义,一般使用的时精简的版本。

2.1.参数类型省略

绝大多数情况,编译器都可以从上下文环境中推断出lambda表达式的参数类型。这样lambda表达式就变成了:

(param1,param2, ..., paramN) -> {  statment1;  statment2;  //.............  return statmentM;}

于是我们上面的例子就变成了

names.stream().map((name) -> {return name.toLowerCase();}).collect(Collectors.toList());

2.2.省略括号

当lambda表达式的参数个数只有一个,可以省略小括号

param1 -> {  statment1;  statment2;  //.............  return statmentM;}

于是又变成了:

names.stream().map(name -> {return name.toLowerCase();}).collect(Collectors.toList());

当lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号。lambda表达式简化为:

param1 -> statment

最终可以简化为:

List<String> lowercaseNames = names.stream().map(name -> name.toLowerCase()).collect(Collectors.toList());

2.3.使用方法引用

List<String> lowercaseNames = names.stream().map(String::toLowerCase).collect(Collectors.toList());

3.Lambda表达式中的变量

    int i=2;    List<Integer> arrs=Arrays.asList(1,2,3,4);    arrs.stream()    .filter(num ->num!=null)    .mapToInt(num ->num*i).forEach(System.out::println);

上面这段代码中Lambda表达式使用了外部变量i,访问外部变量是Lambda表达式的一个重要特性。

Lambda的组成部分

  • 输入参数
  • 可执行语句
  • 存放外部变量的空间

细节

  • lambda表达式访问外部变量有一个非常重要的限制:变量不可变(只是引用不可变,而不是真正的不可变)。
  • 在lambda中,this不是指向lambda表达式产生的那个SAM对象,而是声明它的外部对象。

4.方法引用和构造器引用

方法引用在某些情况下,可以更加简化Lambda表达式,格式为:

  • objectName::instanceMethod
  • ClassName::staticMethod
  • ClassName::instanceMethod

解释一下:
比如x->System.out.prinln(x)等同于System.out::println
或者(x,y)->Math.max(x,y)等同于Math::max,可以看出来就是把Lambda表达式中的参数直接当成方法的参数来调用。

最后一种方式,等同于把lambda表达式的第一个参数当成instanceMethod的目标对象,其他剩余参数当成该方法的参数。比如String::toLowerCase等同于x->x.toLowerCase()。

构造器应用

构造器引用语法如下:ClassName::new,把lambda表达式的参数当成ClassName构造器的参数 。例如BigDecimal::new等同于x->new BigDecimal(x)。

原创粉丝点击