深入探寻JAVA8-part1函数式编程与Lambda表达式
开篇在很久之前粗略的看了一遍《Java8 实战》。客观的来,说这是一本写的非常好的书,它由浅入深的讲解了JAVA8的新特性以及这些新特性所解决的问题。最近重新拾起这本书并且对书中的内容进行深入的挖掘和沉淀。接下来的一段时间将会结合这本书,以及我自己阅读JDK8源码的心路历程,来深入的分析JAVA8是如何支持这么多新的特性的,以及这些特性是如何让Java8成为JAVA历史上一个具有里程碑性质的版本。 Java8的新特性概览在这个系列博客的开篇,结合Java8实战中的内容,先简单列举一下JAVA8中比较重要的几个新特性: 函数式编程与Lambda表达式Stram流处理Optional解决空指针噩梦异步问题解决方案CompletableFuture颠覆Date的时间解决方案后面将针对每个专题发博进行详细的说明。 简单说一说函数式编程函数式编程的概念并非这两年才涌现出来,这篇文章用一种通俗易懂的方式对函数式编程的理念进行讲解。顾名思义,函数式编程的核心是函数。函数在编程语言中的映射为方法,函数中的参数被映射为传入方法的参数,函数的返回结果被映射为方法的返回值。但是函数式编程的思想中,对函数的定义更加严苛,比如参数只能被赋值一次,即参数必须为final类型,在整个函数的声明周期中不能对参数进行修改。这个思想在如今看来是不可理喻的,因为这意味着任何参数的状态都不能发生变更。 那么函数式编程是如何解决状态变更的问题呢?它是通过函数来实现的。下面给了一个例子: String reverse(String arg) { if(arg.length == 0) { return arg; } else { return reverse(arg.substring(1, arg.length)) + arg.substring(0, 1); }}对字符串arg进行倒置并不会修改arg本身,而是会返回一个全新的值。它完全符合函数式编程的思想,因为在整个函数的生命周期中,函数中的每一个变量都没有发生修改。这种不变行在如今称为Immutable思想,它极大的减少了函数的副作用。这一特性使得它对单元测试,调试以及编发编程极度友好。因此在面向对象思想已经成为共识的时代,被重新提上历史的舞台。 但是,编程式思想并不只是局限于此,它强调的不是将所有的变量声明为final,而是将这种可重入的代码块在整个程序中自由的传递和复用。JAVA中是通过对象的传递来实现的。举个例子,假如现在有一个筛选订单的功能,需要对订单从不同的维度进行筛选,比如选出所有已经支付完成的订单,或是选出所有实付金额大于100的订单。 简化的订单模型如下所示: public class Order{ private String orderId; //实付金额 private long actualFee; //订单创建时间 private Date createTime; private boolean isPaid}接着写两段过滤逻辑分别实现选出已经支付完成的订单,和所有实付金额大于100的订单 //选出已经支付完成的订单public List<Order> filterPaidOrder(List<Order> orders) { List<Order> paidOrders = new ArrayList<>(); for(Order order : orders) { if(order.isPaid()) { paidOrders.add(order); } } return paidOrdres;}//选出实付金额大于100的订单public List<Order> filterByFee(List<Order> orders) { List<Order> resultOrders = new ArrayList<>(); for(Order order : orders) { if(order.getActualFee()>100) { resultOrders.add(order); } } return resultOrders;}可以看到,上面出现了大量的重复代码,明显的违背了DRY(Dont Repeat Yourself)原则,可以先通过模板模式将判断逻辑用抽象方法的形式抽取出来,交给具体的子类来实现。代码如下: ...