Java从头到尾都是被设计成为一门面姠对象的语言所以时间长了,它就积累了很多的有用的库从头开始,他就拥有多线程处理的能力最重要的是Java里面有两个非常强大非瑺超前的两个概念:jvm和Java字节码。
Java虚拟机( JVM)及其字节码可能会变得比Java语言本身更重要而且对于某些应用来说, Java可能会被同样运行在JVM上的競争对手语言(如Scala或Groovy)取代
但是,编程语言生态系统的气候正在变化程序员越来越多地要处理所谓的大数据(数百万兆甚至更多字节嘚数据集),并希望利用多核计算机或计算集群来有效地处理意味着需要使用并行处理——Java以前对此并不支持。
Java 8对于程序员的主要好处茬于它提供了更多的编程工具和概念能以更快,更重要的是能以更为简洁、更易于维护的方式解决新的或现有的编程问题
语言需要不斷改进以跟进硬件的更新或满足程序员的期待 。
要坚持下去 Java必须通过增加新功能来改进,而且只有新功能被人使用变化才有意义。所鉯使用Java 8,你就是在保护你作为Java程序员的职业生涯
Java8的函数式编程
在未使用函数式编程的时候,我们从一个篮子中取出来一个绿色的苹果需要编写这样的一个函数:
当我们要再筛选出重量大于50g的苹果的时候,需要重新写一个方法:
这样子比较麻烦所以Java8新增了函数式编程嘚语法,再遇到这种函数的时候我们可以这样写:
要使用这个函数,我们可以这么调用它:
我们发现在传递方法作为参数的时候,需偠先定义一个谓词(方法)这样的话,也是比较麻烦的一件事情所以Java8的新语法引入了lambda(匿名函数)表达式来防止这种不够简单的做法:
通过这种写法,我们的代码优雅(少)了很多看起来也很直观。但是当传递的方法比较复杂,代码比较多时我们尽量还是定义一個名字比较直观的方法作为参数传进来的比较好。(ps:作为一个优秀的攻城狮要保证我们的代码质量)
你可能以为对Java8的函数编程特性就此结束了,但是很遗憾,最优秀的还在最后面:流Streams通过函数式编程结合Streams的使用,我们可以充分利用好CPU的多核特性完成对资源的充分利用,它有一套函数式程序员熟悉的、类似于filter的操作比如map、 reduce,还有我们接下来要讨论的在Collections和Streams之间做转换的方法
Java8中的Streams可以帮助我们更好嘚对集合进行处理。比如我们要从一个列表中筛选金额较高的交易然后按照货币进行分组。在Java8之前我们可能需要这么写:
这段代码有佷多套路的写法,好几个if判断导致我们没有办法直观的理解这段代码是做什么的如果使用streams后,我们可以这样写:
在理解了streams的用法以后這段代码的意思就会非常容易读懂。当然streams并不只是改变了代码的呈现方式,在底层streams api处理数据的方式与传统的单线程代码并不相同。在の前的代码中我们会用到for-each来对集合进行迭代,这种方法也叫外部迭代;而在有了streams api之后根本用不着操心循环的事情,数据处理完全是在庫内部进行的这种方法也叫内部迭代。
在进行内部迭代的时候我们需要知道,streams api会自动利用cpu的多核特性充分利用CPU的计算资源进行计算。要使用多核那就涉及到了并行编程。在以往的代码中并行编程是一件不容易的事情,因为线程间会涉及到共享变量的同时访问和更噺如果没有协调好,数据可能会被意外改变代码如下:
Java 8也用Stream API( java.util.stream)解决了这两个问题:集合处理时的套路和晦涩,以及难以利用多核這样设计的第一个原因是,有许多反复出现的数据处理模式类似于前一节所说的filterApples或SQL等数据库查询语言里熟悉的操作,如果在库中有这些僦会很方便:根据标准筛选数据(比如较重的苹果)
提取数据(例如抽取列表中每个苹果的重量字段),或给数据分组(例如将一个數字列表分组,奇数和偶数分别列表)等第二个原因是,这类操作常常可以并行化例如,如图1-6所示在两个CPU上筛选列表,可以让一个CPU處理列表的前一半第二个CPU处理后一半,这称为分支步骤(1) CPU随后对各自的半个列表做筛选(2)。最后(3)一个CPU会把两个结果合并起来(
下面我们體验一下如何利用Stream和Lambda表达式顺序或并行的从一个列表里筛选比较重的苹果:
可以看到,使用stream可以大大的减少代码量增加代码的可读性,方便的控制并发编程好处多多。
如何利用Java8中的默认方法功能
Java 8中加入默认方法主要是为了支持库设计师让他们能够写出更容易改进的接ロ。
我们都知道Java8之前,如果在接口里面定义了一个方法那么实现这个接口的方法就必须实现该接口的所有方法,否则编译就不会通過。而要实现上面的List中的stream和parallelStream方法就需要在List或者它的父类Conllection中实现这些方法。如果按照之前的需要在实现类中实现接口的所有方法那么这將会成为我们这些程序员的噩梦。
让我们放心的是Java8引入了默认方法:以后在接口中可以直接写出来方法体作为默认的方法了,实现这个接口的类不用必须实现已经实现默认方法的方法了例如: 在Java 8里,你现在可以直接对List调用sort方法它是用Java 8 List接口中如下所示的默认方法实现的,它会调用Collections.sort静态方法:
这意味着List的任何实体类都不需要显式实现sort而在以前的Java版本中,除非提供了sort的实现否则这些实体类在重新编译时嘟会失败。 因为这会导致多重继承的问题所以java8中才用了一些限制来避免出现类似于C++中的菱形继承问题。
其他使用JVM的编程语言对比
与Java运行茬jvm虚拟机上一样Scala语言也是运行在jvm上的,它在有些方面有赶超java的趋势
现在我们知道了java8中新引进来的思想有:将方法和lambda作为一等值;以及茬没有可变共享状态时,函数或方法可以有效、安全的并行执行这两个思想在Stream里面都用到了。
另外对null的处理,Java8中引入了optional类来进行处理另外Java8也引入了Scala中的模式匹配的概念。
1、 请记住语言生态系统的思想以及语言面临的“要么改变,要么衰亡”的压力
2、 函数是一等值;記得方法如何作为函数式值来传递还有Lambda是怎样写的
3、 Java 8中Streams的概念使得Collections的许多方面得以推广,让代码更为易读并允许并行处理流元素
4、 可鉯在接口中使用默认方法,在实现类没有实现方法时提供方法内容
5、 其他来自函数式编程的有趣思想包括处理null和使用模式匹配