java8 函数式编程初探

1. 什么是函数式编程

  1. 英文名Functional Programming
  2. 从java8开始,和lambda表达式一起结合使用
  3. 一般使用FunctionInterface注解来标注一个函数接口
  4. 通过复合没有副作用的纯函数,来编写业务逻辑代码
  5. 是一个无状态的函数,执行结果不依赖外部变量值,即同样的入参列表,总是得到相同的结果
  6. 函数作为一段功能代码,可以像变量一样进行引用和传递,以便在有需要的时候进行调用

2. 为什么要用函数式编程

  1. 在代码的书写、视觉感观上更加简洁优雅一点
  2. 可以满足动态、灵活的业务逻辑实现
  3. 函数之间通过链式调用连接在一起,完成一些小而简的业务逻辑编写
  4. 发挥函数式编程在并行计算上的优势

3. 怎么用函数式编程

  1.  简单使用

现有函数接口定义都在java.util.function这个包下面,先找一个现有的jdk中自带的一个函数接口IntFunction来看看

@FunctionalInterface
public interface IntFunction<R> {

    /**
     * Applies this function to the given argument.
     *
     * @param value the function argument
     * @return the function result
     */
    R apply(int value);
}

可以看到,它仍然还是一个接口,具有接口的基本特征,那就好办了,我们还写一个简单的调用实现:

//函数接口的业务逻辑定义
IntFunction<Integer> intFunc = new IntFunction<Integer>() {
    @Override
    public Integer apply(int value) {
	return value*4;
    }
};
//函数接口的实现调用
int result = intFunc.apply(2);
System.out.printf("2*4 = %d;", result);

控制台输出:

//控制台输出
2*4 = 8;

这里是对接口里的抽象方法作了实现,再通过手动调用,传进入参,执行了上面的实现代码,得到了最终的结果 

相信此时,你可能会惊呼,现在已经不需要这么写了,对的,我们有更简洁的书写形式,如下:

//函数接口的业务逻辑定义
//        IntFunction<Integer> intFunc = new IntFunction<Integer>() {
//            @Override
//            public Integer apply(int value) {
//                return value*4;
//            }
//        };
IntFunction<Integer> intFunc = i->i*4;

其实,它是这样一步步进化而来的:

  2.  现有基础函数接口汇总

java8类库已经为我们预定义一些函数接口,方便我们来使用,也可以认为是一些函数模板,下面简要说明一下它们的功能

java8类库自带的函数接口
序号接口说明其它
1BiConsumer<T,U>接收两个入参的操作,不返回结果andThen方法支持连接操作
2BiFunction<T,U,R>接收两个入参的操作,返回结果andThen方法支持连接操作
3BinaryOperator<T>继承BiFunction,入参和出参类型相同maxB最大返回,minBy最小返回
4BiPredicate<T,U>两个入参,返回布尔值

and方法支持与操作

negate方法支持取反操作

or方法支持或操作

5BooleanSupplier无参,返回布尔值 
6Consumer<T>一个入参,不返回结果andThen方法支持连接操作
7DoubleBinaryOperator两个double入参,返回double结果 
8DoubleConsumer一个double入参,不返回结果andThen支持连接操作
9DoubleFunction<R>一个double入参,并返回结果 
10DoublePredicate一个double入参,并返回布尔值

and方法支持与操作

negate方法支持取反操作

or方法支持或操作

11DoubleSupplier无参,返回一个double结果 
12DoubleToIntFunction入参double类型,返回int类型 
13DoubleToLongFunction入参double类型,返回long类型 
14DoubleUnaryOperator入参double类型,返回double类型

andThen方法支持连接操作

compose方法支持组合操作

identity方法返回入参

15Function<T,R>一个入参,一个结果

andThen方法支持连接操作

compose方法支持组合操作

identity方法返回入参

16IntBinaryOperator两个int入参,返回int结果 
17IntConsumer一个int入参,不返回结果andThen支持连接操作
18IntFunction<R>一个int入参,并返回结果 
19IntPredicate一个int入参,并返回布尔值

and方法支持与操作

negate方法支持取反操作

or方法支持或操作

20

IntSupplier无参,返回一个int结果 
21IntToDoubleFunction入参int,返回double类型 
22IntToLongFunction入参int,返回long类型 
23IntUnaryOperator入参int类型,返回int类型

andThen方法支持连接操作

compose方法支持组合操作

identity方法返回入参

24LongBinaryOperator入参两个long类型,返回long类型 
25LongConsumer入参long类型,无返回值andThen支持连接操作
26LongFunction<R>一个long入参,并返回结果 
27LongPredicate一个long入参,并返回布尔值

and方法支持与操作

negate方法支持取反操作

or方法支持或操作

28LongSupplier无参,返回一个long结果 
29LongToDoubleFunction入参long类型,返回double类型 
30LongToIntFunction入参long类型,返回int类型 
31LongUnaryOperator入参long类型,返回long类型

andThen方法支持连接操作

compose方法支持组合操作

identity方法返回入参

32ObjDoubleConsumer<T>入参对象和double类型,无返回值 
33ObjIntConsumer<T>入参对象和int类型,无返回值 
34ObjLongConsumer<T>入参对象和long类型,无返回值 
35Predicate<T>一个入参,返回布尔值

and方法支持与操作

negate方法支持取反操作

or方法支持或操作

36Supplier<T>无参,返回一个结果 
37ToDoubleBiFunction<T,U>两个入参,返回double类型 
38ToDoubleFunction<T>一个入参,返回double类型 
39ToIntBiFunction<T,U>两个入参,返回int类型 
40ToIntFunction<T>一个入参,返回int类型 
41ToLongBiFunction<T,U>两个入参,返回long类型 
42ToLongFunction<T>一个入参,返回long类型 
43UnaryOperator<T>一个入参,返回相同类型的结果 

下面对里面最常用的andThen方法做一个简单示例讲解

  • andThen方法
Consumer c = o->{System.out.println("c-" + o);};
Consumer c1 = o->{System.out.println("c1-" + o);};
Consumer c2 = o->{System.out.println("c2-" + o);};
//通过andThen方法,可以将多个函数接口进行连接处理
c.andThen(c2).andThen(c1).accept("hello world!");

最终的输出的结果:

c-hello world!
c2-hello world!
c1-hello world!

我们会发现c本身的输出逻辑先执行,再依次执行后面的c2,c1的输出过程

我们可以通过源码,看到基本的执行过程:

default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    //accept(t); 先执行自身的处理逻辑
    //after.accept(t); 再执行入参的逻辑
    return (T t) -> { accept(t); after.accept(t); };
}

其它的方法,实现过程也基本类似

最后,可以看一下,在我们使用的较多的Stream接口中,存在着大量的函数式接口的参数类型

对函数式编程的相关概念和API有了一定的了解后,对这些API的学习也会有较大的帮助。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值