1.什么是函数式编程
将业务逻辑细化,抽象,封装成一个个功能函数,并借助语言自带的高阶函数api,将整个业务流程转化为函数之间的相互调用,这就是函数式编程。
我们可以看到,函数式编程中,函数不仅直接调用,也可以当成参数被其他函数调用。因此,进一步,如果我们不仅想把函数当参数,还想传入值,所以再封装一下,函数和值封装后是什么。
函数->行为
值->属性
没错就是这就是对象
将业务逻辑细化,抽象,封装成一个个对象,并借助语言,库,组件,框架等,将整个业务流程转化为对象之间的相互调用,这就是面向对象编程。
因此,这么看来,函数式跟面向对象的思想其实都是一致的,即对逻辑的抽象与封装。
函数编程的最直接的表现,莫过于将函数作为数据自由传递,结合泛型推导能力,使代码表达能力获得飞一般的提升。
2.函数式编程优缺点
优点:
2.1.代码简洁,函数式编程写出的代码简洁且意图明确,比如使用stream接口让你告别for循环。
2.2.函数式编程不需要考虑"死锁"(deadlock),因为它不修改变量,所以根本不存在"锁"线程的问题。不必担心一个线程的数据,被另一个线程修改,所以可以很放心地把工作分摊到多个线程,部署"并发编程"(concurrency),从而使得编写并行程序如此简单,只需要调用一下parallel()方法即可。
2.3.函数式编程最大的好处是引用透明,即函数运行的结果只依赖于输入的参数,而不依赖于外部状态,因此,我们常常说函数式编程没有副作用
缺点:
所有的数据都是不可以改变的,严重占据运行资源,导致运行速度也不够快。
3.函数式接口
jdk8提供了一个函数式接口包java.util.function,里面有众多的函数式接口,这些接口有且只有一个未实现的方法的接口,一般通过FunctionalInterface这个注解来表明某个接口是一个函数式接口。函数式接口是Java支持函数式编程的基础,
关于函数接口,需要记住的就是两件事:
3.1.函数接口是行为的抽象;
3.2函数接口是数据转换器。
而其中最基础最常操作的有以下四个核心接口:
3.3.Function
Function<T,R>: 功能型接口,数据转换器
R apply(T) 方法接收一个 T 类型的对象,返回一个 R类型的对象,例如String.valueOf();
是一个单参数单返回值的行为接口;
提供了 apply, compose, andThen, identity 方法;
3.4.Consumer
consumer: 消费型接口,数据消费器
accept(T) 接收一个 T类型的对象,无返回值,通常用于设置T对象的值,例如System.out.printlnt
单参数无返回值的行为接口;
提供了 accept, andThen 方法;
3.5.Supplier
Supplier: 供给型接口,数据提供器
可以提供 T 类型对象,例如String的toUpperCase();
无参的构造器,提供了 get 方法;
3.6.Predicate
Predicate: 断言型接口,条件测试器
boolen test(T) 接收一个 T 类型的对象,返回布尔值,通常用于传递条件函数,例如String的equalsIgnoreCase();
单参数布尔值的条件性接口。
提供了 test (条件测试) , and-or- negate(与或非) 方法。
4.函数式编程的用例
package com.function;
import java.util.function.Function;
/**
* @author luohaojie
* @snice 2019-06-04 17:44
**/
public class FunctionTest {
public static void main(String[] args) {
Function<Integer, Integer> f = s -> s++;
Function<Integer, Integer> g = s -> s * 2;
System.out.println(f.apply(3));
/**
* 下面表示在执行F时,先执行G,并且执行F时使用G的输出当作输入。
* 相当于以下代码:
* Integer a = g.apply(1);
* System.out.println(f.apply(a));
*/
System.out.println(f.compose(g).apply(1));
/**
* 表示执行F的Apply后使用其返回的值当作输入再执行G的Apply;
* 相当于以下代码
* Integer a = f.apply(1);
* System.out.println(g.apply(a));
*/
System.out.println(f.andThen(g).apply(1));
/**
* identity方法会返回一个不进行任何处理的Function,即输出与输入值相等;
*/
System.out.println(Function.identity().apply("a"));
}
}
//打印
3
2
2
a
package com.function;
import java.util.ArrayList;
import java.util.List;
/**
* @author luohaojie
* @snice 2019-05-20 19:45
**/
public class ConsumerTest {
@FunctionalInterface
public interface Consumer {
void accept(Object o);
}
public static void main(String[] args) {
Consumer consumer = new Consumer() {
@Override
public void accept(Object o) {
System.out.println(o);
}
};
consumer.accept("传统消费");
Consumer c2= (o) -> System.out.println(o);
c2.accept("函数式消费");
}
}
//打印
传统消费
函数式消费
package com.function;
import java.util.function.Predicate;
/**
* @author luohaojie
* @snice 2019-06-04 17:50
**/
public class PredicateTest {
public static void main(String [] args){
Predicate<String> p = o -> o.equals("test");
Predicate<String> g = o -> o.startsWith("t");
/**
* negate: 用于对原来的Predicate做取反处理;
* 如当调用p.test("test")为True时,调用p.negate().test("test")就会是False;
*/
System.out.println(p.negate().test("test"));
/**
* and: 针对同一输入值,多个Predicate均返回True时返回True,否则返回False;
*/
System.out.println(p.and(g).test("test"));
/**
* or: 针对同一输入值,多个Predicate只要有一个返回True则返回True,否则返回False
*/
System.out.println(p.or(g).test("ta"));
}
}
//打印
false
true
true