BigDecimal 的流式计算工具

460 阅读4分钟

前言

简单的数据连续计算

例如:在项目开发过程中,存在一个复杂,但是运算符简单的计算逻辑,并且存在多种数据类型时,使用BigDecimal来进行计算时,又需要一直创建。所以就产生了改工具类。对多种类型进行封装,使用建造者模式进行快速处理,达到代码简洁的效果。


一、依赖

本工具依赖 Hutool 工具包的NumberUtil,算的对其的一种扩展。 因为这个类只能实现单一的多个元素计算,无法实现链式的计算。

二、BigDecimalChain 说明

1.方法说明

方法名说明是否必须
chain构造链,并且初始化数据
add加法
sub减法
mul乘法
div除法
scale设置精度与小数位处理(四舍五入等)
get获取最终结果

代码中存在大量的方法重载,以满足不同的需求。可以根据具体业务,再自行扩展新的重载。

如果不需要 NumberUtil 的依赖,可以自行将其替换掉即可。

import cn.hutool.core.util.NumberUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 功能描述: BigDecimal的链式计算 <br/>
 * 依赖hutool 的 NumberUtil
 */
public class BigDecimalChain {

    /** 返回结果*/
    private BigDecimal result;

    private BigDecimalChain(BigDecimal result) {
        this.result = result;
    }

    /**
     * 功能描述: 构造链 <br/>
     */
    public static BigDecimalChain chain(BigDecimal bd) {
        return new BigDecimalChain(bd);
    }

    /**
     * 功能描述: 构造链 <br/>
     */
    public static BigDecimalChain chain(String bd) {
        isNumber(bd);
        return new BigDecimalChain(new BigDecimal(bd));
    }

    /**
     * 功能描述: 构造链 <br/>
     */
    public static BigDecimalChain chain(long bd) {
        return new BigDecimalChain(BigDecimal.valueOf(bd));
    }

    /**
     * 功能描述: 构造链 <br/>
     */
    public static BigDecimalChain chain(double bd) {
        return new BigDecimalChain(BigDecimal.valueOf(bd));
    }

    /** 加 */
    public BigDecimalChain add(BigDecimal v) {
        this.result = result.add(v);
        return this;
    }

    /** 加 */
    public BigDecimalChain add(String v) {
        isNumber(v);
        this.result = result.add(new BigDecimal(v));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(String... vs) {
        this.result = result.add(NumberUtil.add(vs));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(int v1) {
        this.result = result.add(new BigDecimal(Integer.toString(v1)));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(float v1) {
        this.result = result.add(new BigDecimal(Float.toString(v1)));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(double v1) {
        this.result = result.add(new BigDecimal(Double.toString(v1)));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(int v1, int v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(float v1, float v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(float v1, double v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(double v1, float v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(double v1, double v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Integer v1) {
        this.result = result.add(new BigDecimal(v1));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Float v1) {
        this.result = result.add(new BigDecimal(v1));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Double v1) {
        this.result = result.add(new BigDecimal(v1));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Float v1, Float v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Double v1, Double v2) {
        this.result = result.add(NumberUtil.add(new Number[]{v1, v2}));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Integer... vs) {
        this.result = result.add(NumberUtil.add(vs));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Float... vs) {
        this.result = result.add(NumberUtil.add(vs));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Double... vs) {
        this.result = result.add(NumberUtil.add(vs));
        return this;
    }

    /** 加 */
    public BigDecimalChain add(Number... vs) {
        this.result = result.add(NumberUtil.add(vs));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(BigDecimal v) {
        this.result = result.subtract(v);
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(String v) {
        isNumber(v);
        this.result = result.subtract(new BigDecimal(v));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(int v) {
        this.result = result.subtract(new BigDecimal(Integer.toString(v)));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(float v) {
        this.result = result.subtract(new BigDecimal(Float.toString(v)));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(double v) {
        this.result = result.subtract(new BigDecimal(Double.toString(v)));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(Integer v) {
        this.result = result.subtract(new BigDecimal(v));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(Float v) {
        this.result = result.subtract(new BigDecimal(v));
        return this;
    }

    /** 减 */
    public BigDecimalChain sub(Double v) {
        this.result = result.subtract(new BigDecimal(v));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(BigDecimal v) {
        this.result = result.multiply(v);
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(String v) {
        isNumber(v);
        this.result = result.multiply(new BigDecimal(v));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(int v) {
        this.result = result.multiply(new BigDecimal(Integer.toString(v)));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(float v) {
        this.result = result.multiply(new BigDecimal(Float.toString(v)));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(double v) {
        this.result = result.multiply(new BigDecimal(Double.toString(v)));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(Integer v) {
        this.result = result.multiply(new BigDecimal(v));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(Float v) {
        this.result = result.multiply(new BigDecimal(v));
        return this;
    }

    /** 乘 */
    public BigDecimalChain mul(Double v) {
        this.result = result.multiply(new BigDecimal(v));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(BigDecimal v) {
        this.result = result.divide(v);
        return this;
    }

    /** 除 */
    public BigDecimalChain div(String v) {
        isNumber(v);
        this.result = result.divide(new BigDecimal(v));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(int v) {
        this.result = result.divide(new BigDecimal(Integer.toString(v)));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(float v) {
        this.result = result.divide(new BigDecimal(Float.toString(v)));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(double v) {
        this.result = result.divide(new BigDecimal(Double.toString(v)));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(Integer v) {
        this.result = result.divide(new BigDecimal(v));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(Float v) {
        this.result = result.divide(new BigDecimal(v));
        return this;
    }

    /** 除 */
    public BigDecimalChain div(Double v) {
        this.result = result.divide(new BigDecimal(v));
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(BigDecimal v, int scale) {
        this.result = result.divide(v, scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(String v, int scale) {
        isNumber(v);
        this.result = result.divide(new BigDecimal(v), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(int v, int scale) {
        this.result = result.divide(new BigDecimal(Integer.toString(v)), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(float v, int scale) {
        this.result = result.divide(new BigDecimal(Float.toString(v)), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(double v, int scale) {
        this.result = result.divide(new BigDecimal(Double.toString(v)), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(Integer v, int scale) {
        this.result = result.divide(new BigDecimal(v), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(Float v, int scale) {
        this.result = result.divide(new BigDecimal(v), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 四舍五入 */
    public BigDecimalChain div(Double v, int scale) {
        this.result = result.divide(new BigDecimal(v), scale, RoundingMode.HALF_UP);
        return this;
    }

    /** 除 带精度 保留小数模式 */
    public BigDecimalChain div(BigDecimal div, int scale, RoundingMode roundingMode) {
        this.result = result.divide(div, scale, roundingMode);
        return this;
    }

    /** 精度 */
    public BigDecimalChain scale(int scale) {
        this.result = result.setScale(scale);
        return this;
    }

    /**
     * 精度 保留小数模式
     */
    public BigDecimalChain scale(int scale, RoundingMode roundingMode) {
        this.result = result.setScale(scale, roundingMode);
        return this;
    }

    /** 获取最终结果 */
    public BigDecimal get() {
        return result;
    }

    /** 判断是否数字 */
    private static void isNumber(String v) {
            if(!NumberUtil.isNumber(v)) {
            throw new NumberFormatException("非数字入参,请输入有效的数字");
        }
    }

}

2.测试

代码如下(示例):

import java.math.BigDecimal;
import java.math.RoundingMode;

public class BigDecimalChainTest {
    public static void main(String[] args) {
        BigDecimal build = BigDecimalChain
                .chain(new BigDecimal("2"))
                .add(new BigDecimal("3"))
                .add("3", "4")
                .sub(5)
                .mul(2.2F)
                // 存在问题,如果除不尽,再除以相同的数,会出现精度错误问题。有待优化
                .div(4.1D, 5)
                .mul(4.1D)
                .scale(6)
                .scale(2, RoundingMode.HALF_UP)
                .get();
        System.out.println(build);
    }
}

总结

在开发过程中,一个小小的工具类,也是自己辛苦发现的结晶。


感谢关注(微信小程序)

柒宅mini二维码.jpg

代码地址

自己收集的小工具项目,环境star

BigDecimalChain