“ Java SE 8新功能导览”系列的这篇文章中,我们将深入解释并探索代码,以了解如何使用lambda表达式和方法引用 遍历集合 ,并使用谓词接口过滤它们,实现默认方法在接口中,最后在接口中实现静态方法

在上一篇文章“ 使用Lambda Expression进行函数式编程 ”中; 我已深入了解lambda表达式。 我向您展示了Lambda表达式的几种不同用法。 它们都有功能接口的共同实现。 我还解释了编译器如何从代码中推断信息,例如特定类型的变量以及后台实际发生的情况。

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

表中的内容:

  1. 使用lambda表达式遍历集合。
  2. 使用谓词接口过滤集合。
  3. 使用方法引用遍历集合。
  4. 在接口中实现默认方法。
  5. 在接口中实现静态方法。

1,使用lambda表达式遍历集合

在Java SE 8中,可以使用lambda表达式遍历项目集合。 集合的示例包括列表,地图和集合。 所有这些数据类型都实现了一个称为iterable的接口。 为了理解我将要展示的代码,让我们从文档开始。 我正在eg.com.tm.java8.features.lambda2包下的名为TraverseFileContent.java的类中工作。 我将右键单击方法名称readAllLines ,然后单击 Show Javadoc。

它返回扩展了许多接口的List类。 这是我感兴趣的一种叫做可迭代的。 此接口已在Java SE 5中添加。 它有一种称为iterater的方法。 这将返回一个Iterater接口的实例,您可以使用该实例然后遍历集合的内容。 但是在Java SE 8中,有两种新方法。 一台叫做forEach ,另一台叫做spliterator 。 我将专注于forEach方法。

它接受称为Consumer的功能接口的实例。 使用者接口只有一个抽象方法,名为accept 。 通过实现此接口及其单一抽象方法,您可以添加对集合中的某个项目进行操作的代码。

因此,让我们回到代码。 在TraverseFileContent.java类中,我遍历了这行集合,即表示文件内容的字符串数组列表,两次。 在第一个版本中,从第51行开始,我使用了forEach循环,这是一段简单的代码,它为列表中的每个项目创建一个String变量行,然后执行所需的任何代码。

在第58行,我使用了另一种方法,即调用集合的迭代器方法。 获取迭代器对象,然后循环使用while代码块,调用迭代器具有next方法。 现在,这两段代码都可以很好地工作到Java 5,但我将向您展示使用lambda表达式和forEach方法的情况。 在Java 8中,我将从此forEach方法开始。

从65行开始,我将引用我的lines集合并调用新的forEach方法。 再一次,它将接收Consumer接口的实例。 因为Consumer是一个功能接口,所以我可以使用lambda表达式。 使用者接口的accept方法需要一个具有适当数据类型的参数。 因为lines变量被声明为字符串列表,所以我必须传入一个字符串作为参数。

我用行名将其传递。 然后,我将添加我的lambda运算符, 箭头标记 。 我将在此处添加我的系统输出,并直接传递。

您可以通过删除旧的遍历来清理代码。 现在,这一行代码取代了forEach循环的三行。 我将复制此代码并将其移至使用迭代器的版本。 然后,我将选择这些代码行并将其注释掉。 并粘贴我的lambda表达式版本。 因此,当您替换迭代器时,您将用一行替换四行代码。

您可以将Stream与集合一起使用更高级,Streams支持一系列元素,这些元素支持顺序和并行聚合操作。 通常,它用于以下用途:

现在保存并运行代码,看看它的行为与以前完全相同,但是代码更少。 因此,这只是遍历集合的另一种选择。 您可以使用forEach循环。 您可以使用迭代器对象,现在可以对lambda表达式使用forEach方法。

2.使用谓词接口过滤集合

除了新的lambda语法外, Java SE 8还添加了许多新的功能接口 。 最有用的一种称为Predicate接口。 该接口具有一个名为test布尔方法,您可以使用该方法包装条件处理,并使条件代码更加整洁。 我将向您展示如何在该项目中使用谓词接口。

从包eg.com.tm.java8.features.lambda2.predicate名为FileDirFiltereg.com.tm.java8.features.lambda2.predicate ,我声明了一个名为predicateInInnerClass的方法。

我将使用NIO.2 DirectoryStream类来获取特定的路径条目流,在我们的案例中该流声明为:

现在,我的目标是过滤此流,仅显示某些条目,即目录。 您可以将谓词接口与内部类语法或lambda语法一起使用。

我将从内部类语法开始。 在predicateInInnerClass方法中,我将声明谓词接口的实例。 我将输入接口名称,然后按Ctrl + Space 。 然后从列表中选择接口。 它是Java.util.function包的成员,在那里您Java.util.function找到许多其他新的功能接口。 该接口需要通用类型声明。 我将其设置为Path类。 我将谓词命名为dirsFilter

现在,对于内部类语法,我将从new关键字开始,然后按Ctrl + Space并为谓词接口选择构造函数。 选择该选项后, NetBeans会自动实现单个抽象方法test 。 因为我用通用的Path类型声明了谓词,所以test方法也接受该类型的单个参数。 现在,我将实现该方法。 我将要传递的路径对象的名称更改为“ t”。

我将return语句设置为使用非常简单的条件。 我将添加一组括号来包装我的条件。 然后将条件设置为isDirectory(t, NOFOLLOW_LINKS) 。 因此,现在我的谓词对象封装了我的测试,并且可以使用测试方法来确定我是否要处理集合中的对象。

下一步是遍历集合。 您可以通过forEach循环,迭代器对象或新的forEach方法以多种方式执行此操作。

我将使用经典的forEach循环。 我将输入foreach并按Ctrl + Space ,然后选择foreach代码模板。 在for循环中,我将使用一条if语句。 我将设置条件以使用我刚刚声明的dirsFilter对象。 我将呼叫dirsFilter.test 。 我将在foreach循环中传递要声明的文件对象。 然后,如果条件为true,则将使用系统输出,并将输出调用file对象的getFileName方法的结果。

我将保存并运行该代码。 而且我只看到目录类型路径的完整路径。 现在,如果我想更改条件,则可以更改谓词对象并重新运行代码,它将可以正常工作。 但是我们这里的目标是使代码尽可能简洁和可读。 为此,您可能决定使用lambda表达式来实现此谓词接口。 因此,让我们回到代码,然后折叠该方法predicateInInnerClass ,并展开其他方法predicateWithLambda

现在,我将进行非常类似的处理。 但这次我将使用lambda表达式声明我的谓词对象。 再一次,我将输入接口的名称。 我将按Ctrl + Space并从列表中选择它,然后设置其通用类型。 我将这个谓词对象noFilter 。 现在,我将使用lambda表达式实现该接口。 我将从要实现的方法的签名开始。 那是test方法。 并且由于我声明的谓词具有通用的Path类型,因此该参数将成为path的实例。

我将其命名为p 。 然后,我将添加arrow标记 ,然后使用一个简单的条件表达式来实现我的方法,将其设置为true即可返回所有已定义的路径条目。 这就是我所需要的。 在内部类版本中,这一行代码替换了五到六行代码。 接下来,我将遍历该列表并使用谓词对象的test方法。 这次,我将使用doFilterAndPrintPath方法传入谓词noFilter

我展示了如何在以前的lambda实现中使用此方法。 这是Java SE 8中添加的一个新方法。在doFilterAndPrintPath方法的实现中,我使用newDirectoryStream返回的路径集合的forEach方法,我将从作为参数传递的对象的名称开始。 这次,我不会将其包装在括号内只是为了向您展示语法上的差异。 然后,我将添加箭头标记和一对大括号。 在大括号内,我将使用if语句。 然后我将通过条件,这也是谓词的test方法。 我将使用pred.test ,并传递path对象。

如果条件为真,我将使用系统输出。 然后我将输出路径对象文件名。 我将保存并运行代码。 结果就是。 我再次显示所有条目。 但是,如果我想处理不止一种可能的情况怎么办? 好吧,这是关于lambda语法和谓词接口的伟大之处。

您可以根据需要创建任意多个谓词对象,每个谓词对象代表不同的条件。

因此,我将复制这一行代码,并将新代码的名称更改为hiddenFilter 。 并且我将其条件更改为仅显示隐藏的文件和目录。 为了使传递想要的谓词真的很容易,我将遍历集合的这段代码放入单独的方法中。 我们已经在doFilterAndPrintPath方法中做到了。

现在,该方法不知道它将获得哪个谓词,因此我将方法中谓词对象的名称重构为pred 。 现在,我现有的代码将传递给hiddenFilter ,所以我将运行它。 而且我得到了所有隐藏的文件目录 。 然后将传入的谓词对象更改为timeFilter ,然后再次运行代码。

这次我得到了今天修改的所有文件和目录。 因此,这就是您可以使用新的谓词接口和lambda表达式将条件封装在单个对象中的方式。 然后将这些对象传递到您自己的方法中进行处理。

我不会详细介绍Java SE 8中的许多其他新功能接口,但是我鼓励您研究一下谓词接口是java.util.function的一部分的程序包。 您会在那里找到许多新的有用界面。

而且由于它们都是功能性接口,因此都可以使用lambda表达式实现。

3,使用方法引用遍历集合

除了Lambda表达式外,Java SE 8的Project Lambda还向该语言添加了方法引用。 方法参考提供了一种命名您要调用的方法的方法,而不是直接调用它。 就像Lambda表达式一样,目标是使您的代码更简洁,更易读。

我将在名为MethodReference此类中的类( MethodReference下进行eg.com.tm.java8.features.lambda2.mthdRefs

您可以对四种方法使用方法引用:

  1. 任何类的静态方法。
  2. 特定对象的实例方法。
  3. 任意对象的实例方法,在这种情况下,您将像静态方法一样引用它。
  4. 并引用构造函数方法。

我将从静态方法开始。 在这段代码中,我有一个FilesDirTests类,我的目标是检查是否可以访问特定文件。 我将创建一个对路径类进行一些比较的方法。 现在您可以将此方法放置在任何您喜欢的位置,并且开发人员在最佳放置位置上会有所不同,但是我将创建该方法作为我的FilesDirTests类的静态方法。

我将打开类,并放置此新方法。 我将其声明为publicstatic ,并将其返回数据类型设置为boolean 。 我将方法命名为isAccessible 。 并且该方法将接受对路径类的引用。 我将其命名为p。 该方法将知道目标是将路径与java.nio.file.Files类中定义的某些可访问性方法进行比较。 就像Predicate接口的test方法一样,如果该路径可访问,则返回true,否则返回false表示该路径不可访问。

我将保存该更改,现在我将进入类MethodReference 。 为了测试给定路径文件的可访问性,我再次使用doFilterAndPrintPath(Predicate<Path> pred)方法。 我将在doPrint方法中调用它。 定义的路径在doFilterAndPrintPath方法内部使用。 对于谓词对象,我将使用方法reference 。 它看起来像这样,我指的是静态方法,因此我将从包含静态方法的类的类型开始。

然后,我将输入双冒号运算符,这就是您将类型或对象与要调用的方法的名称分开的方式。 然后,我将传入方法的名称isAccessible 。 现在,这就是为什么这样做的原因。 此方法doFilterAndPrintPath方法期望谓词接口的实例。 该接口只有一个抽象方法,该方法需要一个值。 我正在调用一个期望一个值的方法。 并返回测试方法可以使用的数据类型。

doFilterAndPrintPath将遍历路径文件,并根据测试输出值。 保存更改,然后运行代码,即可得到结果。 Opppps没有结果? 没有打印文件? 这是因为isAccessible具有测试条件,该条件会使测试失败,这是isExecutable方法。

这是一个静态方法参考。 如果愿意,可以将方法引用与实例方法一起使用 。 为此,我将在MethodReference类的结尾处添加以下两个方法:

在此类的main方法中,我将创建当前类的实例,然后将其称为doFilterAndPrintPath方法。 在我到这里时,所有数据和方法都是实例成员,而不是静态成员。

因为main是静态方法,所以我们不能使用this关键字,作为替代语法,您可以在对象实例方法中将此关键字用作引用。

和以前一样,我将保存并运行,然后得到结果。 因此,方法引用是使代码简明扼要的一种简单方法。

4,在接口中实现默认方法

Java SE 8之前,接口可以包含抽象方法和常量声明,但是您不能提供可继承的完全实现的方法。

我正在使用一个名为eg.com.tm.java8.features.lambda2.defltMthd的软件包。 在此应用程序中,我有一个名为VehicleInterface.Java的接口。 它有八个抽象方法,在接口中所有抽象方法都即将公开,因此我没有包含public关键字,它们是基本的gettersetter

然后,我有一个名为Car.java的类,该类具有实现的setter和getter。 还有一个构造函数方法,可以很容易地实例化该类。

然后,我有一个名为DefaultMethod.java的主类。 在这段代码中,我使用谓词对象过滤汽车列表,然后显示汽车。 我将一个名为info的字符串放在一起,并将其输出到控制台。 因此,我将使用Java SE 8的新功能来重构此代码,该功能使我可以向接口添加称为默认方法的内容。

将默认方法添加到接口时,可以添加其完整实现。 然后,实现该接口的任何类都将继承该方法,并且您可以调用该方法本身,或者该方法将可在应用程序的任何其他位置调用,因为与抽象方法一样,该方法将是公共的。

返回VehicleInterface.Java我将光标移到abstract方法下面。 然后,我将使用new关键字default开始方法签名。 该方法的其余部分看起来完全一样,就像我在一个类中实现它一样。

我将从返回类型开始,然后是方法的名称。 接下来,我将添加代码,它将是一个return语句,可以将name , model ,car CC和make year的值连接起来。 现在, 因为这是一个接口,所以我不能引用私有字段。 你不能那样做 。

因此,我将只引用抽象方法,我知道它将由类本身实现。 我将调用getNamegetModelgetCC 。 然后,我将getMakeYeargetMakeYear圆括号连接getMakeYear

我将保存该更改,现在该方法可用于实现该接口的每个类。 我不会对Car类进行任何更改。 它已经有该方法。 然后,我将在这里转到主类,使用默认方法,然后更改此代码。 我不再需要创建名为Info的字符串,这将由Car类继承的新方法完成。 因此,我将注释掉那行代码。 然后,我将使用对getInfo方法的调用来替换对info变量的引用。

但是我将其称为我现在正在使用的汽车对象的成员。 我将保存更改并运行代码。 结果就来了。 我成功地调用了getInfo方法来获取字符串,名称,模型,CC和制造年份的值的串联,然后使用主类中的代码将其输出到控制台。

通过使用默认方法 ,有时可以消除整个继承层。 例如,某些开发人员在Java的早期版本中可能创建了一个接口,然后创建了实现该接口的基类,然后创建了他们将在其代码中实际使用的子类。

使用此新功能,您可能根本不需要基类,而是可以直接实现子类,直接从接口继承默认方法。

5,在接口中实现静态方法

前面我已经描述了如何向接口添加默认方法,这些方法已完全实现并由实现类继承。 在Java SE 8中,还可以向接口添加完全实现的静态方法。 与默认方法一样,目标是让您消除继承层并简化应用程序。

我正在使用一个名为eg.com.tm.java8.features.lambda2.staticMthd的包。 就像在较早的项目中一样,用于默认方法的那个主类在这里称为StaticMethod ,它具有从汽车对象获取名称modelCC以及年份的代码。

在本课程的第47行。 我的目标是采用此代码并将其移至静态方法,但不是将其添加到基类或其他具体类中,而是将其添加到接口中。 我在早期版本的Java中无法执行的操作。 我将使用此代码并将其复制到剪贴板。 然后,我将打开名为VehicleInterface.java的接口。 和以前一样,我从一组抽象方法声明开始。 现在,将光标放在这些抽象方法声明之后,并从关键字static开始。

与默认方法和抽象方法一样,这将自动成为公共方法。 我不需要声明它。 它将返回一个字符串,并将其命名为getVehicleInfo 。 现在,由于这是一个static方法,因此无法引用上面声明的实例方法。 因此,我将传递Car对象的实例。 然后,我将提供return关键字,并粘贴之前的代码,然后进行清理,以便现在返回namemodelCC以及make year和右括号。

现在,可以在应用程序中的任何位置使用此static方法。 和以前一样,我无需对Model类做任何事情。 之所以称为car ,是因为该接口中已经提供了要获取字符串并输出的所有代码。

我将回到我的主类,使用静态方法,现在,我将使用接口名称VehicleInterface.java调用该接口,而不是在此处将这个字符串放在一起,然后将其称为新的静态方法, getVehicleInfo并传入Car对象c

我将保存更改并运行代码。 结果就来了。 从功能上讲,它与使用默认方法,将此代码放入Car类或在主类的顶级将其完全相同。

默认方法和静态方法的目的只是为您提供更多选择,以为您的应用程序组合继承模型。 使用默认方法和静态方法, 您可以消除应用程序的整个继承层,并极大地简化编码模型,从而使应用程序更易于编码和维护

资源资源

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

翻译自: https://www.javacodegeeks.com/2014/12/java-se-8-new-features-tour-traversing-filtering-processing-collection-methods-enhancements-with-lambda.html

Java SE 8新功能介绍:Lambda的遍历,过滤,处理集合和方法增强相关推荐

  1. Java SE 8新功能介绍:使用Streams API处理集合

    使用Java SE 8 Streams的代码更干净,易读且功能强大..... 在" Java SE 8新功能介绍"系列的这篇文章中,我们将深入解释和探索代码,以了解如何使用流遍历集 ...

  2. Java SE 8新功能介绍:使用新的DateTime API计算时间跨度

    使用Java SE 8新的DateTime API JSR 310-可以实现更清晰,可读且功能强大的编码. Java SE 8,JSR 310 在上一篇文章" 使用Streams API处理 ...

  3. java8 streams_Java SE 8新功能介绍:使用Streams API处理集合

    java8 streams 使用Java SE 8 Streams的代码更干净,易读且功能强大..... 在" Java SE 8新功能导览"系列的这篇文章中,我们将深入解释并探索 ...

  4. java lambda函数_Java SE 8新功能介绍:使用Lambda Expression进行函数式编程

    java lambda函数 " Java SE 8新功能浏览 "系列的这篇文章将深入了解Lambda表达式 . 我将向您展示Lambda表达式的几种不同用法. 它们都具有功能接口的 ...

  5. Java SE 8新功能导览:Java开发世界中的重大变化

    与其他专业团队成员一样,我是采用OpenJDK的成员之一,但是从最近8个月开始加入,我们经历了Java SE 8 开发,编译,编码,讨论等各个阶段,直到将其付诸实践为止. . 它于2014年3月18日 ...

  6. java se 导原码_Java SE 8新功能导览:Java开发世界中的重大变化

    java se 导原码 我很自豪,像其他专业团队成员一样,是采用OpenJDK的成员之一,但是从过去8个月就加入了,我们经历了Java SE 8 开发,编译,编码,讨论等各个阶段,直到将其付诸实践为止 ...

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

    " Java SE 8新功能浏览 "系列的这篇文章将深入了解Lambda表达式 . 我将向您展示Lambda表达式的几种不同用法. 它们都具有功能接口的共同实现. 我将解释编译器如 ...

  8. Java SE 6 新特性 Instrumentation 新功能

    系列内容: 此内容是该系列的一部分:Java SE 6 新特性 Instrumentation 简介 利用 Java 代码,即 java.lang.instrument 做动态 Instrumenta ...

  9. Java 17 新功能介绍(LTS)

    点赞再看,动力无限.Hello world : ) 微信搜「 程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Ja ...

最新文章

  1. 《计算机组成与体系结构:性能设计》读后小记 11、指令集:寻址方式和指令格式...
  2. 处理字符串_13_按照指定的分隔符截取字符返回表形式
  3. EconomicIndoor集成测试
  4. 软件版本号命名规范_软件发布版本介绍
  5. DMA双缓冲传输意义
  6. netcat运行出错
  7. java编译容器_Java基础:容器
  8. 删除HTML标签的正则表达式
  9. Content-type 对照表
  10. TeamTalk源码分析(1)
  11. 【时间序列】多变量时间序列异常检测数据集整理及标准化处理代码合集
  12. m4s格式转换mp3_QQ音乐下载的歌曲怎么转换MP3?音频转换格式详细教程
  13. 斑马网络招聘汽车安全软件工程师
  14. 微软Win8Server2012各版本安装密匙序列号
  15. 高级转录组调控分析和R语言数据可视化第十三期 (线上线下开课)
  16. (CVE-2020-11800)Zabbix_Server_trapper_命令注入漏洞
  17. 3月份GitHub上最热门的JavaScript开源项目(下)
  18. 写给前端初学者的Vue入门教程
  19. Python爬虫——爬取股票信息
  20. 原生 js 获取所有兄弟节点

热门文章

  1. stream 提取某字段_java8从list集合中取出某一属性的值的集合案例
  2. mysql自动插入的时间不对 差8小时
  3. 计算机网络协议和通信规则,计算机网络协议基本知识
  4. python scratch unity_Unity3D研究院之2D游戏开发制作原理(二十一)
  5. javaweb调用python算法_请教怎么用java远程调用python? 多谢
  6. map iterator_一个简单的Map Iterator性能测试
  7. kafka netty_惠而浦:使用Netty和Kafka的微服务
  8. java方法重载和重载方法_Java 8的方法参考进一步限制了重载
  9. apache camel_Apache Camel日志组件示例
  10. java 从未导入_Java 8的10个您从未听说过的功能