好程序员Java培训分享Java函数式编码结构,本文将探讨三种下一代JVM语言:Groovy、Scala和Clojure,比较并对比新的功能和范例,让Java开发人员对自己近期的未来发展有大体的认识,下面我们一起来看一下吧。

  当垃圾回收成为主流时,它消除了所有类别的难以调试的问题,使运行时能够为开发人员管理复杂的、容易出错的进程。函数式编程旨在为你编写的算法实现同样的优化,这样你就可以从一个更高的抽象层面开展工作,同时运行时执行复杂的优化。

  Java下一代语言并不都占用从命令式到函数式的语言频谱的同一位置,但都展现出函数功能和习语。函数式编程技术有明确定义,但语言有时为相同的函数式概念使用不同的术语,使得我们很难看到相似之处。在本期文章中,我比较了Scala、Groovy和Clojure的函数式编码风格并讨论了它们的优势。

  命令式处理

  我要首先探讨一个常见问题及其命令式解决方案。假如给定一个名称列表,其中一些名称包含一个字符。系统会要求你在一个逗号分隔的字符串中返回名称,该字符串中不包含单字母的名称,每个名称的首字母都大写。实现该算法的Java代码如清单1所示。

  清单1.命令式处理

  public class TheCompanyProcess {

  public String cleanNames(List listOfNames) {

  StringBuilder result = new StringBuilder();

  for(int i = 0; i < listOfNames.size(); i++) {

  if (listOfNames.get(i).length() > 1) {

  result.append(capitalizeString(listOfNames.get(i))).append(",");

  }

  }

  return result.substring(0, result.length() - 1).toString();

  }

  public String capitalizeString(String s) {

  return s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

  }

  }

  由于你必须处理整个列表,解决清单1中问题最简单的方式是使用一个命令式循环。对于每个名称,都需要进行检查,确认其长度是否大于1,然后(如果长度大于1)将首字母大写的名称附加到result字符串,并在后面加逗号。最终字符串中的最后一个名称不应包含逗号,所以我将它从最后返回值中移走。

  在命令式编程中,建议你在较低级上别执行操作。在清单1中的cleanNames()方法中,我执行了三个任务:我筛选列表以消除单字符,将列表中每个名称的首字母变换为大写,然后将列表转化为一个字符串。在命令式语言中,我不得不为三个任务都使用同一低级机制(对列表进行迭代)。函数式语言将筛选、变换和转化视为常见操作,因此它们提供给你从不同视角解决问题的方式。

  函数式处理

  函数编程语言与命令式语言的问题分类方式不同。筛选、变换和转化逻辑类别表现为函数。那些函数实现低级变换并依赖于开发人员来编写作为参数传递的函数,进而定制函数的行为。我可以用伪代码将清单1中的问题概念化为:

  listOfEmps -> filter(x.length > 1) -> transform(x.capitalize) ->

  convert(x, y -> x + "," + y)

  利用函数式语言,你可以建模这一概念性解决方案,无需担心实现细节。

  Scala实现

  清单2使用Scala实现清单1中的处理示例。它看起来就像是前面的伪代码,包含必要的实现细节。

  清单2.Scala处理

  val employees = List("neal", "s", "stu", "j", "rich", "bob")

  val result = employees

  .filter(_.length() > 1)

  .map(_.capitalize)

  .reduce(_ + "," + _)

  对于给定的名称列表,我首先筛选它,剔除长度不大于1的所有名称。然后将该操作的输出提供给map()函数,该函数对集合的每个元素执行所提供的代码块,返回变换后的集合。最后,来自map()的输出集合流向reduce()函数,该函数基于代码块中提供的规则将每个元素结合起来。

  在本例中,我将每对元素结合起来,用插入的逗号连接它们。我不必考虑三个函数调用中参数的名称是什么,所以我可以使用方便的Scala快捷方式,也就是说,使用_跳过名称。reduce()函数从前两个元素入手,将它们结合成一个元素,成为下一个串接中的第一个元素。在“浏览”列表的同时,reduce()构建了所需的逗号分隔的字符串。

  我首先展示Scala实现是因为我对它的语法比较熟悉,而且Scala分别为筛选、变换和转化概念使用了行业通用的名称,即filter、map和reduce。

  Groovy实现

  Groovy拥有相同的功能,但对它们进行命名的方式与脚本语言(比如Ruby)更加一致。清单1中处理示例的Groovy版本如清单3所示。

  清单3.Groovy处理

  class TheCompanyProcess {

  public static String cleanUpNames(List listOfNames) {

  listOfNames

  .findAll {it.length() > 1}

  .collect {it.capitalize()}

  .join(',')

  }

  }

  尽管清单3在结构上类似于清单2中的Scala示例,但方法名称不同。Groovy的findAll集合方法应用所提供的代码块,保留代码块为true的元素。如同Scala,Groovy包含一个隐式参数机制,为单参数代码块使用预定义的it隐式参数。collect方法(Groovy的map版本)对集合的每个元素执行所提供的代码块。Groovy提供一个函数(join()),使用所提供的分隔符将字符串集合串联为单一字符串,这正是本示例中所需要的。

  Clojure实现

  Clojure是一个使用reduce、map和filter函数名的函数式语言,如清单4所示。

  清单4.Clojure处理示例

  (defn process [list-of-emps]

  (reduce str (interpose ","

  (map clojure.string/capitalize

  (filter #(< 1 (count %)) list-of-emps)))))

  Clojure的thread-first宏

  thread-last宏使集合的处理变得更加简单。类似的Clojure宏thread-first可简化与JavaAPI的交互。例如普遍的Java代码语句person.getInformation().

  getAddress().getPostalCode(),这体现了Java违反迪米特法则的倾向。这种类型的语句给Clojure编程带来一些烦恼,迫使使用JavaAPI的开发人员不得不构建由内而外的语句,比如(getPostalCode(getAddress(getInformationperson)))。thread-first宏消除了这一语法困扰。你可以使用宏将嵌套调用编写为(->persongetInformationgetAddressgetPostalCode),想嵌套多少层都可以。

  如果你不习惯查看Clojure,可以使用清单4中的代码,其结构可能不够清晰。Clojure这样的Lisp是“由内而外”进行工作的,所以必须从最后的参数值list-of-emps着手。Clojure的(filter)函数接受两个参数:用于进行筛选的函数(本例中为匿名函数)和要筛选的集合。

  你可以为第一个参数编写一个正式函数定义,比如(fn[x](<1(countx))),但使用Clojure可以更简洁地编写匿名函数。与前面的示例一样,筛选操作的结果是一个较少的集合。(map)函数将变换函数接受为第一个参数,将集合(本例中是(filter)操作的返回值)作为第二个参数。Clojure的(map)函数的第一个参数通常是开发人员提供的函数,但接受单一参数的任何函数都有效;内置capitalize函数也符合要求。

  最后,(map)操作的结果成为了(reduce)的集合参数。(reduce)的第一个参数是组合函数(应用于(interpose)的返回的(str))。(interpose)在集合的每个元素之间(除了最后一个)插入其第一个参数。

  当函数嵌套过多时,即使最有经验的开发人员也会倍感头疼,如清单4中的(process)函数所示。所幸的是,Clojure包含的宏支持你将结构“调整”为更可读的顺序。清单5中的功能与清单4中的功能一样。

  清单5.使用Clojure的thread-last宏

  (defn process2 [list-of-emps]

  (->> list-of-emps

  (filter #(< 1 (count %)))

  (map clojure.string/capitalize)

  (interpose ",")

  (reduce str)))

  Clojurethread-last宏采取对集合应用各种变换的常见操作并颠倒典型的Lisp的顺序,恢复了从左到右的更自然的阅读方式。在清单5中,首先是(list-of-emps)集合。代码块中每个随后的表单被应用于前一个表单。Lisp的优势之一在于其语法灵活性:任何时候代码的可读性变得很差时,你都可以将代码调整回具有较高可读性。

:传递给 left 或 substring 函数的长度参数无效。_Java函数式编码结构-好程序员相关推荐

  1. SQLServer SubString函数提示[传递给 LEFT 或 SUBSTRING 函数的长度参数无效]错误的解决方法

    看错误的字面意思就清楚,一般是substring的length长度有错误. 例如:select top 10 SUBSTRING (c_dept , 1 ,CHARINDEX (',' , c_dep ...

  2. 传递给 left 或 substring 函数的长度参数无效_MySQL:函数入门实例

    数据表PL: Count()函数: 对于除"*"以外的任何参数,返回所选择集合中非NULL值的行的数目 对于"*"参数,返回所选择集合中所有行数,包含NULL值 ...

  3. python process返回值_如何恢复传递给multiprocessing.Process的函数的返回值?

    如何恢复传递给multiprocessing.Process的函数的返回值? 在下面的示例代码中,我想恢复函数的返回值worker.我该怎么做呢?这个值存储在哪里? 示例代码: import mult ...

  4. java length()函数_小猿圈介绍java函数式编码结构及优势

    对于java大家都已经不陌生了吧,今天小猿圈Java讲师就分享一篇关于java函数式编码结构及优势的知识点,希望对于学习java的你有一定的帮助,想学习就需要积累. 探讨三种下一代JVM语言:Groo ...

  5. CImage GetBits()和像素存储格式 传递给opengl贴图函数

    GetBits(): CImage类提供了GetBits()函数来读取数据区,GetBits()函数返回的是图片最后一行第一个像素的地址, 网上有人说返回指针的起始位置是不同的,有些图片返回的是左上角 ...

  6. json最大长度限制_GET请求中URL的最大长度限制总结,读完之后,大部分程序员收藏了...

    浏览器 1.IE IE浏览器(Microsoft Internet Explorer) 对url长度限制是2083(2K+53),超过这个限制,则自动截断(若是form提交则提交按钮不起作用). 2. ...

  7. 编写函数判断一个数是否是回文数_程序员面试金典 - 面试题 01.04. 回文排列

    题目难度: 简单 原题链接 题目描述 给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一. 回文串是指正反两个方向都一样的单词或短语.排列是指字母的重新排列. 回文串不一定是字典当中的单词. ...

  8. 如何将参数传递给setTimeout()回调?

    我有一些如下的JavaScript代码: function statechangedPostQuestion() {//alert("statechangedPostQuestion&quo ...

  9. java中main函数的args参数

    先说一下args的作用: 我们习惯将一些有用的参数传递给我们定义的函数,那么可曾想过有参数传递给main函数?args就是传递给main函数的一个数组参数.         可是main函数作为程序( ...

最新文章

  1. python创建mysql数据库_python 怎么创建create mysql的数据库
  2. Codeforces Round #539 (Div. 2) C. Sasha and a Bit of Relax
  3. “挨踢民工”的奇葩生活录
  4. 关于移动端meta设置(未完待续)
  5. object如何转换为int_如何使用Python将语音转换为文本
  6. java中的locksupport_java中线程的停止以及LockSupport工具类
  7. LeetCode 1701. 平均等待时间(模拟)
  8. 作为程序员,北漂的我有很多话想说。
  9. 【白皮书分享】2021中国数字经济时代人工智能生态白皮书.pdf(附下载链接)...
  10. lodop同一页面一次性打印多次
  11. MATLAB bwlabel
  12. make_heap,pop_heap,push_heap
  13. html js 处理元素的数据属性(data)
  14. 两万字博文教你python爬虫requests库【详解篇】
  15. 清华EMBA课程系列思考之九 -- 中国经济前沿问题解读
  16. Xposed环境安装
  17. instant app入门和开发指南
  18. Linux驱动学习--初识PCI驱动(一)
  19. SkipList(跳跃表)详解
  20. 【星门跳跃】解题报告

热门文章

  1. javascript操作符之new 也疯狂 (2)
  2. [导入]blog年终小结
  3. Collections.min()和Collections.max()的使用
  4. docker ps 和docker ps -a
  5. Dataway让 Spring Boot 开发变得更高效!
  6. windows比linux差在哪,怎么让新手理解Linux比Windows好在哪里!
  7. 远程控制工具_不要让您的工具控制您
  8. 架构师论坛 创业_我在早期创业时作为设计师学到的东西
  9. 洛谷 4115 Qtree4——链分治
  10. Linux下编译安装Mysql简单步骤