lambda表达式java_Lambda表达式Java教程

lambda表达式java

在本文中,我们提供了全面的Lambda Expressions Java教程。

1. Lambda Expressions Java教程–简介

Lambda表达式被认为是Java 8中引入的最好的功能之一。Lambda表达式被认为是Java进入函数式编程世界的第一步 。 可以将其视为无需类即可创建的函数。 它也可以像参数一样传递,并且可以在需要时和根据需要执行。 Java Lambda表达式是匿名函数的简洁表示,可以将其传递。 具有单个功能的匿名类使用额外的语法进行了笨拙的演示。 这些表述旨在消除这种混乱。

如前所述,Java Lambda表达式是无名函数 ,可以作为常量值进行传递。 这意味着它们可以出现在可能存在任何其他常数值的任何位置,但是通常作为参数写入某些其他函数。 考虑一个典型的例子,我们可以将比较函数传递给泛型排序函数,而不是麻烦地定义一个整个过程(并引起词法不连续和名称空间污染)来描述这种比较,我们只需传递一个lambda表达式描述了比较。 让我们看一下Lambda表达式的一些属性

  • 匿名:它仍然可以称为匿名,因为它没有明确的名称。
  • 简洁:正如前面提到的匿名类的情况,与匿名类相比,我们用Lambdas编写的代码要少得多。
  • 函数:Lambda更像是函数而不是方法。 这是因为方法属于类,而Lambda不属于。 但是就像方法一样,Lambda接受参数列表,具有主体并且还可以引发异常。
  • 可以传递:Lambda可以传递给其他函数,就像普通参数一样。

为了消除可能由于我们上面提到的观点而引起的任何误解,lambda不会添加引入之前的更多功能。 它只是改善了我们编写代码的方式,并减少了很多样板代码。 该样板代码甚至与我们用来通过基础操作系统的多核性质进行代码识别的系统级编程有关。 让我们看看这种简单的语法糖如何使我们的工作在并行性,代码简洁性和紧凑性方面变得更加轻松。

2.编写Lambda表达式

在本节中,我们将看到Java Lambda表达式如何减少执行一些简单操作所需编写的代码行。 例如,我们将比较代码行数以构成比较器功能。 为了建立比较,我们将在这里创建一个简单的POJO类,一个Student类,其中包含Student ID(作为Long和name作为String参数:

学生.java

 public class Student {   private Long id; private String name; // standard setters and getters  } 

比较我们在应用程序中定义的POJO对象是一种非常通用的编程实践。 如果要比较两个Student类对象,则可以使Comparator像这样:

匿名类的比较器

 Comparator<Student> byId = new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { return s1.getId().compareTo(s2.getId()); }  }; 

这是一个作为Anonymous类的简单Comparator实现,但我们发现使用Lambda进行处理时,相同的实现非常精确和干净。 让我们在这里看到使用Lambda表达式完成的相同任务:

pom.xml

 Comparator<Student> byId = (s1, s2) -> s1.getId().compareTo(s2.getId()); 

Lambda表达式上方也可以称为块Lambda表达式,因为它由>符号右侧的单个代码块组成。 它变得更加简洁小巧,这听起来很神奇,请参见以下代码片段:

简洁的Lambda实现

 Comparator<Student> byId = Comparator.comparing(Student::getId); 

这是建立比较器的好方法,而且也很简单。 对于上面我们进行的Block Lambda表达式,让我们对其进行分解以更好地理解:

Lambda表达式Java-Lambda表达式
Lambda表达
  • Lambda Expression以在此情况下传递给函数Comparator的参数列表开头
  • 箭头符号将Lambda Expression参数与Lambda主体分开
  • 主体清楚地将两个学生对象及其id进行比较,该表达式定义了Lambda返回值

要注意的是,已编译的代码(即匿名类版本和Lambda表达式版本的字节码)将完全相同,因为Lambda表达式只是使代码清晰的语法。 尽管使用Lambda表达式有时可能会使代码的可读性降低。

3. Lambda表达式与匿名类

我们使用Lambda表达式编写的代码也可以使用Anonymous类编写,其实现方式与Lambda Expressions完全相同。 区别在于Lambda代码的简洁性。

作为比较示例,让我们构造一个类和一个将Runnable作为输入的方法:

可运行类

 public class RunnableInstance { public static void doSomething(Runnable runnable){ runnable.run(); }  } 

当我们使用Anonymous类制作Runnable时,其外观如下所示:

可通过匿名类运行

 Runnable runnable = new Runnable() { @Override public void run() { System.out.print( "Anonymous class implementation." ); }  };  doSomething(runnable); 

让我们尝试将上面的代码转换为Lambda表达式,看看如何得到干净的东西:

可与Lambda一起运行

 Runnable runnable = () -> System.out.print( "Lambda Expression." );  doSomething(runnable); 

如果我们不想多次使用可运行的实现,我们甚至可以避免进行引用:

简洁的Lambda Runnable

 doSomething(() -> System.out.print( "Lambda Expression." )); 

4.使用Lambda表达式进行并行编程

每当我们谈论线程时,我们大多数人都会退后一步,考虑是否真的需要在我们的应用程序中实现线程以支持并行性,因为并行性本质上微不足道且难以管理。 当我们有一组项目时,我们实现了一个lambda,如:

并行编程

 collection.map { // my lambda } 

在这里,集合本身能够与提供的Lambda实现并行性,而不必自己执行线程。 这意味着,在多核环境中,Lambda可以在集合上进行流式传输时利用多个核。 就像我们考虑一个简单的例子一样:

Lambda与并行流

 List<String> names = students.stream() .map(s -> s.getName().toUpperCase()) .collect(Collectors.toList()); 

map函数可以在多核环境中并行运行,以一次处理多个对象,而无需我们做任何事情。 为此,仅需要执行此程序的操作系统必须是多核。 一旦满足此条件,我们可以确保可以在给定语句中并行化的任何操作都将自动完成。

5.集合和流

Collections框架是Java中最常用的Framework API之一。 集合允许我们将相似的对象收集到可以针对特定目的进行优化的数据结构中。 前面的所有示例都需要对象集合,因此,假设我们有一个Student类型的对象集合,就像我们之前定义的那样:

学生集合

 List students = getStudentObjectCollection(); 

我们从添加到Collection接口的新方法stream()开始。 由于所有集合都“扩展”集合,因此所有Java集合都继承了此方法:

学生流

 List students = getStudentObjectCollection();  Stream stream = students.stream(); // a stream of student objects 

尽管看起来很像,但Stream接口不是另一种常规的集合类型。 我们可以将Stream视为“数据流”抽象,它使我们能够转换或操纵其包含的数据。 与我们在Java中研究过的其他集合不同,Stream不允许我们直接访问其包含的元素。 尽管如果您想访问元素,我们总是可以将流转换为Java中的集合之一并实现我们的目的。

出于演示目的,我们将看到如果我们必须计算我们的students集合中有多少个奇数ID对象,我们的代码将是什么样子。 首先,让我们看看如何在不使用流的情况下完成此操作:

计数奇数

 long count = 0 ;  List students = getStudentObjectCollection();  for (Student s : students) { if (s.getId() % 2 == 1 ) { count++; }  } 

使用for循环,我们创建了一个计数器,每次在学生列表中遇到奇数ID时,该计数器都会递增。 我们已经为这种非常简单的任务写了数百遍这种类型的代码,它跨越多行。

我们也可以在一行中使用Stream编写完全相同的代码:

使用流

 List students = getStudentObjectCollection();  long count = students.stream().filter(student -> student.getId() % 2 == 1 ).count(); 

这看起来比以前的for循环方法干净整洁吗? 一切都始于调用stream()方法,该方法将给定的集合转换为Stream,所有其他调用都链接在一起,因为Stream接口中的大多数方法都是在考虑到Builder模式的情况下设计的 。 对于那些不习惯使用这种方法进行链接的用户,可能更容易这样可视化:

可视化流

 List students = getStudentObjectCollection();  Stream stream = students.stream();  stream = stream.filter(student -> student.getId() % 2 == 1 );  long count = stream.count(); 

让我们将注意力集中在我们使用的Stream的两种方法中, filter()count()

filter()方法采用要过滤集合的条件,该条件由一个lambda表达式表示,该表达式带有一个参数并返回一个布尔值:

Lambda条件

 student -> student.getId() % 2 == 1 

并非偶然,用于表示该表达式的功能接口filter()方法的参数filter()是谓词接口。 它只有一个抽象方法boolean test(T t)

功能介面

 @FunctionalInterface  public interface Predicate { boolean test(T t); // non-abstract methods here  } 

参数化类型T表示流中元素的类型,即Student对象。 过滤之后,剩下的就是调用count()方法。 没什么大不了的,它只是计算过滤发生后我们流中还剩下多少个对象(除了过滤之外,我们还可以有更多的东西)。 count()方法被视为“终端操作”,在调用该方法后,该流被称为“已消耗”且无法再使用。

6. Lambda表达式的缺点

尽管带有Lambda Expressions的代码看起来非常简洁,但是Lambdas也有一些缺点。 让我们在这里研究其中的一些:

  • 无法处理检查的异常 :任何引发检查的异常的代码都应包装在try-catch语句中。 但是,即使我们这样做,也不总是总是清楚抛出的异常发生了什么。
  • 性能问题 :由于JIT不能始终将forEach() + lambda优化到与普通循环相同的程度,因此Lambda可以在很小程度上影响性能。
  • 调试挑战 :显然,使用Lambdas时,代码并不总是那么简洁。 这使得堆栈跟踪代码中出现的异常和可读性变得有些困难。

尽管Lambda有一些缺点,但是当您编写简洁的代码时,它们仍然是不错的伴侣。

7.结论

Java Lambda表达式在所有LISP,Perl,Python以及最新版本的C ++,Objective C,C#和Java 8中都出现(具有不同的语法),但值得注意的是,即使它可以处理传递的函数(或一些借口)作为参数。 它们是具有特定语义的语法元素,并且这些语义对运行时的要求比C所设计的要高。

在本课中 ,我们可以阅读有关Lambda表达式的更多信息,它与功能接口有很深的联系,还演示了将并行流与Lambda表达式配合使用的性能比较,并加深了对Lambda表达式如何与功能接口一起使用以及可以在简单语句中使用的理解。利用多核操作系统提供的并行性,而无需了解幕后工作的API。

上次更新时间为2020年2月17日

翻译自: https://www.javacodegeeks.com/lambda-expressions-java-tutorial.html

lambda表达式java

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

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

相关文章

MySQL命令之mysqlhotcopy -- 热备份

文章目录命令介绍命令格式安装 mysqlhotcopy常用选项命令介绍 mysqlhotcopy 只是简单的缓存写入和文件复制的过程&#xff0c;其使用 LOCK TABLES、FLUSH TABLES 和 CP 来进行快速备份,占用资源和备份速度比 mysqldump 快很多很多。特别适合大的数据库&#xff0c;但需要注意的…

trackby_使用trackBy启动流程

trackby仍然沿用我的Corda Services趋势&#xff0c;我还有其他一些技巧可帮助您的CorDapp顺利工作。 这次&#xff0c;我们将重点关注使用trackBy从服务内部启动流以及如果您不小心可能会引发的离散问题。 这应该是一个相对简短的职位&#xff0c;因为我可以依靠以前的职位&a…

SQL查询语句的排序

order by column1 asc, column2 desc -- 按column1升序排序&#xff0c;若column1值相同&#xff0c;则按column1降序排序asc&#xff0c;ascend 的缩写&#xff0c;表示正序&#xff0c;即升序&#xff0c;从小到大&#xff0c;可以省略&#xff0c;默认的 desc&#xff0c;de…

SpringBoot创建项目入门案例

目录结构 一、创建SpringBoot项目 1.创建骨架名称 2.给项目命名 3.配置pom.xml文件 4.MySql的驱动包 5.自动生成的pom.xml文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xs…

apache spark_Apache Spark Job的剖析

apache sparkApache Spark是通用的大规模数据处理框架。 了解spark如何执行作业对于获取大部分作业非常重要。 关于Spark评估范式的简要介绍&#xff1a;Spark使用的是惰性评估范式&#xff0c;在该范式中&#xff0c;Spark应用程序在驱动程序调用“ Action”之前不会执行任何…

MySQL常用权限的解释

文章目录全局管理权限数据库/数据表/数据列权限特别的权限全局管理权限 FILE: 在MySQL服务器上读写文件。 PROCESS: 显示或杀死属于其它用户的服务线程。 RELOAD: 重载访问控制表&#xff0c;刷新日志等。 SHUTDOWN: 关闭MySQL服务。 数据库/数据表/数据列权限 ALTER: 修改已…

No identifier specified for entity没有为实体指定标识符

异常 ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘userController’: Injection of resour…

aws jenkins_Jenkins在AWS上(第1部分)

aws jenkins这是我对PEAT UK播客的逐字记录&#xff1a; 你好&#xff0c;再一次到另一个热点。 我叫Peter Pilgrim。 我曾经是DevOps专家&#xff0c;欢迎观看另一集。 这是11 Jenkins n AWS的第一部分&#xff0c;我是一名平台工程师&#xff0c;并且是Java Champion。 在…

SELECT ... FOR UPDATE_手动加行级排他锁_行级写锁_行级独占锁

文章目录介绍加锁情况分析明确指定主键&#xff0c;并且数据真实存在&#xff0c;锁定行明确指定主键&#xff0c;但数据不存在&#xff0c;不加锁主键不明确&#xff0c;锁定整个表无主键&#xff0c;锁定整个表应用场景介绍 1.FOR UPDATE 加的锁是一种行级排他锁&#xff0c…

广义表

广义表(广义表也称为列表&#xff0c;是线性表的一种推广&#xff0c;也是数据元素的有序序列) 一、基础 1.如何设定链表结点?广义表中的数据元素可能为单元素(原子)或子表&#xff0c;由此需要两种结点:一种是表结点&#xff0c;用以表示广义表;一种是单元素结点&#xff0c;…

数据库各种锁详解

文章目录排他锁共享锁更新锁意向锁锁的粒度数据库自动加锁手动加锁各种锁之间的兼容问题排他锁 Exclusive Locks&#xff0c;英译&#xff1a;排他锁&#xff0c;简称 X 锁&#xff0c;又称为写锁或独占锁。排他锁分为表级排他锁和行级排他锁。 如果事务 T1 对数据行对象 A 加…

activiti dmn_新的DMN编辑器预览

activiti dmnWorkbench 7.13.0.Final于10月16日星期二发布&#xff0c;此版本带来了许多有趣的功能和重要的修复程序。 亮点之一是作为技术预览功能的新DMN编辑器&#xff0c;该功能仍在开发中&#xff0c;但您可以开始使用。 在本文中&#xff0c;您将学习如何启用DMN编辑器预…

MySQL的索引存储数据结构BTree和B+Tree的区别

文章目录BTree 原理示意图BTree 原理示意图BTree的树层级很少BTree 可以高效支持范围查找BTree 原理示意图 注&#xff1a;BTree 就是 B-Tree&#xff0c;实际上官方并没有 B-Tree 的说法。 BTree 原理示意图 BTree的树层级很少 BTree 的数据存在每个节点中&#xff0c;所以每…

jdk11 javafx_JDK 11上的JavaFX

jdk11 javafx在JFX第11版发布后&#xff0c;人们对JavaFX与JDK的解耦感到百感交集。 我们许多人认为现在是时候告别JavaFX并改用另一种GUI技术了&#xff0c;而另一些人对此情况感到高兴。 他们认为&#xff0c;将JavaFX与Oracle分离开来&#xff0c;并致力于将其作为开源社区驱…

配置Java环境变量

JAVA环境变量配置 一、新建系统变量 新建变量&#xff0c;找到安装目录新建一个JAVA_HOME,路径为bin目录的前一级目录。 可以安装多个JAVA版本&#xff0c;然后新建不同的JAVA_HOME名称&#xff0c;然后填写bin目录的前一级路径。 二、编辑环境变量 找到path,然后编辑%JAVA…

MySQL的存储引擎InnoDB,B+Tree数据结构索引的实现原理图(聚簇索引/聚集索引)

1.表数据文件本身就是按BTree组织的一个索引结构文件 2.InnoDB的BTree的索引数据结构中&#xff0c;表数据和索引数据合并在一起&#xff0c;即叶子节点包含了完整的数据记录&#xff0c;这样的索引叫聚簇索引。

idea 切换java11_Java 11就在这里,您准备好进行切换了吗?

idea 切换java11在应该将Java 9发行版“震撼我们的世界”一年之后&#xff0c;我们一直在等待的LTS版本终于出现了 我们知道&#xff0c;大多数开发人员&#xff0c;团队&#xff0c;公司等尚未通过Java 8进行更新。 即使去年发布了模块Java 9&#xff0c;随后在3月又发布了Ja…

编译Java源文件

编写 新建hello.java文件 注意类名要和文件名称相同&#xff0c;如果不相同会提示错误 public class hello{public static void main(String[] args) {System.out.println("HelloWorld");} }编译 javac hello.java 编译会生成相应的.class文件。 运行 java hell…

oracle jdk_两个Oracle JDK的故事

oracle jdk最近 &#xff0c;人们担心 Java开发人员现在会无意中使用错误的Oracle提供的JDK实现&#xff08;从JDK 11开始 &#xff09;&#xff0c; Oracle提供了开源OpenJDK的构建 &#xff0c;并且还主要基于OpenJDK源提供了商业JDK的构建。 下表比较并对比了Oracle提供的两…

安装MAVEN和找不到JAVA_HOME问题原因

一、MAVEN安装 1.将下载好的MAVEN解压 2.配置MAVEN环境变量 MAVEN_HOME3.3.9 配置path 3.配置本地仓库 打开settings.xml进行修改 在MAVEN下新建一个repository文件夹 4.配置阿里MAVEN仓库配置 每次去阿里云下载jar包 <mirror><id>AliMaven</id>&…