Lambda初体验

作为一只小测试,在每次测试之前总会或多或少的把开发的代码拉下来本地review,在看代码过程中发现很多“小箭头”表达式,代码不再像之前一样“臃肿”,显得简洁了很多。

了解了以后知道,这些“小箭头”运用到了lambda表达式,那么什么是lambda表达式呢?为什么它能这么简洁?它与匿名内部类之间的区别是啥呢?

什么是lambda表达式?

通过百度百科可以看到,Lambda 表达式(lambda expression)是一个匿名函数,即没有函数名的函数,它把函数作为基本运算单元,函数可以作为变量,可以接收函数,还可以返回函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),他们必须依附于一类特别的对象类型——函数式接口(functional interface)。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

其实在Scala等jvm语言中lambda早就被广泛运用了,像我们平常经常使用的Python、Java 8、C#、C++ 11都已经引入lambda表达式,使用它设计的代码会更加简洁易读。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。

lambda表达式语法结构:

Lambda表达式通常使用(param)->(body)语法书写,基本格式如下:

//没有参数

() -> body

// 1个参数

(param) -> body

// 1个参数

(param) ->{ body; }

// 多个参数

(param1, param2...) -> { body }

// 多个参数

(type1 param1, type2 param2...) -> { body }

举一个简单list遍历的🌰:

1.普通循环遍历表达式

public void function(){

    String [] stringArray={"hello","world"};

    for(int i=0;i<stringArray.length;i++){

        System.out.println(stringArray[i]);

    }

}

2.lambda表达式

public void function(){

        //List遍历

        List<String> books = new ArrayList<String>(3);

        books.add("TEST1");

        books.add("TEST2");

        books.add("TEST3");

        books.forEach(obj -> System.out.println("测试:" + obj));

        books.forEach(System.out::println);

        //map的遍历

        Map maps = new HashMap();

        maps.put(1, "test1");

        maps.put(2, "test2");

        maps.forEach((k, v) -> System.out.println("Key : " + k + " Value : " + v));

    }

}

观察到lambda表达式的格式是:

(obj) -> {

    return System.out.println("测试:" + obj);

}

如果只有一行retrun的代码,就可以是这样:

obj -> System.out.println("测试:" + obj)

其中,参数是(a,b),参数类型可以省略,因为编译器可以自动推断出object类型,这得益于javac的类型推断机制,编译器能够根据上下文信息推断出参数的类型,当然也有推断失败的时候,这时就需要手动指明参数类型了。注意,Java是强类型语言,每个变量和对象都必需有明确的类型。-> { ... }表示方法体,所有代码写在内部即可。

为什么它能这么简洁?

Lambda表达式没有class定义,因此写法非常简洁。

它与匿名内部类之间的区别是啥呢?

在了解区别之前先知道一下什么是匿名内部类,这种类顾名思义,没有名字(当然只是程序员不用指定类名,但是编译器会自动为该类取名的),创建方法如下:

new 父类构造器(参数列表)|实现接口() 

    { 

     //匿名内部类的类体部分 

    }

那么两者之间有啥区别呢?从两个方面解释,1.编译方法 2.关键词this的使用

1.编译方法不同

匿名类编译后会生成两个class文件,分别是主类跟内部类产生。是会额外消耗class文件的

而lambda表达式编译结果只有一个class,不会产生class额外消耗。

还可以通过查看字节码的方式去看两者内部不同,lambda表达式通过java7中新加的invokedynamic 指令动态绑定私有函数方法从而做到了不会产生新的类。

2.关键字this的使用

因为lambda表达式跟内部类如此不同所以this的使用也不是代表内部对象了,而是跟外部一样。这也是两者之间的区别。

总结:

lambda表达式的结构是:

  • Lambda表达式可以有0个参数或者多个参数。

  • 参数类型可以显式声明,也可以让javac编译器从上下文自动推断类型。

  • 多个参数用小括号括起来,逗号分隔。(a,b)-> a+b

  • 没有参数用空括号表示。()->1

  • Lambda表达式的正文可以包含0条,一条或多条语句,如果有返回值则必须包含返回值语句。如果只有一条可省略大括号。

虽然lambda表达式很简洁效率也高,但是缺点也是很明显哒,非并行计算情况下,其计算速度没有比传统的 for 循环快;不容易进行调试等等。有他的好也会有弊端,切记勿滥用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值