Java Lambda表达式学习总结


Lambda表达式

  Lambda表达式是Java 8引入的一个新机制,它是一个可传递的代码块,可以在以后执行一次或者多次。在以往的Java中,单独传递一段代码是不可能的(万物基于类),因此以往的做法是使用接口或者类的方法,通过实现接口方法或者实例化类对象来传递一段代码。而Java 8之后提出了Lambda表达式机制,使得一段代码的传递方式得到大大简化,比如,对比下面两段代码——
  1. 使用Comparator接口函数进行数组排序

/*
 * @Author:Jason.Lee
 * @Date:2019-8-6
 * @Brief:Learn about Java's lambda expression mechanism
 * */
import java.util.Arrays;
import java.util.Comparator;

class NoLambda{
    public static void main(String[] args){
        Integer[] integers = new Integer[]{1,2,3,4,5,6,7,8,9};
        System.out.print(Arrays.toString(integers));
        Arrays.sort(integers, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        System.out.println();
        System.out.print(Arrays.toString(integers));
    }
}

  2.使用Lambda表达式进行数组排序

/*
 * @Author:Jason.Lee
 * @Date:2019-8-6
 * @Brief:Learn about Java's lambda expression mechanism
 * */
import java.util.Arrays;

class UseLambda{
    public static void main(String args[]){
        Integer[] integers = new Integer[] {1,2,3,4,5,6,7,8,9};
        System.out.print(Arrays.toString(integers));
        Arrays.sort(integers,(x,y)->y-x);
        System.out.println();
        System.out.print(Arrays.toString(integers));
    }
}

在这里插入图片描述
  两者都能达到相同的排序效果,显而易见,Lambda的方式更加简洁。这就是Java Lambda机制所要达到的效果,在某些适用的场景下,提供更加简洁的代码块表达方法。

语法总结

  Lambda最基本的组成包括括号、箭头以及一个表达式。语法格式形如——

	(x)->{
		/* lambda expression*/
	};

  其中,括号中参数可以有零个或者多个,表达式可以为多行。Lambda表达式在不同情形下,使用方法会有所不同,下面总结集中常见的情形。

语法1: (Type x,Type y)->{expression with return};

  这是Lambda表达式最完整的形态,x和y表示调用该代码段可能要用到的参数以及对应的类型,表达式代表要对参数进行的处理,我们举个例子,对String类型进行长度排列——

import java.util.Arrays;

class UseLambda{
    public static void main(String args[]){
        String[] strings = new String[]{"ABC","DE","F"};
        System.out.println("original arrays:"+Arrays.toString(strings));
        Arrays.sort(strings);
        System.out.println("after arrays.sort:"+Arrays.toString(strings));
        Arrays.sort(strings,(String x,String y)->{return x.length()-y.length();});
        System.out.print("after arrays.sort by lambda expression:"+Arrays.toString(strings));
    }
}
		

在这里插入图片描述
  String类型扩展了Comparator接口中的comparaTo方法,可以按照字典序排列字符串,但是我们这里定义了自己的排序方法,可以使得字符串按照字符长度排列。

语法2: (x,y)->expression

  实际上,虚拟机比我们想象的要机智一些,很多时候,括号中的类型声明可以省去,因为在代码段调用的时候虚拟机会自动推断,如上文中的表达式完全可以写成——

 	Arrays.sort(strings,(x,y)->{return x.length()-y.length();});

  结果完全一致。实际上,如果表达式只有一行,且不带return关键字的话,大括号可以省去,比如,上一行代码可以进一步简化为:

	Arrays.sort(strings,(x,y)->x.length()-y.length());

语法3:x->expression

  如果参数只有一个,那么小括号也可以省去,比如下列情形——

import java.util.function.Consumer;

class UseLambda{
    public static void main(String args[]){
        Consumer<String> consumer = c->System.out.println("Hello,"+c);
        consumer.accept("Lambda expression!");
    }
}

在这里插入图片描述
  这种写法比较抽象,首先,c->System.out.println("Hello,"+c),JVM通过前面的泛型类型<String>判断c的类型是String,然后System.out.println("Hello,"+c)实现了函数接口accept,所以这段代码等同于:

		Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("Hello,"+s);
            }
        };
        consumer.accept("Lambda expression!");

  但是显而易见,Lambda更加灵活飘逸。

语法4:()->expression

  情形4比情形3更进一步,参数可以为零,但是此时要加上小括号,如果表达式没有return返回值且只有一行,同样可以不带大括号。举个例子——

class UseLambda{
    public static void main(String args[]){
        Runnable runnable = ()->System.out.println("thread run!");
        runnable.run();
    }
}

在这里插入图片描述
  这段代码等同于——

	Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("thread run!");
            }
        };
        runnable.run();

  重写run方法来开启线程,是我们常用的手段,但现在可以用Lambda表达式的方法来取代之前使用匿名类实现接口方法的方式(多行只需要加大括号就行了),显然Lambda的方式更简洁。

函数式接口

  对于自由一个抽象方法的接口,我们成之外函数式接口(functional interface),从前面的例子不难看出,Lambda表达式发挥作用的场合大多是函数式接口,实际上,在Java中,Lambda表达式可以转换为函数式接口。下表是一个常见函数式接口的列表——

序号函数式接口参数类型返回类型抽象方法描述
1Runnablevoidvoidrun作为无参数或返回值的动作运行
2SupplierTget提供一个T类型的值
3ConsumerTvoidaccept处理一个T类型的值
4Function<T,R>TRapply有一个T类型的函数
5PredicateTbooleantest布尔值函数

  当然也可以设计自己的函数式接口,但在编写的时候务必添加注解@FunctionalInterface

与C++ Lambda表达式的对比

  Java 8提供的Lambda表达式与C++ 11的Lambda表达式相比,无论是形式上还是功能上,都高度相似(关于C++ Lambda表达式的介绍,可参加另一篇博客)。可能是为了弥补Java在面向过程上的不足,Java的设计者建议将Lambda看作一个函数,而非对象,但两者在不同的语言特性中又表现出不同的性能,C++11所提供的Lambda表达式更多服务于STL库中各种容器以及算法上,而Java的Lambda表达式更多应用于函数式接口。但受限于语言特性,Java的Lambda表达式只能使用对象作为中间参数,而C++的Lambda相对而言就神通广大得多,它既能应用于普通函数、类、泛型、STL容器、仿函数,也能使用指针、引用、基本类型等,方方面面,几乎无所不能。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值