热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JAVA之Lambda表达式

JAVA之Lambda表达式,Go语言社区,Golang程序员人脉社


Lambda表达式入门

Lambda表达式支持将代码块作为方法参数,Lambda表达式允许使用更简洁的代码块来创建只有一个抽象方法的接口(函数式接口)的实例。

Lambda表达式的代码块可以代替那些函数式接口的匿名内部类创建对象,Lambda表达式的代码块将会代替实现抽象方法的方法体,Lambda表达式就相当于一个匿名方法。

也就是说,Lambda表达式的主要作用就是代替匿名内部类的繁琐语法。

Lambda表达式由三部分构成


  1. 形参列表。形参列表可以省略形参类型。如果形参列表只有一个参数,那么可以省略形参列表的圆括号
  2. 箭头(->)
  3. 代码块。如果代码块只包含一条语句,Lambda表达式允许省略代码块的花括号,如果只有一条return语句,那么可以省略return关键字(当Lambda表达式需要返回值,而代码块中仅有一条省略了return的语句,那么表达式会自动返回这条语句的值)
下面举个例子:

interface ProcessArray
{
abstract void calculate(int[]a);
public static void end()
{
System.out.println("运算结束");
}
}
public class Test1 {
public void process(int []array,ProcessArray pa)
{
pa.calculate(array);
ProcessArray.end();

}
public static void main(String []args)
{
int []ia=new int[]{2,3,4,5,6,7};
Test1 test=new Test1();
test.process(ia, (a)->{
int sum=0;
for(int i=0;i sum+=ia[i];
System.out.println(sum);
});
}
}
运行结果如下:


Lambda表达式实际上会被当成一个“任意类型的对象”,到底需要当成何种类型的对象,这取决于运行环境的需要。



Lambda表达式与函数式接口
Lambda表达式的目标类型必须是“函数式接口”,也就是说,该接口中可以有多个默认方法、类方法,但只能有一个抽象方法。



同一个Lambda表达式的目标类型完全可能是变化的,但是Lambda表达式实现的匿名方法和目标类型(函数式接口)中位于的抽象方法有相同的形参列表



Lambda表达式的目标类型必须是明确的函数式接口,为了保证这一点,一般以下三种方式使用Lambda表达式




  • 将Lambda表达式的目标类型是一个明确的函数式接口
  • 将Lambda表达式赋值给函数式接口类型的参数传给某个方法
  • 使用函数式接口对Lambda表达式进行强制类型转换

对于第三种用法,举个例子:

public class Test2 {
public static void main(String[]args)
{
Object b=(Runnable)()->{
for(int i=0;i<100;i++)
{
System.out.println(i);
}
};
Thread t=new Thread((Runnable)b);
t.start();
}
}


经实测运行无误



方法引用和构造器引用

如果Lambda表达式的代码块只有一条代码,那么就可以在代码块中使用方法引用和构造器引用(P216)



引用类方法


以下方法引用代替Lambda表达式引用类方法



函数式接口中被实现方法的全部参数传该类方法作为参数



interface Converter
{
Integer conver(String from);
}
public class Test3 {
public static void main(String []args)
{
Converter c1=from->Integer.valueOf(from) ;
Converter c2=Integer::valueOf;
int x=c1.conver("99");
System.out.println(x);
int y=c2.conver("222");
System.out.println(y);
}
}


运行结果如下:






引用特定对象的实例方法

我简单改了一下上面的代码:

interface Converter
{
Integer conver(String from);
}
class Hello
{
public Integer sayHello(String from)
{
System.out.println("Hello "+from);
return 0;
}
}
public class Test3 {
public static void main(String []args)
{
Hello h=new Hello();
Converter c3=h::sayHello;
c3.conver("Black");
System.out.println(c3.conver("aaa"));
}
}


运行结果如下:




引用某类对象的实例方法


interface MyTest
{
String test(String a,int x,int y);
}
public class Test3 {
public static void main(String []args)
{
MyTest mt1=(a,b,c)->a.substring(b,c);
String str=mt1.test("Hello world", 3, 6);
System.out.println(str);
MyTest mt2=String::substring;
System.out.println(mt2.test("abcde", 2, 4));
}
}
输出结果如下:



引用构造器


interface SayHello
{
Hello test(String x);
}
class Hello
{
public Hello(String s)
{
System.out.println("创建Hello对象成功"+s);
}
public Integer sayHello(String from)
{
System.out.println("Hello "+from);
return 0;
}
}
public class Test3 {
public static void main(String []args)
{

SayHello sh1=s->new Hello(s);
System.out.println(sh1.test("white"));
SayHello sh2=Hello::new;
System.out.println(sh2.test("Black"));
}
}
运行结果如下:



Lambda表达式与匿名内部类的联系和区别


Lambda表达式是匿名内部类的一种简化,因此他可以部分取代匿名内部类的作用,它们有以下相同点:


  • 都可以直接访问“effectively final”的局部变量,以及外部类的成员变量(包括实例变量和类变量)
  • 创建的对象都可以直接调用从接口中继承的默认方法
和匿名内部类类似,当Lambda表达式访问局部变量,那么该局部变量等于有一隐式的final修饰,因此不可以对该局部变量重新赋值



匿名内部类实现的抽象方法的方法体允许条用接口中定义的默认方法,但Lambda表达式不可以。





PS:这应该是JAVA入门系列的最后一篇,下面我会开始数据结构系列和JAVA进阶系列




推荐阅读
  • Hadoop中的MapReduce框架原理、自定义Partitioner步骤、在Job驱动中,设置自定义Partitioner、Partition 分区案例
    文章目录13.MapReduce框架原理13.3Shuffle机制13.3.2Partition分区13.3.2.3自定义Partitioner步骤13.3.2.3.1自定义类继承 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • 题目描述:一个DNA序列由ACGT四个字母的排列组合组成。G和C的比例(定义为GC-Ratio)是序列中G和C两个字母的总的出现次数除以总的字母数目(也就是序列长度)。在基因工程中,这个 ... [详细]
  • 两个N位数a和b相乘,手算的话一般是a的末位分别乘以b的末位到首位,然后a的倒数第二位分别乘以b的末位到首位,直到a的首位分别乘以b的末位到首位,最后按位数相加。这个过程的时间复杂度是O(n2)的。 ... [详细]
  • 显示中文星期几
    显示中文星期几引自:第一种方法:直接翻译,最笨、最容易想到的方法。Code获得中文星期名称 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了在Java中gt、gtgt、gtgtgt和lt之间的区别。通过解释符号的含义和使用例子,帮助读者理解这些符号在二进制表示和移位操作中的作用。同时,文章还提到了负数的补码表示和移位操作的限制。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
author-avatar
王聪明2011
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有