Java函数式编程神器 VAVR

共 13125字,需浏览 27分钟

 ·

2021-04-25 10:11

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

76套java从入门到精通实战课程分享

什么是函数式编程

1、基本概念:他是一种编程范式,对于函数式编程来说,它只关心定义输入数据和输出数据相关的关系,数学表达式里面其实是在做一种映射(mapping),输入的数据和输出的数据关系是什么样的,是用函数来定义的。

2、特征:

      (1)stateless:函数不维护任何状态。函数式编程的核心精神是 stateless,简而言之就是它不能存在状态,打个比方,你给我数据我处理完扔出来。里面的数据是不变的。

      (2)immutable:输入数据是不能动的,动了输入数据就有危险,所以要返回新的数据集。(不可变的)

Java为什么要函数式编程

3、优势

(1)没有状态就没有伤害。

(2)并行执行无伤害。

(3)Copy-Paste 重构代码无伤害。

(4)函数的执行没有顺序上的问题。

问题所在

  • 函数式相对于普通的java变成来说,如果没有用过就会直接不清楚这个函数是干什么的,这个是干什么的,如果在团队中只有部分人使用,那我们在其他人在理解我们的代码上就会有问题,也就回增加学习成本,和开发成本。

  • 使用的问题:问题排查的问题 和异常的捕获的问题。

EXAMPLE

package Vavr;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sun.istack.internal.FragmentContentHandler;
import io.vavr.CheckedFunction0;
import io.vavr.Function1;
import io.vavr.Function2;
import io.vavr.Function3;
import io.vavr.Lazy;
import io.vavr.Tuple;
import io.vavr.Tuple2;
import io.vavr.control.Either;
import io.vavr.control.Option;
import io.vavr.control.Try;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Generated;
import lombok.Getter;

/**
 * 函数式编程demo
 *
 * @author yuanxindong
 * @date 4/17/21  7:30 PM
 */
public class VavrTest {

    /**
     * 元组的使用
     */
    public static void tupleTest() {

        //of 静态方法支持使用
        Tuple2<String, Integer> tuple2 = Tuple.of("Hello", 100);

        Tuple2<String, Integer> updatedTuple2 = tuple2.map(String::toUpperCase, v -> v * 5);

        String result = updatedTuple2.apply((str, number) -> String.join(", ",
            str, number.toString()));

        System.out.println(result);
    }

    /**
     * function函数的使用
     */
    public static void functionTest() {

        // 函数定义,前3个是入参,最后是R
        Function3<Integer, Integer, Integer, Integer> function3 = (v1, v2, v3) -> (v1 + v2) * v3;

        // 函数的组合
        Function3<Integer, Integer, Integer, Integer> composed =
            function3.andThen(v -> v * 100);

        //执行结果
        int result = composed.apply(1, 2, 3);

        System.out.println(result);

        //还有包含部分函数的应用
        Function1<Integer, Integer> function1 = function3.apply(1, 2);

        Integer apply = function1.apply(1);
        System.out.println(apply);

        //项目联想
        //结合项目场景使用比如说PDT中定义几个 函数比如:计算MP时效的函数,计算ALG的函数时效,在定义一些函数结果的拼接等
    }

    /**
     * 柯里化想要解决的问题: 柯里化方法的使用 柯里化的含义: 柯里化(currying)是与λ演算相关的重要概念。通过柯里化,可以把有多个输入的函数转换成只有一个输入的函数,从而可以在λ演算中来表示。 柯里化的名称来源于数学家 Haskell Curry。Haskell Curry 是一位传奇性的人物,以他的名字命令了 3 种编程语言,Haskell、Brook 和 Curry。
     * 柯里化是把有多个输入参数的求值过程,转换成多个只包含一个参数的函数的求值过程。 对于清单 6 的函数 f(a, b, c),在柯里化之后转换成函数 g,则对应的调用方式是 g(a)(b)(c)。 函数 (x, y) -> x + y 经过柯里化之后的结果是 x -> (y -> x + y)。
     */
    public static void curriedTest() {
        //设置函数 v1 v
        Function3<Integer, Integer, Integer, Integer> function3 = (v1, v2, v3) -> (v1 + v2) * v3;

        //可以看出来是返回来了一个函数
        Function1<Integer, Function1<Integer, Integer>> apply = function3.curried().apply(1);

        //多次柯里化后就会返回我们想要的记过
        int result = function3.curried().apply(1).curried().apply(2).curried().apply(3);
        System.out.println(result);
    }

    /**
     * 记忆化方法 会将之前计算过的方法进行存储,相同参数在第二次调用的时候会使用缓存
     */
    public static void memoized() {

        //计算差方
        Function2<BigInteger, Integer, BigInteger> pow = BigInteger::pow;
        //记忆化
        Function2<BigInteger, Integer, BigInteger> memoized = pow.memoized();

        long start = System.currentTimeMillis();
        memoized.apply(BigInteger.valueOf(1024), 1024);
        long end1 = System.currentTimeMillis();

        memoized.apply(BigInteger.valueOf(1024), 1024);
        long end2 = System.currentTimeMillis();
        System.out.printf("%d ms -> %d ms", end1 - start, end2 - end1);
    }

    /**
     * java  8 中的optional  是类似 其目的都是为了避免NPE的出现
     */
    public static void optionTest() {
        //个人觉得option好用的地方在于这个of 静态函数。
        Option<String> str = Option.of("Hello");

        str.map(String::length);
        //使用对应的值
        Option<Integer> integers = str.flatMap(v -> Option.of(v.length()));
        boolean empty = integers.isEmpty();
        System.out.println(integers);
    }

    /**
     * either 的使用 包含两个值,left(异常值) 和 right(正确值)
     */
    public static void eitherAndTryTest() {

        //这个是
        Either<String, String> either =
            compute()
                .map(str -> str + " World")
                .mapLeft(Throwable::getMessage);
        System.out.println(either);

        //Try的使用,不用写过多的catch,左后将left值交给某一个函数统一处理,
        //在pdt中有很多这样的代码,try catch 嵌套起来使用 包含参数定义的参数校验异常
        //
        Fruit.fromColor("1111");


    }

    private static ThreadLocalRandom random = ThreadLocalRandom.current();

    private static Either<Throwable, String> compute() {
        return random.nextBoolean()
            ? Either.left(new RuntimeException("Boom!"))
            : Either.right("Hello");
    }

    @Getter
    public enum Fruit {

        APPLE("APPLE""BLACK"),
        BANANA("BANANA""BLUE"),

        NONE("ORANGE""WHITE");
        private final String name;
        private final String color;

        Fruit(String name, String color) {
            this.name = name;
            this.color = color;
        }

        public static Fruit fromColor(String color) {

            return Try.of(() -> Arrays.stream(Fruit.values())
                .filter(t -> t.getColor().equals(color))
                .findFirst().orElse(NONE))
                .toEither().getOrElse(NONE);
        }

    }


    /**
     * Lazy 表示的是一个延迟计算的值。在第一次访问时才会进行求值操作,而且该值只会计算一次。之后的访问操作获取的是缓存的值。Lazy.of 从接口 Supplier 中创建 Lazy 对象。方法 isEvaluated 可以判断 Lazy 对象是否已经被求值。
     */
    public static void LazyTest() {
        Lazy<BigInteger> lazy = Lazy.of(() ->
            BigInteger.valueOf(1024).pow(1024));

        System.out.println(lazy.isEvaluated());
        System.out.println(lazy.get());
        System.out.println(lazy.isEvaluated());
        System.out.println(lazy.get());
        System.out.println(lazy.isEvaluated());
        Lazy<BigInteger> lazy2 = Lazy.of(() ->
            BigInteger.valueOf(1024).pow(1024));
        System.out.println(lazy2.isEvaluated());
        System.out.println(lazy2.get());

        //未想到应用场景
    }


    public static void main(String[] args) {
        tupleTest();
        functionTest();
        curriedTest();
        memoized();
        LazyTest();
    }

}

————————————————

版权声明:本文为CSDN博主「Jeff、yuan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:

https://blog.csdn.net/weixin_40413961/article/details/115803185





粉丝福利:Java从入门到入土学习路线图

👇👇👇

👆长按上方微信二维码 2 秒


感谢点赞支持下哈 

浏览 40
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报