Java SE 8新特性导览:使用Lambda Expression进行函数式编程

Java SE 8新功能浏览 ”系列的这篇文章将深入了解Lambda表达式 。 我将向您展示Lambda表达式的几种不同用法。 它们都具有功能接口的共同实现。 我将解释编译器如何从代码中推断信息,例如特定类型的变量以及后台实际发生的情况。

在上一篇文章“ Java SE 8新功能之旅:Java开发世界中的重大变化 ”中,我谈到了在本系列文章中我们将要探索的内容。 首先介绍Java SE 8的 主要功能 ,然后介绍在Microsoft Windows和Apple Mac OS X平台上JDK8的安装过程 ,并提供重要的建议和注意事项。

最后,我们经历了一个由Lambda表达式支持的控制台应用程序的开发,以确保我们可能已经安装了Java SE 8。

源代码托管在我的Github帐户上:从此处克隆。

Lambda表达是什么?

Java SE 8最著名的新功能也许叫做Project Lambda,它是将Java引入函数式编程领域的一项努力。

用计算机科学术语;


Lambda是一个匿名函数。 即,没有名称的功能。

在Java中;


所有函数都是类的成员,被称为方法。 要创建方法,您需要定义其所属的类。

Java SE 8中的lambda表达式使您可以使用非常简洁的语法定义一个类和单个方法,以实现具有单个抽象方法的接口。

让我们弄清楚这个想法。

Lambda Expressions使开发人员可以简化和缩短其代码。 使它更具可读性和可维护性。 这将导致删除更多详细的类声明

让我们看一些代码片段。

  1. 实现接口:在Java SE 8之前,如果要创建线程,首先要定义一个实现可运行接口的类。 这是一个具有名为Run的抽象方法的接口,该抽象方法不接受任何参数。 您可以在自己的代码文件中定义类。 由MyRunnable.java命名的文件。 就像我在这里所做的那样,您可以将类命名为MyRunnable。 然后,您将实现单个抽象方法。
    public class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("I am running");}public static void main(String[] args) {MyRunnable r1 = new MyRunnable();new Thread(r1).start();}
    }

    在此示例中,我的实现将文字字符串输出到控制台。 然后,您将获取该对象,并将其传递给线程类的实例。 我将可运行对象实例化为名为r1的对象。 将其传递给线程的构造函数并调用线程的start方法。 我的代码现在将在自己的线程和内存空间中运行。

  2. 实现内部类:您可以对此代码进行一些改进,而不是将类声明为单独的文件,而可以将其声明为使用类本地的一次性使用类,即内部类
    public static void main(String[] args) {Runnable r1 = new Runnable() {@Overridepublic void run() {System.out.println("I am running");}};new Thread(r1).start();}

    所以现在,我再次创建一个名为r1的对象,但直接调用该接口的构造方法。 再一次,实现它是单个抽象方法。 然后,我将对象传递给线程的构造函数。

  3. 实现一个匿名类:您可以通过将类声明为匿名类来命名,因为它从未命名,因此可以使其更加简洁。 我正在实例化可运行的接口,并将其立即传递给线程构造函数。 我仍在实现run方法,并且仍在调用线程的start方法。
    public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {System.out.println("I am running");}}).start();}
  4. 使用lambda表达式:Java SE 8中,您可以重构此代码以显着减少它并使它更具可读性。 lambda版本可能看起来像这样。
    public static void main(String[] args) {Runnable r1 = () -> System.out.println("I am running");new Thread(r1).start();}

    我正在声明具有可运行类型的对象,但现在我使用一行代码来声明单个抽象方法实现,然后再次将对象传递给线程的构造函数。 您仍在实现可运行的接口并调用它的run方法,但使用的代码却少得多。 此外,它可以进行以下改进:

    public static void main(String[] args) {   new Thread(() -> System.out.println("I am running")).start();
    }

    这是有关Lambda项目的早期规格文档中的重要报价。

    Lambda表达式只能出现在将它们分配给类型为功能接口的变量的位置。
    引用布莱恩·格茨

    让我们分解一下以了解发生了什么。

有哪些功能接口?

功能接口是仅具有一个自定义抽象方法的接口。 即,不是从对象类继承的对象。 Java有许多这样的接口,例如Runnable,Comparable,Callable,TimerTask等。

在Java 8之前,它们被称为Single Abstract MethodSAM接口 。 在Java 8中,我们现在将它们称为功能接口

Lambda表达式语法:

JDK8-SES-P2-1

这个lambda表达式返回了runnable接口的实现。 它有两部分,由称为箭头标记Lambda运算符的新语法分开。 lambda表达式的第一部分,在箭头标记之前,是您要实现的方法的签名。

在此示例中,这是一个无参数方法,因此仅用括号表示。 但是,如果我要实现一个接受参数的方法,则只需给出参数名称。 我不必声明它们的类型。

因为接口只有一个抽象方法,所以数据类型是已知的。 lambda表达式的目标之一就是消除不必要的语法。 表达式的第二部分,在箭头标记之后,是单个方法主体的实现。

如果仅是一行代码(如本例所示),则您不需要任何其他内容。 要使用多个语句实现方法主体, 请将它们括在花括号中

Runnable r = ( ) -> {System.out.println("Hello!");System.out.println("Lambda!");};

Lambda目标:

Lambda表达式可以减少您需要编写的代码量以及必须创建和维护的自定义类的数量。

如果您要实现一次使用的接口,那么创建另一个代码文件或另一个命名类并不总是很有意义。 Lambda表达式可以定义一次匿名实现,以供一次性使用,并显着简化代码。

定义和实例化功能接口

为了开始学习Lambda表达式,我将创建一个全新的功能接口。 一个具有单个抽象方法的接口,然后我将使用Lambda表达式实现该接口。

您可以使用托管在github上的源代码项目“ JavaSE8-Features”来导航项目代码。

JDK8-SES-P2-2

  1. 没有任何参数的方法,Lambda实现

    在我的源代码中,我实际上将接口放入其自己的以lambda.interfaces结尾的子包中。 我将其命名为HelloInterface接口。为了实现带有lambda表达式的接口,它必须具有一个抽象方法。 我将声明一个返回void的公共方法,并将其命名为doGreeting 。 它不会接受任何参数,这是使接口可用于Lambda表达式所需要做的全部工作。 如果需要,可以使用新的注释,该注释已添加到Java SE 8中,称为功能接口

    /**** @author mohamed_taman*/
    @FunctionalInterface
    public interface HelloInterface {void doGreeting();}

    现在,我准备在lambda.impl包下创建一个新类UseHelloInterface该类将实例化我的功能接口( HelloInterface ),如下所示:

    /*** @author mohamed_taman*/public class UseHelloInterface {public static void main(String[] args) {HelloInterface hello = ()-> out.println("Hello from Lambda expression");hello.doGreeting();}
    }

    运行文件并检查结果,它应该运行并输出以下内容。

    ------------------------------------------------------------------------------------
    --- exec-maven-plugin:1.2.1:exec (default-cli) @ Java8Features ---
    Hello from Lambda expression
    ------------------------------------------------------------------------------------

    因此,当您使用不接受任何参数的单个抽象方法时,代码就是这样。 让我们看一下带有参数的外观。

  2. 具有任何参数的方法,Lambda实现

    lambda.interfaces下 。 我将创建一个新接口,并将其命名为CalculatorInterface 。 然后,我将声明一个返回void的公共方法,并将其命名为doCalculate ,它将接收两个整数参数value1value2

    /*** @author mohamed_taman*/@FunctionalInterface
    public interface CalculatorInterface {public void doCalculate(int value1, int value2);}

    现在,我准备在lambda.impl包下创建一个新类Use CalculatorInterface ,它将实例化我的功能接口( CalculatorInterface ),如下所示:

    public static void main(String[] args) {CalculatorInterface calc = (v1, v2) -> {int result = v1 * v2;out.println("The calculation result is: "+ result);};calc.doCalculate(10, 5);}

    请注意doCalculate()参数,它们在接口中分别命名为value1和value2,但是您可以在此处为它们命名。 我将其命名为v1和v2。 我不需要在参数名称前插入int; 该信息是已知的,因为编译器可以从功能接口方法签名中推断出此信息。运行文件并检查结果,它应该运行并输出以下内容。

    ------------------------------------------------------------------------------------
    --- exec-maven-plugin:1.2.1:exec (default-cli) @ Java8Features ---
    The calculation result is: 50
    ------------------------------------------------------------------------------------
    BUILD SUCCESS

    始终牢记以下规则:

    同样,您必须遵循该规则,即接口只能具有一个抽象方法 然后,可以使用lambda表达式实现该接口及其单一抽象方法。

  3. 将内置功能接口与lambda结合使用

    前面已经介绍了如何使用lambda表达式实现您自己创建的接口。现在,我将展示具有内置接口的lambda表达式。 属于Java运行时的接口。 我将使用两个示例。 我正在一个名为lambda.builtin的程序包中工作,这是练习文件的一部分。 我将从这堂课开始。 UseThreading 。 在此类中,我实现了Runnable接口。 这个接口是Java多线程体系结构的一部分,我的重点是代码的编写方式,而不是操作方式。 我将展示如何使用lambda表达式替换这些内部类。 我将注释掉声明两个对象的代码。 然后,我将重新声明它们并使用lambdas进行实现。 因此,让我们开始吧。

    public static void main(String[] args) {//Old version// Runnable thrd1 = new Runnable(){//  @Override
    //  public void run() {
    //    out.println("Hello Thread 1.");
    //  } 
    //};/******************************************* Using lambda expression inner classes *******************************************/Runnable thrd1 = () -> out.println("Hello Thread 1.");new Thread(thrd1).start();// Old Version/*new Thread(new Runnable() {@Overridepublic void run() {out.println("Hello Thread 2.");}}).start();*//******************************************** Using lambda expression anonymous class ********************************************/new Thread(() -> out.println("Hello Thread 2.")).start();}

    让我们看另一个例子。 我将使用比较器比较器是Java中的另一个功能接口,具有单个抽象方法。 此方法是比较方法。打开文件UseComparator类,并检查代码的注释位,这是实际代码,然后将其重构为lambda表达式。

    public static void main(String[] args) {List<string> values = new ArrayList();values.add("AAA");values.add("bbb");values.add("CCC");values.add("ddd");values.add("EEE");//Case sensitive sort operationsort(values);out.println("Simple sort:");print(values);// Case insensetive sort operation with anonymous class/*      Collections.sort(values, new Comparator<string>() {@Overridepublic int compare(String o1, String o2) {return o1.compareToIgnoreCase(o2);}});
    */// Case insensetive sort operation with Lambdasort(values,(o1, o2) -> o1.compareToIgnoreCase(o2));out.println("Sort with Comparator");print(values);}

    和以前一样,它不会为您提供任何性能优势 。 基本功能完全相同。 无论您声明自己的类 ,使用内部匿名内部类还是lambda表达式 ,完全取决于您。

在本系列的下一篇文章中,我们将探讨和代码如何使用lambda表达式, 过滤谓词接口的集合遍历方法引用 的集合 ,在接口实现的默认方法,并最终实现在接口的静态方法 遍历集合

资源:

  1. Java教程,Lambda表达式
  2. JSR 310:日期和时间API
  3. JSR 337:Java SE 8发行内容
  4. OpenJDK网站
  5. Java平台,标准版8,API规范

翻译自: https://www.javacodegeeks.com/2014/07/java-se-8-new-features-tour-functional-programming-with-lambda-expression.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/363534.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS 数据转换

转换成字符串类型 toString() var num 5;console.log(num.toString()); String() String()函数存在的意义&#xff1a;有些值没有toString()&#xff0c;这个时候可以使用String()。比如&#xff1a;undefined和null 拼接字符串方式 num ""&#xff0c;当 两边一…

凭借K2 SmartObject框架,在SharePoint中集成数据

随着SharePoint 2013的发布&#xff0c;Microsoft已提供Business Connectivity Services&#xff08;BCS&#xff09;增强功能以及外部列表功能&#xff0c;确保您可以更简单地在SharePoint环境下从外部数据源提取数据。针对诸如服务台票务应用或销售仪表盘等实施解决方案&…

浙大计算机专硕培养方案,浙江大学硕士研究生培养方案

《浙江大学硕士研究生培养方案》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《浙江大学硕士研究生培养方案(3页珍藏版)》请在人人文库网上搜索。1、浙江大学硕士研究生培养方案医 学院 肿瘤学 专业(代码&#xff1a; 100214 )(一级学科&#xff1a; 临床医学 )一、培…

停止尝试使用内部DB框架模拟SQL OFFSET分页!

我敢肯定&#xff0c;到目前为止&#xff0c;您已经以多种方式弄错了。 而且您可能很快将无法正确处理。 那么&#xff0c;当您可以实施业务逻辑时&#xff0c;为什么还要在SQL调整上浪费您的宝贵时间呢&#xff1f; 让我解释… 直到最近的SQL&#xff1a;2008标准 &#xff0…

leetcode 20. Valid Parentheses 、32. Longest Valid Parentheses 、301. Remove Invalid Parentheses

20. Valid Parentheses 错误解法&#xff1a; "[])"就会报错&#xff0c;没考虑到出现)、]、}时&#xff0c;stack为空的情况&#xff0c;这种情况也无法匹配 class Solution { public:bool isValid(string s) {if(s.empty())return false;stack<char> st;st.…

和朱晔一起复习Java并发(五):并发容器和同步器

和朱晔一起复习Java并发&#xff08;五&#xff09;&#xff1a;并发容器和同步器 本节我们先会来复习一下java.util.concurrent下面的一些并发容器&#xff0c;然后再会来简单看一下各种同步器。 ConcurrentHashMap和ConcurrentSkipListMap的性能 首先&#xff0c;我们来测试一…

树莓派3显示服务器SSH拒绝了密码,脚本封杀尝试树莓派SSH密码的来源IP

树莓派整天开着&#xff0c;如果用缺省SSH端口对外开放&#xff0c;就会经常遇到扫描SSH密码的肉鸡。虽然密码不是很简单&#xff0c;但还是感觉很不安全的。系统的ssh登录日志文件在&#xff1a;/var/log/auth.log&#xff0c;登录失败时会记录以下格式的日志&#xff1a;Mar …

6-1 数组函数练习

1、引用 /* var num 10;function show(num){num ;alert(num);}alert(num); //10show(num); //11 num numalert(num); //10*//*引用*//*var arr [1, 2, 3, 4];function show(arr){arr.push("hello");alert(arr);}alert(arr); //[1, 2, 3, 4]show(arr)…

整理任务

昨晚帮师姐整理测试&#xff0c;没有时间写日志&#xff0c;今天一大早补上。 十一长假之后的第一个工作日&#xff0c;老师回来了。详细汇报了整个假期的学习之后&#xff0c;老师整理了以后我的学习任务。本来觉得没多少事情&#xff0c;可是细数了一下&#xff0c;竟然光论文…

Hive:使用Apache Hive查询客户最喜欢的搜索查询和产品视图计数

这篇文章涵盖了使用Apache Hive查询存储在Hadoop下的搜索点击数据。 我们将以示例的方式生成有关总产品浏览量的客户排名靠前的搜索查询和统计信息。 继续之前的文章 使用大数据分析客户产品搜索点击次数 &#xff0c; Flume&#xff1a;使用Apache Flume收集客户产品搜索点…

expdp错误案例

转自:https://www.cnblogs.com/kerrycode/p/3960328.html Oracle数据泵(Data Dump)使用过程当中经常会遇到一些奇奇怪怪的错误案例&#xff0c;下面总结一些自己使用数据泵(Data Dump)过程当中遇到的问题以及解决方法。都是在使用过程中遇到的问题&#xff0c;以后陆续遇到数据…

HashSet源码分析:JDK源码系列

1.简介 继续分析源码&#xff0c;上一篇文章把HashMap的分析完毕。本文开始分析HashSet简单的介绍一下。 HashSet是一个无重复元素集合&#xff0c;内部使用HashMap实现&#xff0c;所以HashMap的特征耶继承了下来。存储的元素是无序的并且HashSet允许使用空的元素。 HashSet是…

修改左侧导航显示样式(转载自Sunmoonfire's artistic matrix)

这是一片非常好的文章&#xff0c;修改下CSS就可以改变左侧导航栏的样式&#xff0c;在网上找了一些都是要写代码的。怕连接失效&#xff0c;所以直接将文章考了过来&#xff0c;希望作者原谅&#xff0c;如有不妥&#xff0c;请通知一声&#xff0c;我会将文章删掉&#xff01…

tf.argmax()以及axis

tf.argmax()表示返回最大值的索引号&#xff0c;axis为0 &#xff0c;表示返回每列最大值索引号。axis为1 &#xff0c;表示返回每行最大值索引号 结果为 转载于:https://www.cnblogs.com/san333/p/10507402.html

jquery ajax 上传文件 demo,Jquery+AJAX上传文件,无刷新上传并重命名文件

index.htmlAjax上传图片Ajax上传图片function upload(){var form new FormData(document.getElementById("form"));$.ajax({url:"upload.php",type:"post",data:form,cache: false,processData: false,contentType: false,success:function(dat…

Meet Fabric8:基于Camel和ActiveMQ的开源集成平台

面料8 Fabric8是Red Hat的JBoss Fuse产品的Apache 2.0许可上游社区。 这是一个基于Apache ActiveMQ &#xff0c; Camel &#xff0c; CXF &#xff0c; Karaf &#xff0c; HawtIO等的集成平台。 它提供了自动化的配置和部署管理&#xff0c;以帮助使部署变得容易&#xff0…

Django之web框架的本质

web框架的本质及自定义web框架 我们可以这样理解&#xff1a;所有的Web应用本质上就是一个socket服务端&#xff0c;而用户的浏览器就是一个socket客户端&#xff0c;基于请求做出响应&#xff0c;客户都先请求&#xff0c;服务端做出对应的响应&#xff0c;按照http协议的请求…

5:CSS元素类型

* { margin: 0; padding: 0 } body { padding: 30px; padding-top: 10px; line-height: 35px; font-family: "微软雅黑" } h1,h2 { padding: 20px 0 } h3 { background: #00AA88; color: #FFFCF4; font-size: 20px; font-weight: 700; margin: 10px 0; padding: 5px …

c#中的interface abstract 与 virtual(转)

interface用来声明接口 1.只提供一些方法规约&#xff0c;不提供方法主体. 如:public interface IPerson { void getName();//不包含方法主体 } 2.方法不能用public abstract等修饰,无字段变量&#xff0c;无构造函数。 3.方法可包含参数。 如 public interface IPers…

Springboot 系列(十三)使用邮件服务

在我们这个时代&#xff0c;邮件服务不管是对于工作上的交流&#xff0c;还是平时的各种邮件通知&#xff0c;都是一个十分重要的存在。Java 从很早时候就可以通过 Java mail 支持邮件服务。Spring 更是对 Java mail 进行了进一步的封装&#xff0c;抽象出了 JavaMailSender. 后…