龙空技术网

函数式编程思维第一章为什么

从头开始自学java 2238

前言:

目前姐妹们对“java词频处理”都比较关心,你们都需要学习一些“java词频处理”的相关资讯。那么小编同时在网上收集了一些对于“java词频处理””的相关知识,希望姐妹们能喜欢,兄弟们一起来学习一下吧!

学习编程范式的困难

学习一种全新的编程范式,困难并不在于掌握新的语言。语法不过是些小细节罢了。真正考验人的,是怎么学会用另一种方式去思考。

用“函数式”的方式编写代码牵涉到诸多方面,包括设计上的种种取舍、不同重用单元的作用等。比起语法,更看重思路。

所有的语言都趋向函数式

所有的语言都日渐向函数式靠拢。

范式转变

计算机科学的进步经常是间歇式的,好思路有时搁置数十年后才突然间变成主流。

第一种面向对象的语言Simula 67是1967年发明的,可是直到1983年诞生的C++终于流行起来以后,面向对象才真正成为主流。

再优秀的想法也得等待技术基础慢慢成熟。早年Java总被认为太慢,内存耗费太高,不适合高性能的应用,如今硬件市场的变迁把它变成了极具吸引力的选择。

函数式编程的发展轨迹与面向对象编程十分相似,它也是诞生在学院里。

举例说明命令式和函数式的区别——词频统计

java8之前的版本:

对于提倡以步进方式处理集合(正则表达式的匹配结果)遍历的语言来说,这是司空见惯的编码风格。

在一个迭代块里完成三项操作,这是牺牲了代码的清晰来换取执行性能。

Java 8版本:

命令式编程风格迫使我们出于性能考虑,把不同的任务交织起来,以便能够用一次循环来完成多个任务。而函数式编程用map()、filter()这些高阶函数把我们解放出来,让我们站在更高的抽象层次上去考虑问题,把问题看得更清楚。

跟上语言发展的潮流

所有的主流语言都在进行函数式方面的扩充。

把控制权让渡给语言/运行时

自动垃圾收集

人生苦短,远离malloc。

把乏味单调的任务托付给语言和运行时。

Java接管内存分配减轻了我们的负担,函数式编程语言让我们用高阶抽象从容取代基本的控制结构,也有着同样的意义。

将琐碎的细节交托给运行时,令繁冗的实现化作轻巧。

简洁

函数式抽象和面向对象抽象的关键区别:面向对象编程通过封装不确定因素来使代码能被人理解;函数式编程通过尽量减少不确定因素来使代码能被人理解。

精细地控制谁能够感知状态和改变状态——“不确定因素”(moving parts)

与其建立种种机制来控制可变的状态,不如尽可能消灭可变的状态这个不确定因素。其立论的根据是这样的:假如语言不对外暴露那么多有出错可能的特性,那么开发者就不那么容易犯错。

在面向对象的命令式编程语言里面,重用的单元是类和类之间沟通用的消息,这些都可以用类图(class diagram)来表述。

OOP的世界提倡开发者针对具体问题建立专门的数据结构,相关的专门操作以“方法”的形式附加在数据结构上。

函数式语言提倡在有限的几种关键数据结构(如list、set、map)上运用针对这些数据结构高度优化过的操作,以此构成基本的运转机构。开发者再根据具体用途,插入自己的数据结构和高阶函数去调整机构的运转方式。

比起一味创建新的类结构体系,把封装的单元降低到函数级别,更有利于达到细粒度的、基础层面的重用。

函数式程序员喜欢用少数几个核心数据结构,围绕它们去建立一套充分优化的运转机构。面向对象程序员喜欢不断地创建新的数据结构和附属的操作,因为压倒一切的面向对象编程范式就是建立新的类和类间的消息。把所有的数据结构都封装成类,一方面压制了方法层面的重用,另一方面鼓励了大粒度的框架式的重用。函数式编程的程序构造更方便我们在比较细小的层面上重用代码。

举例说明——Java版本

indexOfAny()方法的参数是一个CharSequence和一个数组,它会在CharSequence中查找数组里的字符,并返回任意一个字符第一次出现的索引位置。

对于searchChars中的任意字符,在目标字符串中查找该字符第一处匹配的索引位置。

举例说明——Scala版本

Scala的zip()方法将(从0到输入字符串长度值的)数字集合与String对象中所含字符的集合对位结合,组成一个新的、由数字和字符对构成的集合。

zip方法得名于它像拉链(zipper)一样让两个集合对齐咬合在一起。

null的存在是Java语言的一大混乱来源:它到底是一个有效的返回值,还是表明返回值缺失了?包括Scala在内的很多函数式语言通过Option类来避免这种语义上的含混,其取值要么是表示没有返回值的None,要么是容纳了返回值的Some。

scala版本的程序可以直接修改为返回匹配项的一个缓求值列表:

标签: #java词频处理