Java8体验

最近开始研究Java8,现将其体验分享如下:   


 1.为什么需要使用Java8     

1996 年1 月,Java 1.0 发布,此后计算机编程领域发生了翻天覆地的变化。商业发展需要更复杂的应用,大多数程序都跑在功能强大的多核CPU 的机器上。带有高效运行时编译器的Java 虚拟机(JVM)的出现,使程序员将更多精力放在编写干净、易于维护的代码上,而不是思考如何将每一个CPU 时钟周期、每字节内存物尽其用。多核CPU 的兴起成为了不容回避的事实。涉及锁的编程算法不但容易出错,而且耗费时间。人们开发了java.util.concurrent 包和很多第三方类库,试图将并发抽象化,帮助程序员写出在多核CPU 上运行良好的程序。很可惜,到目前为止,我们的成果还远远不够。        

开发类库的程序员使用Java 时,发现抽象级别还不够。处理大型数据集合就是个很好的例子,面对大型数据集合,Java 还欠缺高效的并行操作。开发者能够使用Java 8 编写复杂的集合处理算法,只需要简单修改一个方法,就能让代码在多核CPU 上高效运行。为了编写这类处理批量数据的并行类库,需要在语言层面上修改现有的Java:增加Lambda 表达式。        

当然,这样做是有代价的,程序员必须学习如何编写和阅读使用Lambda 表达式的代码,但是,这不是一桩赔本的买卖。与手写一大段复杂、线程安全的代码相比,学习一点新语法和一些新习惯容易很多。开发企业级应用时,好的类库和框架极大地降低了开发时间和成本,也为开发易用且高效的类库扫清了障碍。       

对于习惯了面向对象编程的开发者来说,抽象的概念并不陌生。面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象。现实世界中,数据和行为并存,程序也是如此,因此这两种编程方式我们都得学。这种新的抽象方式还有其他好处。不是所有人都在编写性能优先的代码,对于这些人来说,函数式编程带来的好处尤为明显。程序员能编写出更容易阅读的代码——这种代码更多地表达了业务逻辑的意图,而不是它的实现机制。易读的代码也易于维护、更可靠、更不容易出错。     

 在写回调函数和事件处理程序时,程序员不必再纠缠于匿名内部类的冗繁和可读性,函数式编程让事件处理系统变得更加简单。能将函数方便地传递也让编写惰性代码变得容易,惰性代码在真正需要时才初始化变量的值。Java 8 还让集合类可以拥有一些额外的方法:default 方法。程序员在维护自己的类库时,可以使用这些方法。        


2.函数式编程     

每个人对函数式编程的理解不尽相同。但其核心是:在思考问题时,使用不可变值和函数,函数对一个值进行处理,映射成另一个值。不同的语言社区往往对各自语言中的特性孤芳自赏。现在谈Java 程序员如何定义函数式编程还为时尚早,但是,这根本不重要!我们关心的是如何写出好代码,而不是符合函数式编程风格的代码。本书将重点放在函数式编程的实用性上,包括可以被大多数程序员理解和使用的技术,帮助他们写出易读、易维护的代码。      


3.Lambda表达式      

Lambda 表达式是􀅖 一个匿名方法,将行为像数据一样进行传递。     

 A.Lambda表达式的常见结构:BinaryOperatoradd = (x, y) → x + y。

B.函数接口指仅具有单个抽象方法的接口,用来表示 Lambda表达式的类型。


4.流

内部迭代将更多控制权交给了集合类。

A.和 Iterator 类似,Stream 是一种内部迭代方式。

B.将 Lambda表达式和 Stream 上的方法结合起来,可以完成很多常见的集合操作。


5.类库

使用为基本类型定􀅖 制的 Lambda表达式和 Stream,如IntStream 可以显著提升系统性能。

A.默认方法是指接口中定义的包含方法体的方法,方法名有 default 关键字做前缀。

B.在一个值可能为空的建模情况下,使用 Optional 对象能替代使用 null 值。


6.高级集合类和收集器

方法引用是一种引用方法的轻量级语法,形如:ClassName::methodName。

A.收集器可用来计算流的最终值,是 reduce 方法的模拟。

B.Java 8 提供了收集多种容器类型的方式,同时允许用户自定义收集器。


7.数据并行化

数据并行化是把􀅖 工作拆分,同时在多核 CPU上执行的方式。

A.如果使用流编写代码,可通过调用 parallel 或者 parallelStream 方法实现数据并行化操作。

B. 影响性能的五要素是:数据大小、源数据结构、值是否装箱、可用的 CPU 核数量,以及处理每个元素所花的时间。


8.重构代码和测试

重构遗留代码时考虑如何使用􀅖 Lambda 表达式,有一些通用的模式。

A.如果想要对复杂一点的 Lambda表达式编写单元测试,将其抽取成一个常规的方法。

B.peek 方法能记录中间值,在调试时非常有用。


9.设计架构和原则

Lambda 表达式能让很多现有设计模􀅖 式更简单、可读性更强,尤其是命令者模式。

A.在 Java 8 中,创建领域专用语言有更多的灵活性。

B.在 Java 8 中,有应用 SOLID 原则的新机会。


10.关于响应式编程RxJava

构建复杂并行操作的另外一种方案是使用Future。Future 像一张欠条,方法不是返回一个值,而是返回一个Future 对象,该对象第一次创建时没有值,但以后能拿它“换回”一个值。调用Future 对象的get 方法获取值,它会阻塞当前线程,直到返回值。可惜,和回调一样,组合Future 对象时也有问题,我们会快速浏览这些可能碰到的问题。

这些问题的解决之道是CompletableFuture,它结合了Future 对象打欠条的主意和使用回调处理事件驱动的任务。其要点是可以组合不同的实例,而不用担心末日金字塔问题。

CompletableFuture 背后的概念可以从单一的返回值推广到数据流,这就是响应式编程。响应式编程其实是一种声明式编程方法,它让程序员以自动流动的变化和数据流来编程。你可以将电子表格想象成一个使用响应式编程的例子。如果在单元格C1 中键入=B1+5,其实是在告诉电子表格将B1 中的值加5,然后将结果存入C1。而且,将来B1 中的值变化后,电子表格会自动刷新C1 中的值。

RxJava 类库将这种响应式的理念移植到了JVM。我们这里不会深入类库,只描述其中的一些关键概念。

RxJava 类库引入了一个叫作Observable 的类,该类代表了一组待响应的事件,可以理解为一沓欠条。在Observable 对象和第3 章讲述的Stream 接口之间有很强的关联。

两种情况下,都需要使用Lambda 表达式将行为和一般的操作关联、都需要将高阶函数链接起来定义完成任务的规则。实际上,Observable 定义的很多操作都和Stream 的相同:map、filter、reduce。

最大的不同在于用例。Stream 是为构建内存中集合的计算流程而设计的,而RxJava 则是为了组合异步和基于事件的系统流程而设计的。它没有取数据,而是把数据放进去。换个角度理解RxJava,它是处理一组值,而CompletableFuture 用来处理一个值。


11.何时使用新技术

新技术那么美好,这是否意味着大家明天就要扔掉现有的Java EE 或者Spring 企业级Web 应用呢?答案当然是否定的。

即使不去考虑CompletableFuture 和RxJava 相对较新,使用它们依然有一定的复杂度。它们用起来比到处显式使用Future 和回调简单,但对很多问题来说,传统的阻塞式Web 应用开发技术就足够了。如果还能用,就别修理。

事件驱动和响应式应用正在变得越来越流行,而且经常会是为你的问题建模的最好方式之一。响应式编程宣言(http://www.reactivemanifesto.org/)鼓励大家使用这种方式编写更多应用,如果它适合你的待解问题,那么就应该使用。相比阻塞式设计,有两种情况可能特别适合使用响应式或事件驱动的方式来思考。

第一种情况是业务逻辑本身就使用事件来描述。Twitter 就是一个经典例子。Twitter 是一种订阅文字流信息的服务,用户彼此之间推送信息。使用事件驱动架构编写应用,能准确地为业务建模。图形化展示股票价格可能是另一个例子,每一次价格的变动都可认为是一个事件。

另一种显然的用例是应用需要同时处理大量I/O 操作。阻塞式I/O 需要同时使用大量线程,这会导致大量锁之间的竞争和太多的上下文切换。如果想要处理成千上万的连接,非阻塞式I/O 通常是更好的选择。


12.使用Lambda表达式编写并发程序

使用基于Lambda 表达式的回调,很容易实现事件驱动架构。

A.CompletableFuture 代表了 IOU,使用 Lambda表达式能方便地组合、合并。

B.Observable 继承了 CompletableFuture 的概念,用来处理数据流。


13.下一步计划

A. 向其他程序员(朋友或同事)解释什么是Lambda 􀅖 表达式,为什么会对它产生兴趣。

B.尝试将目前从事的项目部署到 Java 8 环境下。如果现有单元测试已经能运行在持续集成系统Jenkins 下,那么在多个版本的Java 上构建程序也易如反掌。

C. 使用新的 Stream 和 Collector,开始重构真实产品中的遗留代码。它既可以是感兴趣的开放源码项目,也可以是当前从事的项目,前提是第一步里已经部署成功一个测试环境。

D.如果还没准备好大规模迁往Java 8,那么在分支上使用Java 8 做一些原型会是个不错的开始。

E.有没有一些大规模处理数据的代码?或者代码中存在并发问题?试着使用 Stream 处理数据,或使用RxJava 中新的并发特性,也可以使用CompletableFuture 类,来重构你的代码。

F.选择一个熟悉的代码库,分析它的设计和架构。

从宏观上看,有没有更好的实现方法?

能否简化设计?

能否减少实现某功能所需的代码量?

怎样让代码更易读?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,894评论 25 707
  • lambda表达式(又被成为“闭包”或“匿名方法”)方法引用和构造方法引用扩展的目标类型和类型推导接口中的默认方法...
    183207efd207阅读 1,476评论 0 5
  • 原文链接:https://github.com/EasyKotlin 值就是函数,函数就是值。所有函数都消费函数,...
    JackChen1024阅读 5,962评论 1 17
  • 嗡嗡响金黄身子尾带针天露一线光倾巢而出吻花忙 天下瓜果一遍红有谁知道是你功红了瓜果甜满勺一年四季劳 花儿点头你效劳...
    蒋光头jL94430阅读 487评论 8 20
  • 崔雪。我的女朋友,我最爱的女人之一。 我和她认识超过100天了,期间我们通过微信联系,我们打过几次电话,最长一次通...
    張學武阅读 460评论 0 0